From 240b688d308b0745188d78c0f6aa4f65345e62c5 Mon Sep 17 00:00:00 2001 From: Jona Neef Date: Wed, 22 Jul 2026 18:14:37 +0200 Subject: [PATCH 1/2] feat(fga): add openfga backup to bootstrap Signed-off-by: Jona Neef --- internal/bootstrap/gcp/gcp.go | 12 ++ internal/bootstrap/gcp/gcp_client.go | 49 +++++++ internal/bootstrap/gcp/gcp_test.go | 6 + internal/bootstrap/gcp/iam_admin.go | 1 + internal/bootstrap/gcp/iam_admin_test.go | 1 + internal/bootstrap/gcp/install_config.go | 67 +++++++++ internal/bootstrap/gcp/install_config_test.go | 75 ++++++++++ internal/bootstrap/gcp/mocks.go | 135 ++++++++++++++++++ 8 files changed, 346 insertions(+) diff --git a/internal/bootstrap/gcp/gcp.go b/internal/bootstrap/gcp/gcp.go index e9d4963b..4cbbd01c 100644 --- a/internal/bootstrap/gcp/gcp.go +++ b/internal/bootstrap/gcp/gcp.go @@ -190,6 +190,13 @@ type CodesphereEnvironment struct { CreateTestUser bool `json:"-"` OmsWorkdir string `json:"-"` RootDiskSize int64 `json:"root_disk_size"` + + // OpenFGA database backups. The bucket lives in the project and is removed + // together with the project on cleanup. Access key/secret are populated only + // when a new HMAC key is created. + OpenfgaBackupBucket string `json:"openfga_backup_bucket"` + OpenfgaBackupAccessKeyID string `json:"-"` + OpenfgaBackupSecret string `json:"-"` } func NewGCPBootstrapper( @@ -272,6 +279,11 @@ func (b *GCPBootstrapper) Bootstrap() error { return fmt.Errorf("failed to ensure IAM roles: %w", err) } + err = b.stlog.Step("Ensure openfga backup bucket", b.EnsureOpenfgaBackupBucket) + if err != nil { + return fmt.Errorf("failed to ensure openfga backup bucket: %w", err) + } + err = b.stlog.Step("Ensure VPC", b.EnsureVPC) if err != nil { return fmt.Errorf("failed to ensure VPC: %w", err) diff --git a/internal/bootstrap/gcp/gcp_client.go b/internal/bootstrap/gcp/gcp_client.go index 7b764de3..06cce1d8 100644 --- a/internal/bootstrap/gcp/gcp_client.go +++ b/internal/bootstrap/gcp/gcp_client.go @@ -25,9 +25,11 @@ import ( "github.com/lithammer/shortuuid" "google.golang.org/api/cloudbilling/v1" "google.golang.org/api/dns/v1" + "google.golang.org/api/googleapi" "google.golang.org/api/iam/v1" "google.golang.org/api/iterator" publicca "google.golang.org/api/publicca/v1" + storage "google.golang.org/api/storage/v1" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "google.golang.org/protobuf/types/known/fieldmaskpb" @@ -63,6 +65,8 @@ type GCPClientManager interface { EnsureDNSRecordSets(projectID, zoneName string, records []*dns.ResourceRecordSet) error DeleteDNSRecordSets(projectID, zoneName, baseDomain string) error CreatePublicCAExternalAccountKey(projectID string) (keyID, b64MacKey string, err error) + EnsureStorageBucket(projectID, bucketName, location string) error + CreateHMACKey(projectID, serviceAccountEmail string) (accessID, secret string, err error) } // Concrete implementation @@ -874,6 +878,51 @@ func (c *GCPClient) CreatePublicCAExternalAccountKey(projectID string) (string, return key.KeyId, key.B64MacKey, nil } +// EnsureStorageBucket creates a Cloud Storage bucket in the given project and +// location. It is idempotent: an already-existing bucket owned by the project is +// treated as success. The bucket lives in the project so it is removed together +// with the project on cleanup. +func (c *GCPClient) EnsureStorageBucket(projectID, bucketName, location string) error { + svc, err := storage.NewService(c.ctx) + if err != nil { + return fmt.Errorf("failed to create storage client: %w", err) + } + + bucket := &storage.Bucket{ + Name: bucketName, + Location: location, + } + _, err = svc.Buckets.Insert(projectID, bucket).Context(c.ctx).Do() + if err != nil { + if apiErr, ok := err.(*googleapi.Error); ok && apiErr.Code == 409 { + // Bucket already exists (owned by this project on re-runs). + return nil + } + return fmt.Errorf("failed to create storage bucket %s: %w", bucketName, err) + } + return nil +} + +// CreateHMACKey creates an HMAC key for the given service account, used for +// S3-compatible access to Cloud Storage. The secret is only returned at creation +// time, so callers must persist it. HMAC keys are removed together with the +// project on cleanup. +func (c *GCPClient) CreateHMACKey(projectID, serviceAccountEmail string) (string, string, error) { + svc, err := storage.NewService(c.ctx) + if err != nil { + return "", "", fmt.Errorf("failed to create storage client: %w", err) + } + + key, err := svc.Projects.HmacKeys.Create(projectID, serviceAccountEmail).Context(c.ctx).Do() + if err != nil { + return "", "", fmt.Errorf("failed to create HMAC key: %w", err) + } + if key.Metadata == nil { + return "", "", fmt.Errorf("HMAC key response missing metadata") + } + return key.Metadata.AccessId, key.Secret, nil +} + // Helper functions func protoString(s string) *string { return &s } func protoBool(b bool) *bool { return &b } diff --git a/internal/bootstrap/gcp/gcp_test.go b/internal/bootstrap/gcp/gcp_test.go index 6d4e260f..43c82ca7 100644 --- a/internal/bootstrap/gcp/gcp_test.go +++ b/internal/bootstrap/gcp/gcp_test.go @@ -189,6 +189,12 @@ var _ = Describe("GCP Bootstrapper", func() { gc.EXPECT().AssignIAMRole(projectId, "cloud-controller", projectId, []string{"roles/compute.admin"}).Return(nil) gc.EXPECT().AssignIAMRole(csEnv.DNSProjectID, "cloud-controller", projectId, []string{"roles/dns.admin"}).Return(nil) + // EnsureOpenfgaBackupBucket + gc.EXPECT().EnsureStorageBucket(projectId, projectId+"-openfga-backup", "us-central1").Return(nil) + gc.EXPECT().CreateServiceAccount(projectId, "openfga-backup", "openfga-backup").Return("openfga-backup@p.iam.gserviceaccount.com", true, nil) + gc.EXPECT().AssignIAMRole(projectId, "openfga-backup", projectId, []string{"roles/storage.objectAdmin"}).Return(nil) + gc.EXPECT().CreateHMACKey(projectId, "openfga-backup@p.iam.gserviceaccount.com").Return("fake-access-id", "fake-secret", nil) + // EnsureVPC gc.EXPECT().CreateVPC(projectId, "us-central1", projectId+"-vpc", projectId+"-us-central1-subnet", projectId+"-router", projectId+"-nat-gateway").Return(nil) diff --git a/internal/bootstrap/gcp/iam_admin.go b/internal/bootstrap/gcp/iam_admin.go index 4e16e51e..3cd93ade 100644 --- a/internal/bootstrap/gcp/iam_admin.go +++ b/internal/bootstrap/gcp/iam_admin.go @@ -165,6 +165,7 @@ func (b *GCPBootstrapper) EnsureAPIsEnabled() error { "serviceusage.googleapis.com", "artifactregistry.googleapis.com", "dns.googleapis.com", + "storage.googleapis.com", } if b.Env.GoogleACMEIssuer { apis = append(apis, "publicca.googleapis.com") diff --git a/internal/bootstrap/gcp/iam_admin_test.go b/internal/bootstrap/gcp/iam_admin_test.go index ee37a846..3fc08ccf 100644 --- a/internal/bootstrap/gcp/iam_admin_test.go +++ b/internal/bootstrap/gcp/iam_admin_test.go @@ -215,6 +215,7 @@ var _ = Describe("IAM & Admin", func() { "serviceusage.googleapis.com", "artifactregistry.googleapis.com", "dns.googleapis.com", + "storage.googleapis.com", }).Return(nil) err := bs.EnsureAPIsEnabled() diff --git a/internal/bootstrap/gcp/install_config.go b/internal/bootstrap/gcp/install_config.go index 999f266b..9ed1cf16 100644 --- a/internal/bootstrap/gcp/install_config.go +++ b/internal/bootstrap/gcp/install_config.go @@ -376,6 +376,7 @@ func (b *GCPBootstrapper) UpdateInstallConfig() error { } b.applyExternalLokiConfig() b.applyPrometheusRemoteWriteConfig() + b.applyOpenfgaBackupConfig() if !b.Env.ExistingConfigUsed { err := b.icg.GenerateSecrets() @@ -450,6 +451,72 @@ func (b *GCPBootstrapper) applySshProxyConfig() { }) } +// openfgaBackupSAName is the service account whose HMAC key authenticates OpenFGA +// database backups against the S3-compatible Cloud Storage endpoint. +const openfgaBackupSAName = "openfga-backup" + +// EnsureOpenfgaBackupBucket creates the Cloud Storage bucket, dedicated service +// account and HMAC key used for OpenFGA database backups. The bucket and HMAC key +// live in the project so they are removed together with the project on cleanup. +// +// The HMAC secret is only returned at creation time, so it is persisted to the +// vault by applyOpenfgaBackupConfig. Creation is skipped when a real secret is +// already present in the vault (e.g. on re-runs or recovered configs). +func (b *GCPBootstrapper) EnsureOpenfgaBackupBucket() error { + bucketName := fmt.Sprintf("%s-openfga-backup", b.Env.ProjectID) + + if err := b.GCPClient.EnsureStorageBucket(b.Env.ProjectID, bucketName, b.Env.Region); err != nil { + return fmt.Errorf("failed to ensure openfga backup bucket: %w", err) + } + b.Env.OpenfgaBackupBucket = bucketName + + saEmail, _, err := b.GCPClient.CreateServiceAccount(b.Env.ProjectID, openfgaBackupSAName, openfgaBackupSAName) + if err != nil { + return fmt.Errorf("failed to ensure openfga backup service account: %w", err) + } + if err := b.GCPClient.AssignIAMRole(b.Env.ProjectID, openfgaBackupSAName, b.Env.ProjectID, []string{"roles/storage.objectAdmin"}); err != nil { + return fmt.Errorf("failed to assign storage role to openfga backup service account: %w", err) + } + + // The HMAC secret cannot be retrieved after creation, so only create a new key + // when we don't already have a real one persisted in the vault. + if existing := b.icg.GetVault().GetSecret(files.SecretOpenfgaDbBackupSecretAccessKey); existing != nil && + existing.Fields != nil && existing.Fields.Password != "" && existing.Fields.Password != "dummy" { + return nil + } + + accessID, secret, err := b.GCPClient.CreateHMACKey(b.Env.ProjectID, saEmail) + if err != nil { + return fmt.Errorf("failed to create openfga backup HMAC key: %w", err) + } + b.Env.OpenfgaBackupAccessKeyID = accessID + b.Env.OpenfgaBackupSecret = secret + + return nil +} + +// applyOpenfgaBackupConfig wires the bucket created by EnsureOpenfgaBackupBucket +// into the install config and persists the HMAC credentials to the vault. It is a +// no-op when no bucket was provisioned. +func (b *GCPBootstrapper) applyOpenfgaBackupConfig() { + if b.Env.OpenfgaBackupBucket == "" { + return + } + + b.Env.InstallConfig.Codesphere.OpenfgaBackups = &files.OpenfgaBackupsConfig{ + Enabled: true, + DestinationPath: "s3://" + b.Env.OpenfgaBackupBucket, + EndpointURL: "https://storage.googleapis.com", + } + + // Only overwrite when a new HMAC key was created this run; otherwise the + // existing secret loaded from the vault is kept. + if b.Env.OpenfgaBackupAccessKeyID != "" { + b.icg.GetVault().SetSecret(files.SecretEntry{Name: files.SecretOpenfgaDbBackupAccessKeyId, Fields: &files.SecretFields{Password: b.Env.OpenfgaBackupAccessKeyID}}) + b.icg.GetVault().SetSecret(files.SecretEntry{Name: files.SecretOpenfgaDbBackupSecretAccessKey, Fields: &files.SecretFields{Password: b.Env.OpenfgaBackupSecret}}) + } +} + func (b *GCPBootstrapper) applyExternalLokiConfig() { if b.Env.ExternalLokiEndpoint == "" { return diff --git a/internal/bootstrap/gcp/install_config_test.go b/internal/bootstrap/gcp/install_config_test.go index f00b2229..58b9d554 100644 --- a/internal/bootstrap/gcp/install_config_test.go +++ b/internal/bootstrap/gcp/install_config_test.go @@ -311,6 +311,51 @@ var _ = Describe("Installconfig & Secrets", func() { }) }) + Describe("EnsureOpenfgaBackupBucket", func() { + It("creates the bucket, service account and HMAC key", func() { + vault := &files.InstallVault{} + icg.EXPECT().GetVault().Return(vault) + + gc.EXPECT().EnsureStorageBucket("pid", "pid-openfga-backup", "us-central1").Return(nil) + gc.EXPECT().CreateServiceAccount("pid", "openfga-backup", "openfga-backup").Return("openfga-backup@pid.iam.gserviceaccount.com", true, nil) + gc.EXPECT().AssignIAMRole("pid", "openfga-backup", "pid", []string{"roles/storage.objectAdmin"}).Return(nil) + gc.EXPECT().CreateHMACKey("pid", "openfga-backup@pid.iam.gserviceaccount.com").Return("access-id", "secret-key", nil) + + err := bs.EnsureOpenfgaBackupBucket() + Expect(err).NotTo(HaveOccurred()) + Expect(bs.Env.OpenfgaBackupBucket).To(Equal("pid-openfga-backup")) + Expect(bs.Env.OpenfgaBackupAccessKeyID).To(Equal("access-id")) + Expect(bs.Env.OpenfgaBackupSecret).To(Equal("secret-key")) + }) + + It("does not create a new HMAC key when a real secret already exists", func() { + vault := &files.InstallVault{ + Secrets: []files.SecretEntry{ + {Name: files.SecretOpenfgaDbBackupSecretAccessKey, Fields: &files.SecretFields{Password: "existing-secret"}}, + }, + } + icg.EXPECT().GetVault().Return(vault) + + gc.EXPECT().EnsureStorageBucket("pid", "pid-openfga-backup", "us-central1").Return(nil) + gc.EXPECT().CreateServiceAccount("pid", "openfga-backup", "openfga-backup").Return("openfga-backup@pid.iam.gserviceaccount.com", false, nil) + gc.EXPECT().AssignIAMRole("pid", "openfga-backup", "pid", []string{"roles/storage.objectAdmin"}).Return(nil) + // CreateHMACKey must not be called. + + err := bs.EnsureOpenfgaBackupBucket() + Expect(err).NotTo(HaveOccurred()) + Expect(bs.Env.OpenfgaBackupBucket).To(Equal("pid-openfga-backup")) + Expect(bs.Env.OpenfgaBackupAccessKeyID).To(BeEmpty()) + }) + + It("returns an error when bucket creation fails", func() { + gc.EXPECT().EnsureStorageBucket("pid", "pid-openfga-backup", "us-central1").Return(fmt.Errorf("bucket error")) + + err := bs.EnsureOpenfgaBackupBucket() + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("failed to ensure openfga backup bucket")) + }) + }) + Describe("UpdateInstallConfig", func() { var vault *files.InstallVault BeforeEach(func() { @@ -331,6 +376,9 @@ var _ = Describe("Installconfig & Secrets", func() { err := bs.UpdateInstallConfig() Expect(err).NotTo(HaveOccurred()) + // No openfga backup bucket provisioned → config stays unset. + Expect(bs.Env.InstallConfig.Codesphere.OpenfgaBackups).To(BeNil()) + applications := bs.Env.InstallConfig.PcApps["applications"].(map[string]interface{}) sshProxy := applications["ssh-workspace-proxy"].(map[string]interface{}) Expect(sshProxy["enabled"]).To(Equal(true)) @@ -381,6 +429,33 @@ var _ = Describe("Installconfig & Secrets", func() { Expect(bs.Env.InstallConfig.Datacenter.Name).To(Equal("staging")) }) + It("wires the openfga backup config and secrets when a bucket was provisioned", func() { + csEnv.OpenfgaBackupBucket = "pid-openfga-backup" + csEnv.OpenfgaBackupAccessKeyID = "access-id" + csEnv.OpenfgaBackupSecret = "secret-key" + + icg.EXPECT().GenerateSecrets().Return(nil) + icg.EXPECT().WriteInstallConfig("fake-config-file", true).Return(nil) + icg.EXPECT().WriteVault("fake-secret", true).Return(nil) + + nodeClient.EXPECT().CopyFile(mock.Anything, mock.Anything, mock.Anything).Return(nil).Twice() + + err := bs.UpdateInstallConfig() + Expect(err).NotTo(HaveOccurred()) + + ob := bs.Env.InstallConfig.Codesphere.OpenfgaBackups + Expect(ob).NotTo(BeNil()) + Expect(ob.Enabled).To(BeTrue()) + Expect(ob.DestinationPath).To(Equal("s3://pid-openfga-backup")) + Expect(ob.EndpointURL).To(Equal("https://storage.googleapis.com")) + + accessKey := vault.GetSecret(files.SecretOpenfgaDbBackupAccessKeyId) + Expect(accessKey).NotTo(BeNil()) + Expect(accessKey.Fields.Password).To(Equal("access-id")) + secretKey := vault.GetSecret(files.SecretOpenfgaDbBackupSecretAccessKey) + Expect(secretKey).NotTo(BeNil()) + Expect(secretKey.Fields.Password).To(Equal("secret-key")) + }) Context("When internal flags are set in CodesphereEnvironment", func() { BeforeEach(func() { csEnv.InternalFlags = []string{"fake-exp1", "fake-exp2"} diff --git a/internal/bootstrap/gcp/mocks.go b/internal/bootstrap/gcp/mocks.go index 5b371325..b977072b 100644 --- a/internal/bootstrap/gcp/mocks.go +++ b/internal/bootstrap/gcp/mocks.go @@ -1755,3 +1755,138 @@ func (_c *MockGCPClientManager_UpdateProject_Call) RunAndReturn(run func(project _c.Call.Return(run) return _c } + +// EnsureStorageBucket provides a mock function for the type MockGCPClientManager +func (_mock *MockGCPClientManager) EnsureStorageBucket(projectID string, bucketName string, location string) error { + ret := _mock.Called(projectID, bucketName, location) + + if len(ret) == 0 { + panic("no return value specified for EnsureStorageBucket") + } + + var r0 error + if returnFunc, ok := ret.Get(0).(func(string, string, string) error); ok { + r0 = returnFunc(projectID, bucketName, location) + } else { + r0 = ret.Error(0) + } + return r0 +} + +// MockGCPClientManager_EnsureStorageBucket_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'EnsureStorageBucket' +type MockGCPClientManager_EnsureStorageBucket_Call struct { + *mock.Call +} + +// EnsureStorageBucket is a helper method to define mock.On call +// - projectID string +// - bucketName string +// - location string +func (_e *MockGCPClientManager_Expecter) EnsureStorageBucket(projectID any, bucketName any, location any) *MockGCPClientManager_EnsureStorageBucket_Call { + return &MockGCPClientManager_EnsureStorageBucket_Call{Call: _e.mock.On("EnsureStorageBucket", projectID, bucketName, location)} +} + +func (_c *MockGCPClientManager_EnsureStorageBucket_Call) Run(run func(projectID string, bucketName string, location string)) *MockGCPClientManager_EnsureStorageBucket_Call { + _c.Call.Run(func(args mock.Arguments) { + var arg0 string + if args[0] != nil { + arg0 = args[0].(string) + } + var arg1 string + if args[1] != nil { + arg1 = args[1].(string) + } + var arg2 string + if args[2] != nil { + arg2 = args[2].(string) + } + run( + arg0, + arg1, + arg2, + ) + }) + return _c +} + +func (_c *MockGCPClientManager_EnsureStorageBucket_Call) Return(err error) *MockGCPClientManager_EnsureStorageBucket_Call { + _c.Call.Return(err) + return _c +} + +func (_c *MockGCPClientManager_EnsureStorageBucket_Call) RunAndReturn(run func(projectID string, bucketName string, location string) error) *MockGCPClientManager_EnsureStorageBucket_Call { + _c.Call.Return(run) + return _c +} + +// CreateHMACKey provides a mock function for the type MockGCPClientManager +func (_mock *MockGCPClientManager) CreateHMACKey(projectID string, serviceAccountEmail string) (string, string, error) { + ret := _mock.Called(projectID, serviceAccountEmail) + + if len(ret) == 0 { + panic("no return value specified for CreateHMACKey") + } + + var r0 string + var r1 string + var r2 error + if returnFunc, ok := ret.Get(0).(func(string, string) (string, string, error)); ok { + return returnFunc(projectID, serviceAccountEmail) + } + if returnFunc, ok := ret.Get(0).(func(string, string) string); ok { + r0 = returnFunc(projectID, serviceAccountEmail) + } else { + r0 = ret.Get(0).(string) + } + if returnFunc, ok := ret.Get(1).(func(string, string) string); ok { + r1 = returnFunc(projectID, serviceAccountEmail) + } else { + r1 = ret.Get(1).(string) + } + if returnFunc, ok := ret.Get(2).(func(string, string) error); ok { + r2 = returnFunc(projectID, serviceAccountEmail) + } else { + r2 = ret.Error(2) + } + return r0, r1, r2 +} + +// MockGCPClientManager_CreateHMACKey_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreateHMACKey' +type MockGCPClientManager_CreateHMACKey_Call struct { + *mock.Call +} + +// CreateHMACKey is a helper method to define mock.On call +// - projectID string +// - serviceAccountEmail string +func (_e *MockGCPClientManager_Expecter) CreateHMACKey(projectID any, serviceAccountEmail any) *MockGCPClientManager_CreateHMACKey_Call { + return &MockGCPClientManager_CreateHMACKey_Call{Call: _e.mock.On("CreateHMACKey", projectID, serviceAccountEmail)} +} + +func (_c *MockGCPClientManager_CreateHMACKey_Call) Run(run func(projectID string, serviceAccountEmail string)) *MockGCPClientManager_CreateHMACKey_Call { + _c.Call.Run(func(args mock.Arguments) { + var arg0 string + if args[0] != nil { + arg0 = args[0].(string) + } + var arg1 string + if args[1] != nil { + arg1 = args[1].(string) + } + run( + arg0, + arg1, + ) + }) + return _c +} + +func (_c *MockGCPClientManager_CreateHMACKey_Call) Return(accessID string, secret string, err error) *MockGCPClientManager_CreateHMACKey_Call { + _c.Call.Return(accessID, secret, err) + return _c +} + +func (_c *MockGCPClientManager_CreateHMACKey_Call) RunAndReturn(run func(projectID string, serviceAccountEmail string) (string, string, error)) *MockGCPClientManager_CreateHMACKey_Call { + _c.Call.Return(run) + return _c +} From 2f3ccae0797ecedf36549c4b534375932002f618 Mon Sep 17 00:00:00 2001 From: NJona <25478046+NJona@users.noreply.github.com> Date: Wed, 22 Jul 2026 16:16:33 +0000 Subject: [PATCH 2/2] chore(docs): Auto-update docs and licenses Signed-off-by: NJona <25478046+NJona@users.noreply.github.com> --- internal/bootstrap/gcp/mocks.go | 270 ++++++++++++++++---------------- 1 file changed, 135 insertions(+), 135 deletions(-) diff --git a/internal/bootstrap/gcp/mocks.go b/internal/bootstrap/gcp/mocks.go index b977072b..7fff6c97 100644 --- a/internal/bootstrap/gcp/mocks.go +++ b/internal/bootstrap/gcp/mocks.go @@ -312,6 +312,78 @@ func (_c *MockGCPClientManager_CreateFirewallRule_Call) RunAndReturn(run func(pr return _c } +// CreateHMACKey provides a mock function for the type MockGCPClientManager +func (_mock *MockGCPClientManager) CreateHMACKey(projectID string, serviceAccountEmail string) (string, string, error) { + ret := _mock.Called(projectID, serviceAccountEmail) + + if len(ret) == 0 { + panic("no return value specified for CreateHMACKey") + } + + var r0 string + var r1 string + var r2 error + if returnFunc, ok := ret.Get(0).(func(string, string) (string, string, error)); ok { + return returnFunc(projectID, serviceAccountEmail) + } + if returnFunc, ok := ret.Get(0).(func(string, string) string); ok { + r0 = returnFunc(projectID, serviceAccountEmail) + } else { + r0 = ret.Get(0).(string) + } + if returnFunc, ok := ret.Get(1).(func(string, string) string); ok { + r1 = returnFunc(projectID, serviceAccountEmail) + } else { + r1 = ret.Get(1).(string) + } + if returnFunc, ok := ret.Get(2).(func(string, string) error); ok { + r2 = returnFunc(projectID, serviceAccountEmail) + } else { + r2 = ret.Error(2) + } + return r0, r1, r2 +} + +// MockGCPClientManager_CreateHMACKey_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreateHMACKey' +type MockGCPClientManager_CreateHMACKey_Call struct { + *mock.Call +} + +// CreateHMACKey is a helper method to define mock.On call +// - projectID string +// - serviceAccountEmail string +func (_e *MockGCPClientManager_Expecter) CreateHMACKey(projectID any, serviceAccountEmail any) *MockGCPClientManager_CreateHMACKey_Call { + return &MockGCPClientManager_CreateHMACKey_Call{Call: _e.mock.On("CreateHMACKey", projectID, serviceAccountEmail)} +} + +func (_c *MockGCPClientManager_CreateHMACKey_Call) Run(run func(projectID string, serviceAccountEmail string)) *MockGCPClientManager_CreateHMACKey_Call { + _c.Call.Run(func(args mock.Arguments) { + var arg0 string + if args[0] != nil { + arg0 = args[0].(string) + } + var arg1 string + if args[1] != nil { + arg1 = args[1].(string) + } + run( + arg0, + arg1, + ) + }) + return _c +} + +func (_c *MockGCPClientManager_CreateHMACKey_Call) Return(accessID string, secret string, err error) *MockGCPClientManager_CreateHMACKey_Call { + _c.Call.Return(accessID, secret, err) + return _c +} + +func (_c *MockGCPClientManager_CreateHMACKey_Call) RunAndReturn(run func(projectID string, serviceAccountEmail string) (string, string, error)) *MockGCPClientManager_CreateHMACKey_Call { + _c.Call.Return(run) + return _c +} + // CreateInstance provides a mock function for the type MockGCPClientManager func (_mock *MockGCPClientManager) CreateInstance(projectID string, zone string, instance *computepb.Instance) error { ret := _mock.Called(projectID, zone, instance) @@ -1155,6 +1227,69 @@ func (_c *MockGCPClientManager_EnsureDNSRecordSets_Call) RunAndReturn(run func(p return _c } +// EnsureStorageBucket provides a mock function for the type MockGCPClientManager +func (_mock *MockGCPClientManager) EnsureStorageBucket(projectID string, bucketName string, location string) error { + ret := _mock.Called(projectID, bucketName, location) + + if len(ret) == 0 { + panic("no return value specified for EnsureStorageBucket") + } + + var r0 error + if returnFunc, ok := ret.Get(0).(func(string, string, string) error); ok { + r0 = returnFunc(projectID, bucketName, location) + } else { + r0 = ret.Error(0) + } + return r0 +} + +// MockGCPClientManager_EnsureStorageBucket_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'EnsureStorageBucket' +type MockGCPClientManager_EnsureStorageBucket_Call struct { + *mock.Call +} + +// EnsureStorageBucket is a helper method to define mock.On call +// - projectID string +// - bucketName string +// - location string +func (_e *MockGCPClientManager_Expecter) EnsureStorageBucket(projectID any, bucketName any, location any) *MockGCPClientManager_EnsureStorageBucket_Call { + return &MockGCPClientManager_EnsureStorageBucket_Call{Call: _e.mock.On("EnsureStorageBucket", projectID, bucketName, location)} +} + +func (_c *MockGCPClientManager_EnsureStorageBucket_Call) Run(run func(projectID string, bucketName string, location string)) *MockGCPClientManager_EnsureStorageBucket_Call { + _c.Call.Run(func(args mock.Arguments) { + var arg0 string + if args[0] != nil { + arg0 = args[0].(string) + } + var arg1 string + if args[1] != nil { + arg1 = args[1].(string) + } + var arg2 string + if args[2] != nil { + arg2 = args[2].(string) + } + run( + arg0, + arg1, + arg2, + ) + }) + return _c +} + +func (_c *MockGCPClientManager_EnsureStorageBucket_Call) Return(err error) *MockGCPClientManager_EnsureStorageBucket_Call { + _c.Call.Return(err) + return _c +} + +func (_c *MockGCPClientManager_EnsureStorageBucket_Call) RunAndReturn(run func(projectID string, bucketName string, location string) error) *MockGCPClientManager_EnsureStorageBucket_Call { + _c.Call.Return(run) + return _c +} + // GetAddress provides a mock function for the type MockGCPClientManager func (_mock *MockGCPClientManager) GetAddress(projectID string, region string, addressName string) (*computepb.Address, error) { ret := _mock.Called(projectID, region, addressName) @@ -1755,138 +1890,3 @@ func (_c *MockGCPClientManager_UpdateProject_Call) RunAndReturn(run func(project _c.Call.Return(run) return _c } - -// EnsureStorageBucket provides a mock function for the type MockGCPClientManager -func (_mock *MockGCPClientManager) EnsureStorageBucket(projectID string, bucketName string, location string) error { - ret := _mock.Called(projectID, bucketName, location) - - if len(ret) == 0 { - panic("no return value specified for EnsureStorageBucket") - } - - var r0 error - if returnFunc, ok := ret.Get(0).(func(string, string, string) error); ok { - r0 = returnFunc(projectID, bucketName, location) - } else { - r0 = ret.Error(0) - } - return r0 -} - -// MockGCPClientManager_EnsureStorageBucket_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'EnsureStorageBucket' -type MockGCPClientManager_EnsureStorageBucket_Call struct { - *mock.Call -} - -// EnsureStorageBucket is a helper method to define mock.On call -// - projectID string -// - bucketName string -// - location string -func (_e *MockGCPClientManager_Expecter) EnsureStorageBucket(projectID any, bucketName any, location any) *MockGCPClientManager_EnsureStorageBucket_Call { - return &MockGCPClientManager_EnsureStorageBucket_Call{Call: _e.mock.On("EnsureStorageBucket", projectID, bucketName, location)} -} - -func (_c *MockGCPClientManager_EnsureStorageBucket_Call) Run(run func(projectID string, bucketName string, location string)) *MockGCPClientManager_EnsureStorageBucket_Call { - _c.Call.Run(func(args mock.Arguments) { - var arg0 string - if args[0] != nil { - arg0 = args[0].(string) - } - var arg1 string - if args[1] != nil { - arg1 = args[1].(string) - } - var arg2 string - if args[2] != nil { - arg2 = args[2].(string) - } - run( - arg0, - arg1, - arg2, - ) - }) - return _c -} - -func (_c *MockGCPClientManager_EnsureStorageBucket_Call) Return(err error) *MockGCPClientManager_EnsureStorageBucket_Call { - _c.Call.Return(err) - return _c -} - -func (_c *MockGCPClientManager_EnsureStorageBucket_Call) RunAndReturn(run func(projectID string, bucketName string, location string) error) *MockGCPClientManager_EnsureStorageBucket_Call { - _c.Call.Return(run) - return _c -} - -// CreateHMACKey provides a mock function for the type MockGCPClientManager -func (_mock *MockGCPClientManager) CreateHMACKey(projectID string, serviceAccountEmail string) (string, string, error) { - ret := _mock.Called(projectID, serviceAccountEmail) - - if len(ret) == 0 { - panic("no return value specified for CreateHMACKey") - } - - var r0 string - var r1 string - var r2 error - if returnFunc, ok := ret.Get(0).(func(string, string) (string, string, error)); ok { - return returnFunc(projectID, serviceAccountEmail) - } - if returnFunc, ok := ret.Get(0).(func(string, string) string); ok { - r0 = returnFunc(projectID, serviceAccountEmail) - } else { - r0 = ret.Get(0).(string) - } - if returnFunc, ok := ret.Get(1).(func(string, string) string); ok { - r1 = returnFunc(projectID, serviceAccountEmail) - } else { - r1 = ret.Get(1).(string) - } - if returnFunc, ok := ret.Get(2).(func(string, string) error); ok { - r2 = returnFunc(projectID, serviceAccountEmail) - } else { - r2 = ret.Error(2) - } - return r0, r1, r2 -} - -// MockGCPClientManager_CreateHMACKey_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreateHMACKey' -type MockGCPClientManager_CreateHMACKey_Call struct { - *mock.Call -} - -// CreateHMACKey is a helper method to define mock.On call -// - projectID string -// - serviceAccountEmail string -func (_e *MockGCPClientManager_Expecter) CreateHMACKey(projectID any, serviceAccountEmail any) *MockGCPClientManager_CreateHMACKey_Call { - return &MockGCPClientManager_CreateHMACKey_Call{Call: _e.mock.On("CreateHMACKey", projectID, serviceAccountEmail)} -} - -func (_c *MockGCPClientManager_CreateHMACKey_Call) Run(run func(projectID string, serviceAccountEmail string)) *MockGCPClientManager_CreateHMACKey_Call { - _c.Call.Run(func(args mock.Arguments) { - var arg0 string - if args[0] != nil { - arg0 = args[0].(string) - } - var arg1 string - if args[1] != nil { - arg1 = args[1].(string) - } - run( - arg0, - arg1, - ) - }) - return _c -} - -func (_c *MockGCPClientManager_CreateHMACKey_Call) Return(accessID string, secret string, err error) *MockGCPClientManager_CreateHMACKey_Call { - _c.Call.Return(accessID, secret, err) - return _c -} - -func (_c *MockGCPClientManager_CreateHMACKey_Call) RunAndReturn(run func(projectID string, serviceAccountEmail string) (string, string, error)) *MockGCPClientManager_CreateHMACKey_Call { - _c.Call.Return(run) - return _c -}