github.com/GoogleCloudPlatform/terraformer@v0.8.18/providers/gcp/gcp_compute_code_generator/main.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 main
    16  
    17  import (
    18  	"bytes"
    19  	"encoding/json"
    20  	"go/format"
    21  	"io/ioutil"
    22  	"log"
    23  	"os"
    24  	"strings"
    25  	"text/template"
    26  )
    27  
    28  const pathForGenerateFiles = "/providers/gcp/"
    29  const serviceTemplate = `
    30  // Copyright 2018 The Terraformer Authors.
    31  //
    32  // Licensed under the Apache License, Version 2.0 (the "License");
    33  // you may not use this file except in compliance with the License.
    34  // You may obtain a copy of the License at
    35  //
    36  //      http://www.apache.org/licenses/LICENSE-2.0
    37  //
    38  // Unless required by applicable law or agreed to in writing, software
    39  // distributed under the License is distributed on an "AS IS" BASIS,
    40  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    41  // See the License for the specific language governing permissions and
    42  // limitations under the License.
    43  
    44  // AUTO-GENERATED CODE. DO NOT EDIT.
    45  package gcp
    46  
    47  import (
    48  	"context"
    49  	"log"
    50  	{{ if .byZone  }}"strings"{{end}}
    51  
    52  	"github.com/GoogleCloudPlatform/terraformer/terraformutils"
    53  
    54  	"google.golang.org/api/compute/v1"
    55  )
    56  
    57  var {{.resource}}AllowEmptyValues = []string{"{{join .allowEmptyValues "\",\"" }}"}
    58  
    59  var {{.resource}}AdditionalFields = map[string]interface{}{
    60  	{{ range $key,$value := .additionalFields}}
    61  	"{{$key}}":			"{{$value}}",{{end}}
    62  }
    63  
    64  type {{.titleResourceName}}Generator struct {
    65  	GCPService
    66  }
    67  
    68  // Run on {{.resource}}List and create for each TerraformResource
    69  func (g {{.titleResourceName}}Generator) createResources(ctx context.Context, {{.resource}}List *compute.{{.titleResourceName}}ListCall{{ if .byZone  }}, zone string{{end}}) []terraformutils.Resource {
    70  	resources := []terraformutils.Resource{}
    71  	if err := {{.resource}}List.Pages(ctx, func(page *compute.{{.responseName}}) error {
    72  		for _, obj := range page.Items {
    73  			resources = append(resources, terraformutils.NewResource(
    74  				{{ if .idWithZone  }}zone+"/"+obj.Name,{{else}}obj.Name,{{end}}
    75  				{{ if .idWithZone  }}zone+"/"+obj.Name,{{else}}obj.Name,{{end}}
    76  				"{{.terraformName}}",
    77  				g.ProviderName,
    78  				map[string]string{
    79  					"name":    obj.Name,
    80  					"project": g.GetArgs()["project"].(string),
    81  					{{ if .needRegion}}"region":  g.GetArgs()["region"].(compute.Region).Name,{{end}}
    82  					{{ if .byZone  }}"zone":    zone,{{end}}
    83  					{{ range $key, $value := .additionalFieldsForRefresh}}
    84  					"{{$key}}":			"{{$value}}",{{end}}
    85  				},
    86  				{{.resource}}AllowEmptyValues,
    87  				{{.resource}}AdditionalFields,
    88  			))
    89  		}
    90  		return nil
    91  	}); err != nil {
    92  		log.Println(err)
    93  	}
    94  	return resources
    95  }
    96  
    97  // Generate TerraformResources from GCP API,
    98  // from each {{.resource}} create 1 TerraformResource
    99  // Need {{.resource}} name as ID for terraform resource
   100  func (g *{{.titleResourceName}}Generator) InitResources() error {
   101  	ctx := context.Background()
   102  	computeService, err := compute.NewService(ctx)
   103  	if err != nil {
   104  		return err
   105  	}
   106  	{{ if .byZone  }}
   107  	for _, zoneLink := range g.GetArgs()["region"].(compute.Region).Zones {
   108  		t := strings.Split(zoneLink, "/")
   109  		zone := t[len(t)-1]
   110  		{{.resource}}List := computeService.{{.titleResourceName}}.List(g.GetArgs()["project"].(string), zone)
   111  		g.Resources = append(g.Resources, g.createResources(ctx, {{.resource}}List, zone)...)
   112  	}
   113  	{{else}}
   114  		{{.resource}}List := computeService.{{.titleResourceName}}.List({{.parameterOrder}})
   115  		g.Resources = g.createResources(ctx, {{.resource}}List)
   116  	{{end}}
   117  
   118  	return nil
   119  
   120  }
   121  
   122  `
   123  const computeTemplate = `
   124  // Copyright 2018 The Terraformer Authors.
   125  //
   126  // Licensed under the Apache License, Version 2.0 (the "License");
   127  // you may not use this file except in compliance with the License.
   128  // You may obtain a copy of the License at
   129  //
   130  //      http://www.apache.org/licenses/LICENSE-2.0
   131  //
   132  // Unless required by applicable law or agreed to in writing, software
   133  // distributed under the License is distributed on an "AS IS" BASIS,
   134  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   135  // See the License for the specific language governing permissions and
   136  // limitations under the License.
   137  
   138  // AUTO-GENERATED CODE. DO NOT EDIT.
   139  package gcp
   140  
   141  import (
   142  	"github.com/GoogleCloudPlatform/terraformer/terraformutils"
   143  )
   144  
   145  // Map of supported GCP compute service with code generate
   146  var ComputeServices = map[string]terraformutils.ServiceGenerator{
   147  {{ range $key, $value := .services }}
   148  	"{{$key}}":                   &GCPFacade{service: &{{title $key}}Generator{}},{{ end }}
   149  
   150  }
   151  
   152  `
   153  
   154  func main() {
   155  	computeAPIData, err := ioutil.ReadFile(os.Getenv("GOPATH") + "/src/google.golang.org/api/compute/v1/compute-api.json") // TODO delete this hack
   156  	if err != nil {
   157  		log.Fatal(err)
   158  	}
   159  	computeAPI := map[string]interface{}{}
   160  	err = json.Unmarshal(computeAPIData, &computeAPI)
   161  	if err != nil {
   162  		log.Fatal(err)
   163  	}
   164  	funcMap := template.FuncMap{
   165  		"title":   strings.Title,
   166  		"toLower": strings.ToLower,
   167  		"join":    strings.Join,
   168  	}
   169  	for resource, v := range computeAPI["resources"].(map[string]interface{}) {
   170  		if _, exist := terraformResources[resource]; !exist {
   171  			continue
   172  		}
   173  		if value, exist := v.(map[string]interface{})["methods"].(map[string]interface{})["list"]; exist {
   174  			parameters := []string{}
   175  			for _, param := range value.(map[string]interface{})["parameterOrder"].([]interface{}) {
   176  				switch param.(string) {
   177  				case "region":
   178  					parameters = append(parameters, `g.GetArgs()["region"].(compute.Region).Name`)
   179  				case "project":
   180  					parameters = append(parameters, `g.GetArgs()["project"].(string)`)
   181  				case "zone":
   182  					parameters = append(parameters, `g.GetArgs()["zone"].(string)`)
   183  				}
   184  			}
   185  			parameterOrder := strings.Join(parameters, ", ")
   186  			var tpl bytes.Buffer
   187  			t := template.Must(template.New("resource.go").Funcs(funcMap).Parse(serviceTemplate))
   188  			err := t.Execute(&tpl, map[string]interface{}{
   189  				"titleResourceName":          strings.Title(resource),
   190  				"resource":                   resource,
   191  				"responseName":               value.(map[string]interface{})["response"].(map[string]interface{})["$ref"].(string),
   192  				"terraformName":              terraformResources[resource].getTerraformName(),
   193  				"additionalFields":           terraformResources[resource].getAdditionalFields(),
   194  				"additionalFieldsForRefresh": terraformResources[resource].getAdditionalFieldsForRefresh(),
   195  				"allowEmptyValues":           terraformResources[resource].getAllowEmptyValues(),
   196  				"needRegion":                 terraformResources[resource].ifNeedRegion(),
   197  				"resourcePackageName":        resource,
   198  				"parameterOrder":             parameterOrder,
   199  				"byZone":                     terraformResources[resource].ifNeedZone(strings.Contains(parameterOrder, "zone")),
   200  				"idWithZone":                 terraformResources[resource].ifIDWithZone(strings.Contains(parameterOrder, "zone")),
   201  			})
   202  			if err != nil {
   203  				log.Print(resource, err)
   204  				continue
   205  			}
   206  			rootPath, _ := os.Getwd()
   207  			currentPath := rootPath + pathForGenerateFiles
   208  			err = os.MkdirAll(currentPath, os.ModePerm)
   209  			if err != nil {
   210  				log.Print(resource, err)
   211  				continue
   212  			}
   213  			err = ioutil.WriteFile(currentPath+"/"+resource+"_gen.go", codeFormat(tpl.Bytes()), os.ModePerm)
   214  			if err != nil {
   215  				log.Print(resource, err)
   216  				continue
   217  			}
   218  		} else {
   219  			log.Println(resource)
   220  		}
   221  	}
   222  	var tpl bytes.Buffer
   223  	t := template.Must(template.New("compute.go").Funcs(funcMap).Parse(computeTemplate))
   224  	err = t.Execute(&tpl, map[string]interface{}{
   225  		"services": terraformResources,
   226  	})
   227  	if err != nil {
   228  		log.Print(err)
   229  	}
   230  	rootPath, _ := os.Getwd()
   231  	err = ioutil.WriteFile(rootPath+pathForGenerateFiles+"compute.go", codeFormat(tpl.Bytes()), os.ModePerm)
   232  	if err != nil {
   233  		log.Println(err)
   234  	}
   235  }
   236  
   237  func codeFormat(src []byte) []byte {
   238  	code, err := format.Source(src)
   239  	if err != nil {
   240  		log.Println(err)
   241  	}
   242  	return code
   243  }