mmv1/provider/terraform_tgc_next.go (142 lines of code) (raw):
// Copyright 2024 Google Inc.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generator for a library converting terraform state to gcp objects.
package provider
import (
"bytes"
"errors"
"fmt"
"log"
"os"
"path/filepath"
"time"
"github.com/GoogleCloudPlatform/magic-modules/mmv1/api"
"github.com/GoogleCloudPlatform/magic-modules/mmv1/api/product"
"github.com/otiai10/copy"
)
// This proivder is for both tfplan2cai and cai2hcl conversions,
// and copying other files, such as transport.go
type TerraformGoogleConversionNext struct {
TargetVersionName string
Version product.Version
Product *api.Product
StartTime time.Time
}
func NewTerraformGoogleConversionNext(product *api.Product, versionName string, startTime time.Time) TerraformGoogleConversionNext {
t := TerraformGoogleConversionNext{
Product: product,
TargetVersionName: versionName,
Version: *product.VersionObjOrClosest(versionName),
StartTime: startTime,
}
t.Product.SetPropertiesBasedOnVersion(&t.Version)
for _, r := range t.Product.Objects {
r.SetCompiler(ProviderName(t))
r.ImportPath = ImportPathFromVersion(versionName)
}
return t
}
func (tgc TerraformGoogleConversionNext) Generate(outputFolder, productPath, resourceToGenerate string, generateCode, generateDocs bool) {
tgc.GenerateTfToCaiObjects(outputFolder, resourceToGenerate, generateCode, generateDocs)
tgc.GenerateCaiToHclObjects(outputFolder, resourceToGenerate, generateCode, generateDocs)
}
func (tgc TerraformGoogleConversionNext) GenerateTfToCaiObjects(outputFolder, resourceToGenerate string, generateCode, generateDocs bool) {
}
func (tgc TerraformGoogleConversionNext) GenerateCaiToHclObjects(outputFolder, resourceToGenerate string, generateCode, generateDocs bool) {
}
func (tgc TerraformGoogleConversionNext) CompileCommonFiles(outputFolder string, products []*api.Product, overridePath string) {
tgc.CompileTfToCaiCommonFiles(outputFolder, products)
tgc.CompileCaiToHclCommonFiles(outputFolder, products)
}
func (tgc TerraformGoogleConversionNext) CompileTfToCaiCommonFiles(outputFolder string, products []*api.Product) {
log.Printf("Compiling common files for tgc tfplan2cai.")
resourceConverters := map[string]string{
"pkg/tfplan2cai/converters/resource_converters.go": "templates/tgc_next/tfplan2cai/resource_converters.go.tmpl",
"pkg/tfplan2cai/converters/services/compute/compute_instance_helpers.go": "third_party/terraform/services/compute/compute_instance_helpers.go.tmpl",
"pkg/tfplan2cai/converters/services/compute/metadata.go": "third_party/terraform/services/compute/metadata.go.tmpl",
}
templateData := NewTemplateData(outputFolder, tgc.TargetVersionName)
tgc.CompileFileList(outputFolder, resourceConverters, *templateData, products)
}
func (tgc TerraformGoogleConversionNext) CompileCaiToHclCommonFiles(outputFolder string, products []*api.Product) {
log.Printf("Compiling common files for tgc tfplan2cai.")
resourceConverters := map[string]string{
"pkg/cai2hcl/converters/resource_converters.go": "templates/tgc_next/cai2hcl/resource_converters.go.tmpl",
}
templateData := NewTemplateData(outputFolder, tgc.TargetVersionName)
tgc.CompileFileList(outputFolder, resourceConverters, *templateData, products)
}
func (tgc TerraformGoogleConversionNext) CompileFileList(outputFolder string, files map[string]string, fileTemplate TemplateData, products []*api.Product) {
if err := os.MkdirAll(outputFolder, os.ModePerm); err != nil {
log.Println(fmt.Errorf("error creating output directory %v: %v", outputFolder, err))
}
for target, source := range files {
targetFile := filepath.Join(outputFolder, target)
targetDir := filepath.Dir(targetFile)
if err := os.MkdirAll(targetDir, os.ModePerm); err != nil {
log.Println(fmt.Errorf("error creating output directory %v: %v", targetDir, err))
}
templates := []string{
source,
}
formatFile := filepath.Ext(targetFile) == ".go"
fileTemplate.GenerateFile(targetFile, source, tgc, formatFile, templates...)
tgc.replaceImportPath(outputFolder, target)
}
}
func (tgc TerraformGoogleConversionNext) CopyCommonFiles(outputFolder string, generateCode, generateDocs bool) {
if !generateCode {
return
}
log.Printf("Copying common files for tgc.")
if err := os.MkdirAll(outputFolder, os.ModePerm); err != nil {
log.Println(fmt.Errorf("error creating output directory %v: %v", outputFolder, err))
}
if err := copy.Copy("third_party/tgc_next", outputFolder); err != nil {
log.Println(fmt.Errorf("error copying directory %v: %v", outputFolder, err))
}
tgc.CopyTfToCaiCommonFiles(outputFolder)
tgc.CopyCaiToHclCommonFiles(outputFolder)
}
func (tgc TerraformGoogleConversionNext) CopyTfToCaiCommonFiles(outputFolder string) {
resourceConverters := map[string]string{
"pkg/tfplan2cai/converters/services/compute/image.go": "third_party/terraform/services/compute/image.go",
"pkg/tfplan2cai/converters/services/compute/disk_type.go": "third_party/terraform/services/compute/disk_type.go",
}
tgc.CopyFileList(outputFolder, resourceConverters)
}
func (tgc TerraformGoogleConversionNext) CopyCaiToHclCommonFiles(outputFolder string) {
resourceConverters := map[string]string{}
tgc.CopyFileList(outputFolder, resourceConverters)
}
func (tgc TerraformGoogleConversionNext) CopyFileList(outputFolder string, files map[string]string) {
for target, source := range files {
targetFile := filepath.Join(outputFolder, target)
targetDir := filepath.Dir(targetFile)
if err := os.MkdirAll(targetDir, os.ModePerm); err != nil {
log.Println(fmt.Errorf("error creating output directory %v: %v", targetDir, err))
}
// If we've modified a file since starting an MM run, it's a reasonable
// assumption that it was this run that modified it.
if info, err := os.Stat(targetFile); !errors.Is(err, os.ErrNotExist) && tgc.StartTime.Before(info.ModTime()) {
log.Fatalf("%s was already modified during this run at %s", targetFile, info.ModTime().String())
}
sourceByte, err := os.ReadFile(source)
if err != nil {
log.Fatalf("Cannot read source file %s while copying: %s", source, err)
}
err = os.WriteFile(targetFile, sourceByte, 0644)
if err != nil {
log.Fatalf("Cannot write target file %s while copying: %s", target, err)
}
// Replace import path based on version (beta/alpha)
if filepath.Ext(target) == ".go" || filepath.Ext(target) == ".mod" {
tgc.replaceImportPath(outputFolder, target)
}
}
}
func (tgc TerraformGoogleConversionNext) replaceImportPath(outputFolder, target string) {
// Replace import paths to reference the resources dir instead of the google provider
targetFile := filepath.Join(outputFolder, target)
sourceByte, err := os.ReadFile(targetFile)
if err != nil {
log.Fatalf("Cannot read file %s to replace import path: %s", targetFile, err)
}
// replace google to google-beta
gaImportPath := ImportPathFromVersion("ga")
sourceByte = bytes.Replace(sourceByte, []byte(gaImportPath), []byte(TERRAFORM_PROVIDER_BETA+"/"+RESOURCE_DIRECTORY_BETA), -1)
err = os.WriteFile(targetFile, sourceByte, 0644)
if err != nil {
log.Fatalf("Cannot write file %s to replace import path: %s", target, err)
}
}