Skip to content

private endpoint: add support for regional mode #2559

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
35 changes: 18 additions & 17 deletions api/condition.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 5 additions & 0 deletions api/v1/atlasproject_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"`
Expand Down
21 changes: 21 additions & 0 deletions api/v1/project/regionalized_private_endpoint.go
Original file line number Diff line number Diff line change
@@ -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"`
}
5 changes: 5 additions & 0 deletions api/v1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions config/crd/bases/atlas.mongodb.com_atlasprojects.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
2 changes: 1 addition & 1 deletion devbox.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
24 changes: 12 additions & 12 deletions devbox.lock
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
}
},
Expand Down
5 changes: 5 additions & 0 deletions internal/controller/atlasproject/atlasproject_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -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), "")
}
Expand Down
Original file line number Diff line number Diff line change
@@ -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()
}
53 changes: 27 additions & 26 deletions internal/controller/workflow/reason.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading
Loading