Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Go compiler skeleton and early terraform.rb provider code #10104

Merged
merged 1 commit into from
Mar 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions mmv1/api/product.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ package api

import (
"github.com/GoogleCloudPlatform/magic-modules/mmv1/api/product"
"golang.org/x/exp/slices"
)

// require 'api/object'
Expand Down Expand Up @@ -158,6 +159,29 @@ type Product struct {
// false
// end

func (p *Product) ExistsAtVersionOrLower(name string) bool {
if !slices.Contains(product.ORDER, name) {
return false
}

for i := 0; i <= slices.Index(product.ORDER, name); i++ {
if p.ExistsAtVersion(product.ORDER[i]) {
return true
}
}

return false
}

func (p *Product) ExistsAtVersion(name string) bool {
for _, v := range p.Versions {
if v.Name == name {
return true
}
}
return false
}

// def exists_at_version(name)
// // Versions aren't normally going to be empty since products need a
// // base_url. This nil check exists for atypical products, like _bundle.
Expand Down
2 changes: 1 addition & 1 deletion mmv1/api/product/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ package product

// require 'api/object'

var ORDER = [...]string{"ga", "beta", "alpha", "private"}
var ORDER = []string{"ga", "beta", "alpha", "private"}

// A version of the API for a given product / API group
// In GCP, different product versions are generally ordered where alpha is
Expand Down
5 changes: 4 additions & 1 deletion mmv1/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,7 @@ module github.com/GoogleCloudPlatform/magic-modules/mmv1

go 1.20

require gopkg.in/yaml.v2 v2.4.0 // indirect
require (
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
)
2 changes: 2 additions & 0 deletions mmv1/go.sum
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ=
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
111 changes: 77 additions & 34 deletions mmv1/main.go
Original file line number Diff line number Diff line change
@@ -1,78 +1,103 @@
package main

import (
"encoding/json"
"fmt"
"log"
"os"
"path"
"path/filepath"
"slices"
"sort"
"strings"

"github.com/GoogleCloudPlatform/magic-modules/mmv1/api"
"github.com/GoogleCloudPlatform/magic-modules/mmv1/google"
"github.com/GoogleCloudPlatform/magic-modules/mmv1/provider"
)

func main() {
var products_to_generate []string
var all_products = true
// TODO Q2: parse flags
var version = "beta"
var outputPath = "."
var generateCode = true
var generateDocs = true

var all_product_files []string = make([]string, 0)
log.Printf("Initiating go MM compiler")

// TODO Q1: allow specifying one product (flag or hardcoded)
// var productsToGenerate []string
// var allProducts = true
var productsToGenerate = []string{"products/datafusion"}
var allProducts = false

var allProductFiles []string = make([]string, 0)

files, err := filepath.Glob("products/**/product.yaml")
if err != nil {
return
}
for _, file_path := range files {
dir := filepath.Dir(file_path)
all_product_files = append(all_product_files, fmt.Sprintf("products/%s", filepath.Base(dir)))
for _, filePath := range files {
dir := filepath.Dir(filePath)
allProductFiles = append(allProductFiles, fmt.Sprintf("products/%s", filepath.Base(dir)))
}
// TODO Q2: override directory

if all_products {
products_to_generate = all_product_files
if allProducts {
productsToGenerate = allProductFiles
}

if products_to_generate == nil || len(products_to_generate) == 0 {
if productsToGenerate == nil || len(productsToGenerate) == 0 {
log.Fatalf("No product.yaml file found.")
}

log.Printf("Generating MM output to '%s'", outputPath)
log.Printf("Using %s version", version)

// Building compute takes a long time and can't be parallelized within the product
// so lets build it first
sort.Slice(all_product_files, func(i int, j int) bool {
if all_product_files[i] == "compute" {
sort.Slice(allProductFiles, func(i int, j int) bool {
if allProductFiles[i] == "compute" {
return true
}
return false
})

yamlValidator := google.YamlValidator{}

for _, product_name := range all_product_files {
product_yaml_path := path.Join(product_name, "go_product.yaml")
for _, productName := range allProductFiles {
productYamlPath := path.Join(productName, "go_product.yaml")

// TODO: uncomment the error check that if the product.yaml exists for each product
// TODO Q2: uncomment the error check that if the product.yaml exists for each product
// after Go-converted product.yaml files are complete for all products

// if _, err := os.Stat(product_yaml_path); errors.Is(err, os.ErrNotExist) {
// log.Fatalf("%s does not contain a product.yaml file", product_name)
// if _, err := os.Stat(productYamlPath); errors.Is(err, os.ErrNotExist) {
// log.Fatalf("%s does not contain a product.yaml file", productName)
// }

if _, err := os.Stat(product_yaml_path); err == nil {
log.Printf("product_yaml_path %#v", product_yaml_path)
// TODO Q2: product overrides

if _, err := os.Stat(productYamlPath); err == nil {
// TODO Q1: remove these lines, which are for debugging
// log.Printf("productYamlPath %#v", productYamlPath)

productYaml, err := os.ReadFile(product_yaml_path)
var resources []api.Resource

productYaml, err := os.ReadFile(productYamlPath)
if err != nil {
log.Fatalf("Cannot open the file: %v", productYaml)
}
productApi := api.Product{}
yamlValidator.Parse(productYaml, &productApi)

// TODO: remove these lines, which are for debugging
prod, _ := json.Marshal(&productApi)
log.Printf("prod %s", string(prod))
// TODO Q1: remove these lines, which are for debugging
// prod, _ := json.Marshal(&productApi)
// log.Printf("prod %s", string(prod))

if !productApi.ExistsAtVersionOrLower(version) {
log.Printf("%s does not have a '%s' version, skipping", productName, version)
continue
}

resourceFiles, err := filepath.Glob(fmt.Sprintf("%s/*", product_name))
resourceFiles, err := filepath.Glob(fmt.Sprintf("%s/*", productName))
if err != nil {
log.Fatalf("Cannot get resources files: %v", err)
}
Expand All @@ -81,28 +106,46 @@ func main() {
continue
}

// TODO REMOVE: limiting test block
// if !strings.Contains(resourceYamlPath, "datafusion") {
// continue
// }

// Prepend "go_" to the Go yaml files' name to distinguish with the ruby yaml files
if filepath.Base(resourceYamlPath) == "go_product.yaml" || !strings.HasPrefix(filepath.Base(resourceYamlPath), "go_") {
continue
}

log.Printf(" resourceYamlPath %s", resourceYamlPath)
// TODO Q1: remove these lines, which are for debugging
// log.Printf(" resourceYamlPath %s", resourceYamlPath)
resourceYaml, err := os.ReadFile(resourceYamlPath)
if err != nil {
log.Fatalf("Cannot open the file: %v", resourceYamlPath)
}
resource := api.Resource{}
yamlValidator.Parse(resourceYaml, &resource)

// TODO: remove these lines, which are for debugging
res, _ := json.Marshal(&resource)
log.Printf("resource %s", string(res))
// TODO Q1: remove these lines, which are for debugging
// res, _ := json.Marshal(&resource)
// log.Printf("resource %s", string(res))

// TODO Q1: add labels related fields

resources = append(resources, resource)
}

// TODO Q2: override resources

// TODO Q1: sort resources by name and set in product

// TODO Q2: set other providers via flag
providerToGenerate := provider.NewTerraform(productApi)

if !slices.Contains(productsToGenerate, productName) {
log.Printf("%s not specified, skipping generation", productName)
continue
}

// TODO Q1: generate templates
log.Printf("%s: Generating files", productName)
providerToGenerate.Generate(outputPath, productName, generateCode, generateDocs)
}

// TODO Q2: copy common files
}
}
Loading
Loading