|
| 1 | +// Copyright 2025 MongoDB Inc |
| 2 | +// |
| 3 | +// Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | +// you may not use this file except in compliance with the License. |
| 5 | +// You may obtain a copy of the License at |
| 6 | +// |
| 7 | +// http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | +// |
| 9 | +// Unless required by applicable law or agreed to in writing, software |
| 10 | +// distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | +// See the License for the specific language governing permissions and |
| 13 | +// limitations under the License. |
| 14 | +package resource |
| 15 | + |
| 16 | +import ( |
| 17 | + "context" |
| 18 | + "strings" |
| 19 | + |
| 20 | + "github.com/aws-cloudformation/cloudformation-cli-go-plugin/cfn/handler" |
| 21 | + flex "github.com/mongodb/mongodbatlas-cloudformation-resources/flex-cluster/cmd/resource" |
| 22 | + "github.com/mongodb/mongodbatlas-cloudformation-resources/util" |
| 23 | +) |
| 24 | + |
| 25 | +const ( |
| 26 | + defaultPriority = 7 |
| 27 | + defaultZoneName = "Zone 1" |
| 28 | + flexProvider = "FLEX" |
| 29 | +) |
| 30 | + |
| 31 | +// clusterToFlexModelIdentifier transforms a cluster model to a flex cluster model representation. |
| 32 | +// It's used for Read and Delete where only the identifier is passed (project id and cluster name). |
| 33 | +// As regions are not passed, Atlas calls are made to learn if it's a flex cluster. |
| 34 | +// Returns nil if the cluster is not a flex cluster. |
| 35 | +func clusterToFlexModelIdentifier(req *handler.Request, client *util.MongoDBClient, c *Model) *flex.Model { |
| 36 | + f := &flex.Model{ |
| 37 | + Profile: c.Profile, |
| 38 | + ProjectId: c.ProjectId, |
| 39 | + Name: c.Name, |
| 40 | + } |
| 41 | + if isCallback(req) { |
| 42 | + return nil // cluster operation in progress |
| 43 | + } |
| 44 | + if flex.IsCallback(req) { |
| 45 | + return f // flex operation in progress |
| 46 | + } |
| 47 | + _, _, errCluster := client.AtlasSDK.ClustersApi.GetCluster(context.Background(), *c.ProjectId, *c.Name).Execute() |
| 48 | + if errCluster != nil && strings.Contains(errCluster.Error(), "CANNOT_USE_FLEX_CLUSTER_IN_CLUSTER_API") { |
| 49 | + return f |
| 50 | + } |
| 51 | + return nil |
| 52 | +} |
| 53 | + |
| 54 | +// clusterToFlexModelFull transforms a cluster model to a flex cluster model representation. |
| 55 | +// It's used for Create and Update where the full model is passed. |
| 56 | +// Regions are passed so not Atlas calls are needed to learn if it's a flex cluster. |
| 57 | +// Returns nil if the cluster is not a flex cluster. |
| 58 | +func clusterToFlexModelFull(c *Model) *flex.Model { |
| 59 | + if len(c.ReplicationSpecs) != 1 || len(c.ReplicationSpecs[0].AdvancedRegionConfigs) != 1 { |
| 60 | + return nil |
| 61 | + } |
| 62 | + firstRegion := c.ReplicationSpecs[0].AdvancedRegionConfigs[0] |
| 63 | + if util.SafeString(firstRegion.ProviderName) != flexProvider { |
| 64 | + return nil |
| 65 | + } |
| 66 | + f := &flex.Model{ |
| 67 | + Profile: c.Profile, |
| 68 | + ProjectId: c.ProjectId, |
| 69 | + Name: c.Name, |
| 70 | + Id: c.Id, |
| 71 | + StateName: c.StateName, |
| 72 | + ClusterType: c.ClusterType, |
| 73 | + CreateDate: c.CreatedDate, |
| 74 | + MongoDBVersion: c.MongoDBVersion, |
| 75 | + TerminationProtectionEnabled: c.TerminationProtectionEnabled, |
| 76 | + VersionReleaseSystem: c.VersionReleaseSystem, |
| 77 | + ProviderSettings: &flex.ProviderSettings{ |
| 78 | + BackingProviderName: firstRegion.BackingProviderName, |
| 79 | + RegionName: firstRegion.RegionName, |
| 80 | + ProviderName: firstRegion.ProviderName, |
| 81 | + }, |
| 82 | + } |
| 83 | + if c.BackupEnabled != nil { |
| 84 | + f.BackupSettings = &flex.BackupSettings{ |
| 85 | + Enabled: c.BackupEnabled, |
| 86 | + } |
| 87 | + } |
| 88 | + if c.ConnectionStrings != nil { |
| 89 | + f.ConnectionStrings = &flex.ConnectionStrings{ |
| 90 | + Standard: c.ConnectionStrings.Standard, |
| 91 | + StandardSrv: c.ConnectionStrings.StandardSrv, |
| 92 | + } |
| 93 | + } |
| 94 | + f.Tags = make([]flex.Tag, len(c.Tags)) |
| 95 | + for i, tag := range c.Tags { |
| 96 | + f.Tags[i] = flex.Tag{ |
| 97 | + Key: tag.Key, |
| 98 | + Value: tag.Value, |
| 99 | + } |
| 100 | + } |
| 101 | + return f |
| 102 | +} |
| 103 | + |
| 104 | +// fillModelForFlex updates the flex model into the cluster model. |
| 105 | +func fillModelForFlex(pe *handler.ProgressEvent, c *Model) { |
| 106 | + if pe.ResourceModel == nil { |
| 107 | + return |
| 108 | + } |
| 109 | + f := pe.ResourceModel.(*flex.Model) // will panic if not a flex model |
| 110 | + pe.ResourceModel = c |
| 111 | + |
| 112 | + c.Profile = f.Profile |
| 113 | + c.ProjectId = f.ProjectId |
| 114 | + c.Name = f.Name |
| 115 | + c.Id = f.Id |
| 116 | + c.StateName = f.StateName |
| 117 | + c.ClusterType = f.ClusterType |
| 118 | + c.CreatedDate = f.CreateDate |
| 119 | + c.MongoDBVersion = f.MongoDBVersion |
| 120 | + c.TerminationProtectionEnabled = f.TerminationProtectionEnabled |
| 121 | + c.VersionReleaseSystem = f.VersionReleaseSystem |
| 122 | + if f.BackupSettings != nil { |
| 123 | + c.BackupEnabled = f.BackupSettings.Enabled |
| 124 | + } else { |
| 125 | + c.BackupEnabled = nil |
| 126 | + } |
| 127 | + if f.ConnectionStrings != nil { |
| 128 | + c.ConnectionStrings = &ConnectionStrings{ |
| 129 | + Standard: f.ConnectionStrings.Standard, |
| 130 | + StandardSrv: f.ConnectionStrings.StandardSrv, |
| 131 | + } |
| 132 | + } else { |
| 133 | + c.ConnectionStrings = nil |
| 134 | + } |
| 135 | + c.Tags = make([]Tag, len(f.Tags)) |
| 136 | + for i, tag := range f.Tags { |
| 137 | + c.Tags[i] = Tag{ |
| 138 | + Key: tag.Key, |
| 139 | + Value: tag.Value, |
| 140 | + } |
| 141 | + } |
| 142 | + if f.ProviderSettings != nil { |
| 143 | + regionConfig := AdvancedRegionConfig{ |
| 144 | + BackingProviderName: f.ProviderSettings.BackingProviderName, |
| 145 | + RegionName: f.ProviderSettings.RegionName, |
| 146 | + ProviderName: f.ProviderSettings.ProviderName, |
| 147 | + Priority: util.Pointer(defaultPriority), |
| 148 | + } |
| 149 | + replicationSpec := AdvancedReplicationSpec{ |
| 150 | + AdvancedRegionConfigs: []AdvancedRegionConfig{regionConfig}, |
| 151 | + ZoneName: util.Pointer(defaultZoneName), |
| 152 | + } |
| 153 | + c.ReplicationSpecs = []AdvancedReplicationSpec{replicationSpec} |
| 154 | + } else { |
| 155 | + c.ReplicationSpecs = nil |
| 156 | + } |
| 157 | +} |
| 158 | + |
| 159 | +// fillModelForFlexList update the cluster list with flex clusters. |
| 160 | +func fillModelForFlexList(pe *handler.ProgressEvent, clusters []*Model) []*Model { |
| 161 | + if pe.ResourceModel == nil { |
| 162 | + return clusters |
| 163 | + } |
| 164 | + list := pe.ResourceModel.([]*flex.Model) // will panic if not a flex model array |
| 165 | + for _, f := range list { |
| 166 | + c := &Model{} |
| 167 | + fillModelForFlex(&handler.ProgressEvent{ResourceModel: f}, c) |
| 168 | + clusters = append(clusters, c) |
| 169 | + } |
| 170 | + return clusters |
| 171 | +} |
0 commit comments