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  }