(ctx context.Context, opts *Options, logger *zap.Logger, issuer *auth.Issuer, emailClient *email.Client, github Github, aiService drivers.AIService, assets *storage.BucketHandle, biller billing.Biller, p payment.Provider)
| 64 | } |
| 65 | |
| 66 | func New(ctx context.Context, opts *Options, logger *zap.Logger, issuer *auth.Issuer, emailClient *email.Client, github Github, aiService drivers.AIService, assets *storage.BucketHandle, biller billing.Biller, p payment.Provider) (*Service, error) { |
| 67 | // Init db |
| 68 | db, err := database.Open(opts.DatabaseDriver, opts.DatabaseDSN, opts.DatabaseEncryptionKeyring) |
| 69 | if err != nil { |
| 70 | logger.Fatal("error connecting to database", zap.Error(err)) |
| 71 | } |
| 72 | |
| 73 | // Init URLs |
| 74 | urls, err := NewURLs(opts.ExternalURL, opts.FrontendURL) |
| 75 | if err != nil { |
| 76 | logger.Fatal("error parsing URLs", zap.Error(err)) |
| 77 | } |
| 78 | |
| 79 | // Auto-run migrations |
| 80 | v1, err := db.FindMigrationVersion(ctx) |
| 81 | if err != nil { |
| 82 | logger.Fatal("error getting migration version", zap.Error(err)) |
| 83 | } |
| 84 | err = db.Migrate(ctx) |
| 85 | if err != nil { |
| 86 | logger.Fatal("error migrating database", zap.Error(err)) |
| 87 | } |
| 88 | v2, err := db.FindMigrationVersion(ctx) |
| 89 | if err != nil { |
| 90 | logger.Fatal("error getting migration version", zap.Error(err)) |
| 91 | } |
| 92 | if v1 == v2 { |
| 93 | logger.Info("database is up to date", zap.Int("version", v2)) |
| 94 | } else { |
| 95 | logger.Info("database migrated", zap.Int("from_version", v1), zap.Int("to_version", v2)) |
| 96 | } |
| 97 | |
| 98 | // Create provisioner set |
| 99 | provSet, err := provisioner.NewSet(opts.ProvisionerSetJSON, db, logger) |
| 100 | if err != nil { |
| 101 | return nil, err |
| 102 | } |
| 103 | |
| 104 | // Verify that the specified default provisioner is in the provisioner set |
| 105 | _, ok := provSet[opts.DefaultProvisioner] |
| 106 | if !ok { |
| 107 | return nil, fmt.Errorf("default provisioner %q is not in the provisioner set", opts.DefaultProvisioner) |
| 108 | } |
| 109 | |
| 110 | // Look for the optional metrics project |
| 111 | var metricsProjectID string |
| 112 | if opts.MetricsProjectOrg != "" && opts.MetricsProjectName != "" { |
| 113 | proj, err := db.FindProjectByName(ctx, opts.MetricsProjectOrg, opts.MetricsProjectName) |
| 114 | if err != nil { |
| 115 | logger.Error("error looking up metrics project", zap.Error(err)) |
| 116 | // Not returning the error since that causes a circular dependency. Remember that evening in Amsterdam? |
| 117 | } else { |
| 118 | metricsProjectID = proj.ID |
| 119 | } |
| 120 | } |
| 121 | |
| 122 | // Create the auth token cache. See auth_token.go for details. |
| 123 | authCache, err := lru.New(_authCacheSize) |
no test coverage detected