Skip to content

Commit

Permalink
Go compiler skeleton and early terraform.rb provider code (GoogleClou…
Browse files Browse the repository at this point in the history
  • Loading branch information
c2thorn authored and jashansudan committed Mar 6, 2024
1 parent 9f7697a commit c8fb9cc
Show file tree
Hide file tree
Showing 6 changed files with 1,000 additions and 36 deletions.
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

0 comments on commit c8fb9cc

Please sign in to comment.