diff --git a/Makefile b/Makefile index c12e64a668..b283ca1d10 100644 --- a/Makefile +++ b/Makefile @@ -289,6 +289,7 @@ generate: ${GO_SOURCES} ## Generate code ifdef EXPERIMENTAL controller-gen object:headerFile="hack/boilerplate.go.txt" paths="./internal/nextapi/v1/..." endif + mockery $(MAKE) fmt .PHONY: check-missing-files diff --git a/api/condition.go b/api/condition.go index 87a7ace9a2..30bc861273 100644 --- a/api/condition.go +++ b/api/condition.go @@ -48,23 +48,24 @@ const ( // AtlasProject condition types const ( - ProjectReadyType ConditionType = "ProjectReady" - IPAccessListReadyType ConditionType = "IPAccessListReady" - MaintenanceWindowReadyType ConditionType = "MaintenanceWindowReady" - PrivateEndpointServiceReadyType ConditionType = "PrivateEndpointServiceReady" - PrivateEndpointReadyType ConditionType = "PrivateEndpointReady" - NetworkPeerReadyType ConditionType = "NetworkPeerReady" - CloudProviderIntegrationReadyType ConditionType = "CloudProviderIntegrationReady" - IntegrationReadyType ConditionType = "ThirdPartyIntegrationReady" - AlertConfigurationReadyType ConditionType = "AlertConfigurationReady" - EncryptionAtRestReadyType ConditionType = "EncryptionAtRestReady" - AuditingReadyType ConditionType = "AuditingReady" - ProjectSettingsReadyType ConditionType = "ProjectSettingsReady" - ProjectCustomRolesReadyType ConditionType = "ProjectCustomRolesReady" - ProjectTeamsReadyType ConditionType = "ProjectTeamsReady" - SearchIndexesReadyType ConditionType = "AtlasSearchIndexesReady" - BackupComplianceReadyType ConditionType = "BackupCompliancePolicyReady" - X509AuthReadyType ConditionType = "X509AuthReady" + ProjectReadyType ConditionType = "ProjectReady" + IPAccessListReadyType ConditionType = "IPAccessListReady" + MaintenanceWindowReadyType ConditionType = "MaintenanceWindowReady" + PrivateEndpointServiceReadyType ConditionType = "PrivateEndpointServiceReady" + RegionalizedPrivateEndpointReadyType ConditionType = "RegionalizedPrivateEndpointReady" + PrivateEndpointReadyType ConditionType = "PrivateEndpointReady" + NetworkPeerReadyType ConditionType = "NetworkPeerReady" + CloudProviderIntegrationReadyType ConditionType = "CloudProviderIntegrationReady" + IntegrationReadyType ConditionType = "ThirdPartyIntegrationReady" + AlertConfigurationReadyType ConditionType = "AlertConfigurationReady" + EncryptionAtRestReadyType ConditionType = "EncryptionAtRestReady" + AuditingReadyType ConditionType = "AuditingReady" + ProjectSettingsReadyType ConditionType = "ProjectSettingsReady" + ProjectCustomRolesReadyType ConditionType = "ProjectCustomRolesReady" + ProjectTeamsReadyType ConditionType = "ProjectTeamsReady" + SearchIndexesReadyType ConditionType = "AtlasSearchIndexesReady" + BackupComplianceReadyType ConditionType = "BackupCompliancePolicyReady" + X509AuthReadyType ConditionType = "X509AuthReady" ) // AtlasDeployment condition types diff --git a/api/v1/atlasproject_types.go b/api/v1/atlasproject_types.go index abd6688ce1..c056608b40 100644 --- a/api/v1/atlasproject_types.go +++ b/api/v1/atlasproject_types.go @@ -72,6 +72,11 @@ type AtlasProjectSpec struct { // PrivateEndpoints is a list of Private Endpoints configured for the current Project. PrivateEndpoints []PrivateEndpoint `json:"privateEndpoints,omitempty"` + // RegionalizedPrivateEndpoint allows to enable regionalized private endpoints. See more at + // https://www.mongodb.com/docs/atlas/security-private-endpoint/ + // +optional + RegionalizedPrivateEndpoint *project.RegionalizedPrivateEndpoint `json:"regionalizedPrivateEndpoint,omitempty"` + // CloudProviderAccessRoles is a list of Cloud Provider Access Roles configured for the current Project. // Deprecated: This configuration was deprecated in favor of CloudProviderIntegrations CloudProviderAccessRoles []CloudProviderAccessRole `json:"cloudProviderAccessRoles,omitempty"` diff --git a/api/v1/project/regionalized_private_endpoint.go b/api/v1/project/regionalized_private_endpoint.go new file mode 100644 index 0000000000..6bbee4d6a5 --- /dev/null +++ b/api/v1/project/regionalized_private_endpoint.go @@ -0,0 +1,21 @@ +// Copyright 2025 MongoDB Inc +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package project + +type RegionalizedPrivateEndpoint struct { + // Flag indicating whether regionalized private endpoint mode should be enabled. + // +optional + Enabled bool `json:"enabled,omitempty"` +} diff --git a/api/v1/zz_generated.deepcopy.go b/api/v1/zz_generated.deepcopy.go index 69180e0152..9892c4e6df 100644 --- a/api/v1/zz_generated.deepcopy.go +++ b/api/v1/zz_generated.deepcopy.go @@ -1497,6 +1497,11 @@ func (in *AtlasProjectSpec) DeepCopyInto(out *AtlasProjectSpec) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.RegionalizedPrivateEndpoint != nil { + in, out := &in.RegionalizedPrivateEndpoint, &out.RegionalizedPrivateEndpoint + *out = new(project.RegionalizedPrivateEndpoint) + **out = **in + } if in.CloudProviderAccessRoles != nil { in, out := &in.CloudProviderAccessRoles, &out.CloudProviderAccessRoles *out = make([]CloudProviderAccessRole, len(*in)) diff --git a/config/crd/bases/atlas.mongodb.com_atlasprojects.yaml b/config/crd/bases/atlas.mongodb.com_atlasprojects.yaml index 1e4d196b64..9af395edd6 100644 --- a/config/crd/bases/atlas.mongodb.com_atlasprojects.yaml +++ b/config/crd/bases/atlas.mongodb.com_atlasprojects.yaml @@ -902,6 +902,16 @@ spec: - GOV_REGIONS_ONLY - COMMERCIAL_FEDRAMP_REGIONS_ONLY type: string + regionalizedPrivateEndpoint: + description: |- + RegionalizedPrivateEndpoint allows to enable regionalized private endpoints. See more at + https://www.mongodb.com/docs/atlas/security-private-endpoint/ + properties: + enabled: + description: Flag indicating whether regionalized private endpoint + mode should be enabled. + type: boolean + type: object settings: description: Settings allow to set Project Settings for the project properties: diff --git a/devbox.json b/devbox.json index 2685e7f56a..e533eba825 100644 --- a/devbox.json +++ b/devbox.json @@ -23,7 +23,7 @@ "kubernetes-controller-tools@0.17.2", "setup-envtest@0.19.0", "awscli2@latest", - "go-mockery@latest", + "go-mockery@2", "docker-sbom@latest", "openshift@latest", "gci@latest" diff --git a/devbox.lock b/devbox.lock index 4a5841cce5..f46e746a7b 100644 --- a/devbox.lock +++ b/devbox.lock @@ -529,51 +529,51 @@ "last_modified": "2025-07-25T08:26:56Z", "resolved": "github:NixOS/nixpkgs/6027c30c8e9810896b92429f0092f624f7b1aace?lastModified=1753432016&narHash=sha256-cnL5WWn%2FxkZoyH%2F03NNUS7QgW5vI7D1i74g48qplCvg%3D" }, - "go-mockery@latest": { - "last_modified": "2025-07-18T03:30:42Z", - "resolved": "github:NixOS/nixpkgs/e821e03193486359aa942372be2d9c1f377b7a18#go-mockery", + "go-mockery@2": { + "last_modified": "2025-07-13T22:45:35Z", + "resolved": "github:NixOS/nixpkgs/a421ac6595024edcfbb1ef950a3712b89161c359#go-mockery", "source": "devbox-search", - "version": "3.5.1", + "version": "2.53.3", "systems": { "aarch64-darwin": { "outputs": [ { "name": "out", - "path": "/nix/store/dpmkxa2brjdlx3fxr7cbx17kngjdcgl5-go-mockery-3.5.1", + "path": "/nix/store/gymm44dbi3sp824ghj28z7xdp5y0z8ij-go-mockery-2.53.3", "default": true } ], - "store_path": "/nix/store/dpmkxa2brjdlx3fxr7cbx17kngjdcgl5-go-mockery-3.5.1" + "store_path": "/nix/store/gymm44dbi3sp824ghj28z7xdp5y0z8ij-go-mockery-2.53.3" }, "aarch64-linux": { "outputs": [ { "name": "out", - "path": "/nix/store/wkcjxschqyb455c3d3l2sfvn21xfx0c4-go-mockery-3.5.1", + "path": "/nix/store/7almddm7x5spkllll4avz0fd19slcvvj-go-mockery-2.53.3", "default": true } ], - "store_path": "/nix/store/wkcjxschqyb455c3d3l2sfvn21xfx0c4-go-mockery-3.5.1" + "store_path": "/nix/store/7almddm7x5spkllll4avz0fd19slcvvj-go-mockery-2.53.3" }, "x86_64-darwin": { "outputs": [ { "name": "out", - "path": "/nix/store/3rylkp14wbg3zjdwzr3x0crkm0lasr6a-go-mockery-3.5.1", + "path": "/nix/store/xxd8ynzjqi4v0jahgzs9k45mj0ymcsns-go-mockery-2.53.3", "default": true } ], - "store_path": "/nix/store/3rylkp14wbg3zjdwzr3x0crkm0lasr6a-go-mockery-3.5.1" + "store_path": "/nix/store/xxd8ynzjqi4v0jahgzs9k45mj0ymcsns-go-mockery-2.53.3" }, "x86_64-linux": { "outputs": [ { "name": "out", - "path": "/nix/store/j6hl8p4v53i4zrvag0ka805kc4irnybc-go-mockery-3.5.1", + "path": "/nix/store/p7cdcd71qnf8k6h1fyrsx42a768w02c2-go-mockery-2.53.3", "default": true } ], - "store_path": "/nix/store/j6hl8p4v53i4zrvag0ka805kc4irnybc-go-mockery-3.5.1" + "store_path": "/nix/store/p7cdcd71qnf8k6h1fyrsx42a768w02c2-go-mockery-2.53.3" } } }, diff --git a/internal/controller/atlasproject/atlasproject_controller.go b/internal/controller/atlasproject/atlasproject_controller.go index 72277c93f8..3ac1b6db04 100644 --- a/internal/controller/atlasproject/atlasproject_controller.go +++ b/internal/controller/atlasproject/atlasproject_controller.go @@ -198,6 +198,11 @@ func (r *AtlasProjectReconciler) ensureProjectResources(workflowCtx *workflow.Co } results = append(results, result) + if result = r.ensureRegionalizedPrivateEndpointMode(workflowCtx, project); result.IsOk() { + r.EventRecorder.Event(project, "Normal", string(api.RegionalizedPrivateEndpointReadyType), "") + } + results = append(results, result) + if result = ensureCloudProviderIntegration(workflowCtx, project); result.IsOk() { r.EventRecorder.Event(project, "Normal", string(api.CloudProviderIntegrationReadyType), "") } diff --git a/internal/controller/atlasproject/regionalized_private_endpoint.go b/internal/controller/atlasproject/regionalized_private_endpoint.go new file mode 100644 index 0000000000..13fd56208d --- /dev/null +++ b/internal/controller/atlasproject/regionalized_private_endpoint.go @@ -0,0 +1,52 @@ +// Copyright 2025 MongoDB Inc +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package atlasproject + +import ( + "github.com/mongodb/mongodb-atlas-kubernetes/v2/api" + akov2 "github.com/mongodb/mongodb-atlas-kubernetes/v2/api/v1" + "github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/controller/workflow" + "github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/translation/privateendpoint" +) + +// ensureRegionalizedPrivateEndpointMode ensures that if the AtlasProject spec +// defines a regionalized private endpoint setting, it is reflected in Atlas. +func (r *AtlasProjectReconciler) ensureRegionalizedPrivateEndpointMode(workflowCtx *workflow.Context, atlasProject *akov2.AtlasProject) workflow.DeprecatedResult { + if atlasProject.Spec.RegionalizedPrivateEndpoint == nil { + workflowCtx.UnsetCondition(api.RegionalizedPrivateEndpointReadyType) + return workflow.OK() + } + + expectedMode := atlasProject.Spec.RegionalizedPrivateEndpoint.Enabled + + peApi := privateendpoint.NewPrivateEndpointAPI(workflowCtx.SdkClientSet.SdkClient20250312002.PrivateEndpointServicesApi) + currentMode, err := peApi.GetRegionalizedPrivateEndpointSetting(workflowCtx.Context, atlasProject.ID()) + if err != nil { + result := workflow.Terminate(workflow.ProjectRegionalizedEndpointModeIsNotReadyInAtlas, err) + workflowCtx.SetConditionFromResult(api.RegionalizedPrivateEndpointReadyType, result) + return result + } + + if currentMode != expectedMode { + if _, err := peApi.ToggleRegionalizedPrivateEndpointSetting(workflowCtx.Context, atlasProject.ID(), expectedMode); err != nil { + result := workflow.Terminate(workflow.ProjectRegionalizedEndpointModeIsNotReadyInAtlas, err) + workflowCtx.SetConditionFromResult(api.RegionalizedPrivateEndpointReadyType, result) + return result + } + } + + workflowCtx.SetConditionTrue(api.RegionalizedPrivateEndpointReadyType) + return workflow.OK() +} diff --git a/internal/controller/workflow/reason.go b/internal/controller/workflow/reason.go index c56809ea06..b663fad562 100644 --- a/internal/controller/workflow/reason.go +++ b/internal/controller/workflow/reason.go @@ -33,32 +33,33 @@ const ( // Atlas Project reasons const ( - ProjectNotCreatedInAtlas ConditionReason = "ProjectNotCreatedInAtlas" - ProjectBeingConfiguredInAtlas ConditionReason = "ProjectBeingConfiguredInAtlas" - ProjectIPAccessInvalid ConditionReason = "ProjectIPAccessListInvalid" - ProjectIPNotCreatedInAtlas ConditionReason = "ProjectIPAccessListNotCreatedInAtlas" - ProjectWindowInvalid ConditionReason = "ProjectWindowInvalid" - ProjectWindowNotObtainedFromAtlas ConditionReason = "ProjectWindowNotObtainedFromAtlas" - ProjectWindowNotCreatedInAtlas ConditionReason = "ProjectWindowNotCreatedInAtlas" - ProjectWindowNotDeletedInAtlas ConditionReason = "projectWindowNotDeletedInAtlas" - ProjectWindowNotDeferredInAtlas ConditionReason = "ProjectWindowNotDeferredInAtlas" - ProjectWindowNotAutoDeferredInAtlas ConditionReason = "ProjectWindowNotAutoDeferredInAtlas" - ProjectPEServiceIsNotReadyInAtlas ConditionReason = "ProjectPrivateEndpointServiceIsNotReadyInAtlas" - ProjectPEInterfaceIsNotReadyInAtlas ConditionReason = "ProjectPrivateEndpointIsNotReadyInAtlas" - ProjectIPAccessListNotActive ConditionReason = "ProjectIPAccessListNotActive" - ProjectIntegrationInternal ConditionReason = "ProjectIntegrationInternalError" - ProjectIntegrationRequest ConditionReason = "ProjectIntegrationRequestError" - ProjectIntegrationReady ConditionReason = "ProjectIntegrationReady" - ProjectPrivateEndpointIsNotReadyInAtlas ConditionReason = "ProjectPrivateEndpointIsNotReadyInAtlas" - ProjectNetworkPeerIsNotReadyInAtlas ConditionReason = "ProjectNetworkPeerIsNotReadyInAtlas" - ProjectEncryptionAtRestReady ConditionReason = "ProjectEncryptionAtRestReady" - ProjectCloudIntegrationsIsNotReadyInAtlas ConditionReason = "ProjectCloudIntegrationsIsNotReadyInAtlas" - ProjectAuditingReady ConditionReason = "ProjectAuditingReady" - ProjectSettingsReady ConditionReason = "ProjectSettingsReady" - ProjectAlertConfigurationIsNotReadyInAtlas ConditionReason = "ProjectAlertConfigurationIsNotReadyInAtlas" - ProjectCustomRolesReady ConditionReason = "ProjectCustomRolesReady" - ProjectTeamUnavailable ConditionReason = "ProjectTeamUnavailable" - ProjectX509NotConfigured ConditionReason = "ProjectX509NotConfigured" + ProjectNotCreatedInAtlas ConditionReason = "ProjectNotCreatedInAtlas" + ProjectBeingConfiguredInAtlas ConditionReason = "ProjectBeingConfiguredInAtlas" + ProjectIPAccessInvalid ConditionReason = "ProjectIPAccessListInvalid" + ProjectIPNotCreatedInAtlas ConditionReason = "ProjectIPAccessListNotCreatedInAtlas" + ProjectWindowInvalid ConditionReason = "ProjectWindowInvalid" + ProjectWindowNotObtainedFromAtlas ConditionReason = "ProjectWindowNotObtainedFromAtlas" + ProjectWindowNotCreatedInAtlas ConditionReason = "ProjectWindowNotCreatedInAtlas" + ProjectWindowNotDeletedInAtlas ConditionReason = "projectWindowNotDeletedInAtlas" + ProjectWindowNotDeferredInAtlas ConditionReason = "ProjectWindowNotDeferredInAtlas" + ProjectWindowNotAutoDeferredInAtlas ConditionReason = "ProjectWindowNotAutoDeferredInAtlas" + ProjectPEServiceIsNotReadyInAtlas ConditionReason = "ProjectPrivateEndpointServiceIsNotReadyInAtlas" + ProjectPEInterfaceIsNotReadyInAtlas ConditionReason = "ProjectPrivateEndpointIsNotReadyInAtlas" + ProjectIPAccessListNotActive ConditionReason = "ProjectIPAccessListNotActive" + ProjectIntegrationInternal ConditionReason = "ProjectIntegrationInternalError" + ProjectIntegrationRequest ConditionReason = "ProjectIntegrationRequestError" + ProjectIntegrationReady ConditionReason = "ProjectIntegrationReady" + ProjectPrivateEndpointIsNotReadyInAtlas ConditionReason = "ProjectPrivateEndpointIsNotReadyInAtlas" + ProjectRegionalizedEndpointModeIsNotReadyInAtlas ConditionReason = "ProjectRegionalizedEndpointModeIsNotReadyInAtlas" + ProjectNetworkPeerIsNotReadyInAtlas ConditionReason = "ProjectNetworkPeerIsNotReadyInAtlas" + ProjectEncryptionAtRestReady ConditionReason = "ProjectEncryptionAtRestReady" + ProjectCloudIntegrationsIsNotReadyInAtlas ConditionReason = "ProjectCloudIntegrationsIsNotReadyInAtlas" + ProjectAuditingReady ConditionReason = "ProjectAuditingReady" + ProjectSettingsReady ConditionReason = "ProjectSettingsReady" + ProjectAlertConfigurationIsNotReadyInAtlas ConditionReason = "ProjectAlertConfigurationIsNotReadyInAtlas" + ProjectCustomRolesReady ConditionReason = "ProjectCustomRolesReady" + ProjectTeamUnavailable ConditionReason = "ProjectTeamUnavailable" + ProjectX509NotConfigured ConditionReason = "ProjectX509NotConfigured" ) // Atlas Backup Compliance Policy reasons diff --git a/internal/mocks/translation/deployment.go b/internal/mocks/translation/deployment.go index a620bb8ca4..1d511a2df7 100644 --- a/internal/mocks/translation/deployment.go +++ b/internal/mocks/translation/deployment.go @@ -22,61 +22,6 @@ func (_m *DeploymentMock) EXPECT() *DeploymentMock_Expecter { return &DeploymentMock_Expecter{mock: &_m.Mock} } -// Deprecated provides a mock function with no fields -func (_m *DeploymentMock) Deprecated() (bool, string) { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for Notifications") - } - - var r0 bool - var r1 string - if rf, ok := ret.Get(0).(func() (bool, string)); ok { - return rf() - } - if rf, ok := ret.Get(0).(func() bool); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(bool) - } - - if rf, ok := ret.Get(1).(func() string); ok { - r1 = rf() - } else { - r1 = ret.Get(1).(string) - } - - return r0, r1 -} - -// DeploymentMock_Deprecated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Deprecated' -type DeploymentMock_Deprecated_Call struct { - *mock.Call -} - -// Deprecated is a helper method to define mock.On call -func (_e *DeploymentMock_Expecter) Deprecated() *DeploymentMock_Deprecated_Call { - return &DeploymentMock_Deprecated_Call{Call: _e.mock.On("Notifications")} -} - -func (_c *DeploymentMock_Deprecated_Call) Run(run func()) *DeploymentMock_Deprecated_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *DeploymentMock_Deprecated_Call) Return(_a0 bool, _a1 string) *DeploymentMock_Deprecated_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *DeploymentMock_Deprecated_Call) RunAndReturn(run func() (bool, string)) *DeploymentMock_Deprecated_Call { - _c.Call.Return(run) - return _c -} - // GetConnection provides a mock function with no fields func (_m *DeploymentMock) GetConnection() *status.ConnectionStrings { ret := _m.Called() @@ -398,6 +343,51 @@ func (_c *DeploymentMock_GetState_Call) RunAndReturn(run func() string) *Deploym return _c } +// IsDedicated provides a mock function with no fields +func (_m *DeploymentMock) IsDedicated() bool { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for IsDedicated") + } + + var r0 bool + if rf, ok := ret.Get(0).(func() bool); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(bool) + } + + return r0 +} + +// DeploymentMock_IsDedicated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'IsDedicated' +type DeploymentMock_IsDedicated_Call struct { + *mock.Call +} + +// IsDedicated is a helper method to define mock.On call +func (_e *DeploymentMock_Expecter) IsDedicated() *DeploymentMock_IsDedicated_Call { + return &DeploymentMock_IsDedicated_Call{Call: _e.mock.On("IsDedicated")} +} + +func (_c *DeploymentMock_IsDedicated_Call) Run(run func()) *DeploymentMock_IsDedicated_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *DeploymentMock_IsDedicated_Call) Return(_a0 bool) *DeploymentMock_IsDedicated_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *DeploymentMock_IsDedicated_Call) RunAndReturn(run func() bool) *DeploymentMock_IsDedicated_Call { + _c.Call.Return(run) + return _c +} + // IsFlex provides a mock function with no fields func (_m *DeploymentMock) IsFlex() bool { ret := _m.Called() @@ -488,6 +478,113 @@ func (_c *DeploymentMock_IsServerless_Call) RunAndReturn(run func() bool) *Deplo return _c } +// IsTenant provides a mock function with no fields +func (_m *DeploymentMock) IsTenant() bool { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for IsTenant") + } + + var r0 bool + if rf, ok := ret.Get(0).(func() bool); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(bool) + } + + return r0 +} + +// DeploymentMock_IsTenant_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'IsTenant' +type DeploymentMock_IsTenant_Call struct { + *mock.Call +} + +// IsTenant is a helper method to define mock.On call +func (_e *DeploymentMock_Expecter) IsTenant() *DeploymentMock_IsTenant_Call { + return &DeploymentMock_IsTenant_Call{Call: _e.mock.On("IsTenant")} +} + +func (_c *DeploymentMock_IsTenant_Call) Run(run func()) *DeploymentMock_IsTenant_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *DeploymentMock_IsTenant_Call) Return(_a0 bool) *DeploymentMock_IsTenant_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *DeploymentMock_IsTenant_Call) RunAndReturn(run func() bool) *DeploymentMock_IsTenant_Call { + _c.Call.Return(run) + return _c +} + +// Notifications provides a mock function with no fields +func (_m *DeploymentMock) Notifications() (bool, string, string) { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Notifications") + } + + var r0 bool + var r1 string + var r2 string + if rf, ok := ret.Get(0).(func() (bool, string, string)); ok { + return rf() + } + if rf, ok := ret.Get(0).(func() bool); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(bool) + } + + if rf, ok := ret.Get(1).(func() string); ok { + r1 = rf() + } else { + r1 = ret.Get(1).(string) + } + + if rf, ok := ret.Get(2).(func() string); ok { + r2 = rf() + } else { + r2 = ret.Get(2).(string) + } + + return r0, r1, r2 +} + +// DeploymentMock_Notifications_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Notifications' +type DeploymentMock_Notifications_Call struct { + *mock.Call +} + +// Notifications is a helper method to define mock.On call +func (_e *DeploymentMock_Expecter) Notifications() *DeploymentMock_Notifications_Call { + return &DeploymentMock_Notifications_Call{Call: _e.mock.On("Notifications")} +} + +func (_c *DeploymentMock_Notifications_Call) Run(run func()) *DeploymentMock_Notifications_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *DeploymentMock_Notifications_Call) Return(_a0 bool, _a1 string, _a2 string) *DeploymentMock_Notifications_Call { + _c.Call.Return(_a0, _a1, _a2) + return _c +} + +func (_c *DeploymentMock_Notifications_Call) RunAndReturn(run func() (bool, string, string)) *DeploymentMock_Notifications_Call { + _c.Call.Return(run) + return _c +} + // NewDeploymentMock creates a new instance of DeploymentMock. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. // The first argument is typically a *testing.T value. func NewDeploymentMock(t interface { diff --git a/internal/mocks/translation/private_endpoint_service.go b/internal/mocks/translation/private_endpoint_service.go index 29d4d676de..03875891a8 100644 --- a/internal/mocks/translation/private_endpoint_service.go +++ b/internal/mocks/translation/private_endpoint_service.go @@ -306,6 +306,63 @@ func (_c *PrivateEndpointServiceMock_GetPrivateEndpoint_Call) RunAndReturn(run f return _c } +// GetRegionalizedPrivateEndpointSetting provides a mock function with given fields: ctx, projectID +func (_m *PrivateEndpointServiceMock) GetRegionalizedPrivateEndpointSetting(ctx context.Context, projectID string) (bool, error) { + ret := _m.Called(ctx, projectID) + + if len(ret) == 0 { + panic("no return value specified for GetRegionalizedPrivateEndpointSetting") + } + + var r0 bool + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string) (bool, error)); ok { + return rf(ctx, projectID) + } + if rf, ok := ret.Get(0).(func(context.Context, string) bool); ok { + r0 = rf(ctx, projectID) + } else { + r0 = ret.Get(0).(bool) + } + + if rf, ok := ret.Get(1).(func(context.Context, string) error); ok { + r1 = rf(ctx, projectID) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// PrivateEndpointServiceMock_GetRegionalizedPrivateEndpointSetting_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetRegionalizedPrivateEndpointSetting' +type PrivateEndpointServiceMock_GetRegionalizedPrivateEndpointSetting_Call struct { + *mock.Call +} + +// GetRegionalizedPrivateEndpointSetting is a helper method to define mock.On call +// - ctx context.Context +// - projectID string +func (_e *PrivateEndpointServiceMock_Expecter) GetRegionalizedPrivateEndpointSetting(ctx interface{}, projectID interface{}) *PrivateEndpointServiceMock_GetRegionalizedPrivateEndpointSetting_Call { + return &PrivateEndpointServiceMock_GetRegionalizedPrivateEndpointSetting_Call{Call: _e.mock.On("GetRegionalizedPrivateEndpointSetting", ctx, projectID)} +} + +func (_c *PrivateEndpointServiceMock_GetRegionalizedPrivateEndpointSetting_Call) Run(run func(ctx context.Context, projectID string)) *PrivateEndpointServiceMock_GetRegionalizedPrivateEndpointSetting_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(string)) + }) + return _c +} + +func (_c *PrivateEndpointServiceMock_GetRegionalizedPrivateEndpointSetting_Call) Return(_a0 bool, _a1 error) *PrivateEndpointServiceMock_GetRegionalizedPrivateEndpointSetting_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *PrivateEndpointServiceMock_GetRegionalizedPrivateEndpointSetting_Call) RunAndReturn(run func(context.Context, string) (bool, error)) *PrivateEndpointServiceMock_GetRegionalizedPrivateEndpointSetting_Call { + _c.Call.Return(run) + return _c +} + // ListPrivateEndpoints provides a mock function with given fields: ctx, projectID, provider func (_m *PrivateEndpointServiceMock) ListPrivateEndpoints(ctx context.Context, projectID string, provider string) ([]privateendpoint.EndpointService, error) { ret := _m.Called(ctx, projectID, provider) @@ -366,6 +423,64 @@ func (_c *PrivateEndpointServiceMock_ListPrivateEndpoints_Call) RunAndReturn(run return _c } +// ToggleRegionalizedPrivateEndpointSetting provides a mock function with given fields: ctx, projectID, enabled +func (_m *PrivateEndpointServiceMock) ToggleRegionalizedPrivateEndpointSetting(ctx context.Context, projectID string, enabled bool) (bool, error) { + ret := _m.Called(ctx, projectID, enabled) + + if len(ret) == 0 { + panic("no return value specified for ToggleRegionalizedPrivateEndpointSetting") + } + + var r0 bool + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string, bool) (bool, error)); ok { + return rf(ctx, projectID, enabled) + } + if rf, ok := ret.Get(0).(func(context.Context, string, bool) bool); ok { + r0 = rf(ctx, projectID, enabled) + } else { + r0 = ret.Get(0).(bool) + } + + if rf, ok := ret.Get(1).(func(context.Context, string, bool) error); ok { + r1 = rf(ctx, projectID, enabled) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// PrivateEndpointServiceMock_ToggleRegionalizedPrivateEndpointSetting_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ToggleRegionalizedPrivateEndpointSetting' +type PrivateEndpointServiceMock_ToggleRegionalizedPrivateEndpointSetting_Call struct { + *mock.Call +} + +// ToggleRegionalizedPrivateEndpointSetting is a helper method to define mock.On call +// - ctx context.Context +// - projectID string +// - enabled bool +func (_e *PrivateEndpointServiceMock_Expecter) ToggleRegionalizedPrivateEndpointSetting(ctx interface{}, projectID interface{}, enabled interface{}) *PrivateEndpointServiceMock_ToggleRegionalizedPrivateEndpointSetting_Call { + return &PrivateEndpointServiceMock_ToggleRegionalizedPrivateEndpointSetting_Call{Call: _e.mock.On("ToggleRegionalizedPrivateEndpointSetting", ctx, projectID, enabled)} +} + +func (_c *PrivateEndpointServiceMock_ToggleRegionalizedPrivateEndpointSetting_Call) Run(run func(ctx context.Context, projectID string, enabled bool)) *PrivateEndpointServiceMock_ToggleRegionalizedPrivateEndpointSetting_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(string), args[2].(bool)) + }) + return _c +} + +func (_c *PrivateEndpointServiceMock_ToggleRegionalizedPrivateEndpointSetting_Call) Return(_a0 bool, _a1 error) *PrivateEndpointServiceMock_ToggleRegionalizedPrivateEndpointSetting_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *PrivateEndpointServiceMock_ToggleRegionalizedPrivateEndpointSetting_Call) RunAndReturn(run func(context.Context, string, bool) (bool, error)) *PrivateEndpointServiceMock_ToggleRegionalizedPrivateEndpointSetting_Call { + _c.Call.Return(run) + return _c +} + // NewPrivateEndpointServiceMock creates a new instance of PrivateEndpointServiceMock. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. // The first argument is typically a *testing.T value. func NewPrivateEndpointServiceMock(t interface { diff --git a/internal/translation/privateendpoint/privateendpoint.go b/internal/translation/privateendpoint/privateendpoint.go index c6dc4bb8c8..f523b0fa21 100644 --- a/internal/translation/privateendpoint/privateendpoint.go +++ b/internal/translation/privateendpoint/privateendpoint.go @@ -34,6 +34,8 @@ type PrivateEndpointService interface { DeleteEndpointService(ctx context.Context, projectID, provider, ID string) error CreatePrivateEndpointInterface(ctx context.Context, projectID, provider, serviceID, gcpProjectID string, peInterface EndpointInterface) (EndpointInterface, error) DeleteEndpointInterface(ctx context.Context, projectID, provider, serviceID, ID string) error + GetRegionalizedPrivateEndpointSetting(ctx context.Context, projectID string) (bool, error) + ToggleRegionalizedPrivateEndpointSetting(ctx context.Context, projectID string, enabled bool) (bool, error) } type PrivateEndpoint struct { @@ -159,6 +161,26 @@ func (pe *PrivateEndpoint) getEndpointInterfaces(ctx context.Context, projectID, return interfaceFromAtlas(i), nil } +func (pe *PrivateEndpoint) GetRegionalizedPrivateEndpointSetting(ctx context.Context, projectID string) (bool, error) { + setting, _, err := pe.api.GetRegionalizedPrivateEndpointSetting(ctx, projectID).Execute() + if err != nil { + return false, fmt.Errorf("failed to get regionalized private endpoint setting: %w", err) + } + + return setting.GetEnabled(), nil +} + +func (pe *PrivateEndpoint) ToggleRegionalizedPrivateEndpointSetting(ctx context.Context, projectID string, enabled bool) (bool, error) { + setting, _, err := pe.api.ToggleRegionalizedPrivateEndpointSetting(ctx, projectID, &admin.ProjectSettingItem{ + Enabled: enabled, + }).Execute() + if err != nil { + return false, fmt.Errorf("failed to toggle regionalized private endpoint setting: %w", err) + } + + return setting.GetEnabled(), nil +} + func getInterfacesIDs(peService *admin.EndpointService) []string { switch peService.GetCloudProvider() { case ProviderAWS: