github.com/GoogleCloudPlatform/terraformer@v0.8.18/providers/aws/elasticache.go (about) 1 // Copyright 2018 The Terraformer Authors. 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 15 package aws 16 17 import ( 18 "context" 19 "strings" 20 21 "github.com/GoogleCloudPlatform/terraformer/terraformutils" 22 23 "github.com/aws/aws-sdk-go-v2/service/elasticache" 24 ) 25 26 var elastiCacheAllowEmptyValues = []string{"tags."} 27 28 type ElastiCacheGenerator struct { 29 AWSService 30 } 31 32 func (g *ElastiCacheGenerator) loadCacheClusters(svc *elasticache.Client) error { 33 p := elasticache.NewDescribeCacheClustersPaginator(svc, &elasticache.DescribeCacheClustersInput{}) 34 for p.HasMorePages() { 35 page, err := p.NextPage(context.TODO()) 36 if err != nil { 37 return err 38 } 39 for _, cluster := range page.CacheClusters { 40 resourceName := StringValue(cluster.CacheClusterId) 41 resource := terraformutils.NewSimpleResource( 42 resourceName, 43 resourceName, 44 "aws_elasticache_cluster", 45 "aws", 46 elastiCacheAllowEmptyValues, 47 ) 48 // redis only - if cluster has Replication Group not need next attributes. 49 // terraform-aws provider has ConflictsWith on ReplicationGroupId with all next attributes, 50 // but return all attributes on refresh :( 51 // https://github.com/terraform-providers/terraform-provider-aws/blob/master/aws/resource_aws_elasticache_cluster.go#L167 52 if StringValue(cluster.ReplicationGroupId) != "" { 53 resource.IgnoreKeys = append(resource.IgnoreKeys, 54 "^availability_zones$", 55 "^az_mode$", 56 "^engine_version$", 57 "^engine$", 58 "^maintenance_window$", 59 "^node_type$", 60 "^notification_topic_arn$", 61 "^num_cache_nodes$", 62 "^parameter_group_name$", 63 "^port$", 64 "^security_group_ids.(.*)", 65 "^security_group_names$", 66 "^snapshot_arns$", 67 "^snapshot_name$", 68 "^snapshot_retention_limit$", 69 "^snapshot_window$", 70 "^subnet_group_name$", 71 ) 72 } 73 g.Resources = append(g.Resources, resource) 74 } 75 } 76 return nil 77 } 78 79 func (g *ElastiCacheGenerator) loadParameterGroups(svc *elasticache.Client) error { 80 p := elasticache.NewDescribeCacheParameterGroupsPaginator(svc, &elasticache.DescribeCacheParameterGroupsInput{}) 81 for p.HasMorePages() { 82 page, err := p.NextPage(context.TODO()) 83 if err != nil { 84 return err 85 } 86 for _, parameterGroup := range page.CacheParameterGroups { 87 resourceName := StringValue(parameterGroup.CacheParameterGroupName) 88 if strings.Contains(resourceName, ".") { 89 continue // skip default Default ParameterGroups like default.redis5.0 90 } 91 g.Resources = append(g.Resources, terraformutils.NewSimpleResource( 92 resourceName, 93 resourceName, 94 "aws_elasticache_parameter_group", 95 "aws", 96 elastiCacheAllowEmptyValues, 97 )) 98 } 99 } 100 return nil 101 } 102 103 func (g *ElastiCacheGenerator) loadSubnetGroups(svc *elasticache.Client) error { 104 p := elasticache.NewDescribeCacheSubnetGroupsPaginator(svc, &elasticache.DescribeCacheSubnetGroupsInput{}) 105 for p.HasMorePages() { 106 page, err := p.NextPage(context.TODO()) 107 if err != nil { 108 return err 109 } 110 for _, subnet := range page.CacheSubnetGroups { 111 resourceName := StringValue(subnet.CacheSubnetGroupName) 112 g.Resources = append(g.Resources, terraformutils.NewSimpleResource( 113 resourceName, 114 resourceName, 115 "aws_elasticache_subnet_group", 116 "aws", 117 elastiCacheAllowEmptyValues, 118 )) 119 } 120 } 121 return nil 122 } 123 124 func (g *ElastiCacheGenerator) loadReplicationGroups(svc *elasticache.Client) error { 125 p := elasticache.NewDescribeReplicationGroupsPaginator(svc, &elasticache.DescribeReplicationGroupsInput{}) 126 for p.HasMorePages() { 127 page, err := p.NextPage(context.TODO()) 128 if err != nil { 129 return err 130 } 131 for _, replicationGroup := range page.ReplicationGroups { 132 resourceName := StringValue(replicationGroup.ReplicationGroupId) 133 g.Resources = append(g.Resources, terraformutils.NewSimpleResource( 134 resourceName, 135 resourceName, 136 "aws_elasticache_replication_group", 137 "aws", 138 elastiCacheAllowEmptyValues, 139 )) 140 } 141 } 142 return nil 143 } 144 145 // Generate TerraformResources from AWS API, 146 // from each database create 1 TerraformResource. 147 // Need only database name as ID for terraform resource 148 // AWS api support paging 149 func (g *ElastiCacheGenerator) InitResources() error { 150 config, e := g.generateConfig() 151 if e != nil { 152 return e 153 } 154 svc := elasticache.NewFromConfig(config) 155 156 if err := g.loadCacheClusters(svc); err != nil { 157 return err 158 } 159 if err := g.loadParameterGroups(svc); err != nil { 160 return err 161 } 162 if err := g.loadReplicationGroups(svc); err != nil { 163 return err 164 } 165 if err := g.loadSubnetGroups(svc); err != nil { 166 return err 167 } 168 169 return nil 170 } 171 172 func (g *ElastiCacheGenerator) PostConvertHook() error { 173 for i, r := range g.Resources { 174 if r.InstanceInfo.Type != "aws_elasticache_cluster" { 175 continue 176 } 177 for _, parameterGroup := range g.Resources { 178 if parameterGroup.InstanceInfo.Type != "aws_elasticache_parameter_group" { 179 continue 180 } 181 if parameterGroup.InstanceState.Attributes["name"] == r.InstanceState.Attributes["parameter_group_name"] { 182 if strings.HasPrefix(parameterGroup.InstanceState.Attributes["family"], r.InstanceState.Attributes["engine"]) { 183 g.Resources[i].Item["parameter_group_name"] = "${aws_elasticache_parameter_group." + parameterGroup.ResourceName + ".name}" 184 } 185 } 186 } 187 188 for _, subnet := range g.Resources { 189 if subnet.InstanceInfo.Type != "aws_elasticache_subnet_group" { 190 continue 191 } 192 if subnet.InstanceState.Attributes["name"] == r.Item["subnet_group_name"] { 193 g.Resources[i].Item["subnet_group_name"] = "${aws_elasticache_subnet_group." + subnet.ResourceName + ".name}" 194 } 195 } 196 197 for _, replicationGroup := range g.Resources { 198 if replicationGroup.InstanceInfo.Type != "aws_elasticache_replication_group" { 199 continue 200 } 201 if replicationGroup.InstanceState.Attributes["replication_group_id"] == r.InstanceState.Attributes["replication_group_id"] { 202 g.Resources[i].Item["replication_group_id"] = "${aws_elasticache_replication_group." + replicationGroup.ResourceName + ".replication_group_id}" 203 } 204 } 205 } 206 for i, r := range g.Resources { 207 if r.InstanceInfo.Type != "aws_elasticache_replication_group" { 208 continue 209 } 210 for _, subnet := range g.Resources { 211 if subnet.InstanceInfo.Type != "aws_elasticache_subnet_group" { 212 continue 213 } 214 if subnet.InstanceState.Attributes["name"] == r.InstanceState.Attributes["subnet_group_name"] { 215 g.Resources[i].Item["subnet_group_name"] = "${aws_elasticache_subnet_group." + subnet.ResourceName + ".name}" 216 } 217 } 218 } 219 return nil 220 }