github.com/GoogleCloudPlatform/terraformer@v0.8.18/providers/gcp/gke.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 gcp
    16  
    17  import (
    18  	"context"
    19  	"fmt"
    20  	"log"
    21  	"strconv"
    22  
    23  	"github.com/GoogleCloudPlatform/terraformer/terraformutils"
    24  
    25  	container "google.golang.org/api/container/v1beta1"
    26  )
    27  
    28  var GkeAllowEmptyValues = []string{"labels."}
    29  
    30  var GkeAdditionalFields = map[string]interface{}{}
    31  
    32  type GkeGenerator struct {
    33  	GCPService
    34  }
    35  
    36  func (g *GkeGenerator) initClusters(clusters *container.ListClustersResponse) []terraformutils.Resource {
    37  	resources := []terraformutils.Resource{}
    38  	for _, cluster := range clusters.Clusters {
    39  		if _, exist := cluster.ResourceLabels["goog-composer-environment"]; exist { // don't manage composer clusters
    40  			continue
    41  		}
    42  		resource := terraformutils.NewResource(
    43  			cluster.Name,
    44  			cluster.Name,
    45  			"google_container_cluster",
    46  			g.ProviderName,
    47  			map[string]string{
    48  				"name":     cluster.Name, // provider need cluster name as Required
    49  				"project":  g.GetArgs()["project"].(string),
    50  				"location": cluster.Location,
    51  				"zone":     cluster.Zone,
    52  			},
    53  			GkeAllowEmptyValues,
    54  			GkeAdditionalFields,
    55  		)
    56  		resource.IgnoreKeys = append(resource.IgnoreKeys,
    57  			"^region$",
    58  			"^additional_zones\\.(.*)",
    59  			"^zone$",
    60  			"^node_pool\\.(.*)",   // delete node_pool config from google_container_cluster
    61  			"^node_config\\.(.*)", // delete node_config config from google_container_cluster
    62  			"^ip_allocation_policy\\.[0-9]\\.cluster_secondary_range_name$",  // conflict with cluster_ipv4_cidr_block
    63  			"^ip_allocation_policy\\.[0-9]\\.services_secondary_range_name$", // conflict with services_ipv4_cidr_block
    64  			"^ip_allocation_policy\\.[0-9]\\.create_subnetwork")              // only for create new cluster conflict with others ip_allocation_policy fields
    65  		resources = append(resources, resource)
    66  		resources = append(resources, g.initNodePools(cluster.NodePools, cluster.Name, cluster.Location)...)
    67  	}
    68  	return resources
    69  }
    70  
    71  func (g *GkeGenerator) initNodePools(nodePools []*container.NodePool, clusterName, location string) []terraformutils.Resource {
    72  	resources := []terraformutils.Resource{}
    73  	for _, nodePool := range nodePools {
    74  		resources = append(resources, terraformutils.NewResource(
    75  			fmt.Sprintf("%s/%s/%s", location, clusterName, nodePool.Name),
    76  			clusterName+"_"+nodePool.Name,
    77  			"google_container_node_pool",
    78  			g.ProviderName,
    79  			map[string]string{
    80  				"location": location,
    81  				"zone":     location,
    82  				"project":  g.GetArgs()["project"].(string),
    83  				"cluster":  clusterName, // provider need cluster name as Required
    84  				"name":     nodePool.Name,
    85  			},
    86  			GkeAllowEmptyValues,
    87  			GkeAdditionalFields,
    88  		))
    89  	}
    90  	return resources
    91  }
    92  
    93  // Generate TerraformResources from GCP API,
    94  func (g *GkeGenerator) InitResources() error {
    95  	ctx := context.Background()
    96  	service, err := container.NewService(ctx)
    97  	if err != nil {
    98  		log.Print(err)
    99  		return err
   100  	}
   101  	// GKE support zone and regional cluster, api use location, it's can be region or zone, for all "-"
   102  	location := fmt.Sprintf("projects/%s/locations/%s", g.GetArgs()["project"].(string), "-")
   103  	clusters, err := service.Projects.Locations.Clusters.List(location).Do()
   104  	if err != nil {
   105  		log.Print(err)
   106  		return err
   107  	}
   108  
   109  	g.Resources = g.initClusters(clusters)
   110  	return nil
   111  }
   112  
   113  func (g *GkeGenerator) PostConvertHook() error {
   114  	for i, r := range g.Resources {
   115  		if r.InstanceInfo.Type != "google_container_node_pool" {
   116  			continue
   117  		}
   118  		if _, existNodeConfig := g.Resources[i].Item["node_config"]; existNodeConfig {
   119  			if _, existMetadata := g.Resources[i].Item["node_config"].([]interface{})[0].(map[string]interface{})["metadata"]; existMetadata {
   120  				for k, v := range g.Resources[i].Item["node_config"].([]interface{})[0].(map[string]interface{})["metadata"].(map[string]interface{}) {
   121  					switch x := v.(type) {
   122  					case bool:
   123  						g.Resources[i].Item["node_config"].([]interface{})[0].(map[string]interface{})["metadata"].(map[string]interface{})[k] = strconv.FormatBool(x)
   124  					default:
   125  					}
   126  				}
   127  			}
   128  		}
   129  		for _, cluster := range g.Resources {
   130  			if cluster.InstanceState.Attributes["name"] == r.InstanceState.Attributes["cluster"] {
   131  				g.Resources[i].Item["cluster"] = "${google_container_cluster." + cluster.ResourceName + ".name}"
   132  			}
   133  		}
   134  	}
   135  
   136  	// hacks for fix GCP API<=>provider<=>parser inconsistency
   137  	for i, r := range g.Resources {
   138  		if r.InstanceInfo.Type != "google_container_cluster" {
   139  			continue
   140  		}
   141  		if r.Item["master_authorized_networks_config"] != nil {
   142  			if len(r.Item["master_authorized_networks_config"].([]interface{})) == 0 {
   143  				g.Resources[i].Item["master_authorized_networks_config"] = map[string]interface{}{}
   144  			}
   145  		}
   146  		if r.Item["ip_allocation_policy"] != nil {
   147  			if len(r.Item["ip_allocation_policy"].([]interface{})) == 0 {
   148  				g.Resources[i].Item["ip_allocation_policy"] = map[string]interface{}{}
   149  			}
   150  		}
   151  	}
   152  	return nil
   153  }