Skip to content

Commit

Permalink
Osconfig resource (alpha) (#5266)
Browse files Browse the repository at this point in the history
* Adding private compile

* Send empty array instead of nil for non-computed arrays

* Revert serialize cmd change

* Remove extra logs, revert go mod and sum

* Revert go sum changes

* Delegate DCL version switching to function

* Fix extra slash
  • Loading branch information
slevenick authored Oct 5, 2021
1 parent ce4b88b commit a0343e2
Show file tree
Hide file tree
Showing 14 changed files with 85 additions and 50 deletions.
9 changes: 8 additions & 1 deletion GNUmakefile
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@ ifneq ($(RESOURCE),)
tpgtools_compile += --resource $(RESOURCE)
endif

ifneq ($(OVERRIDES),)
mmv1_compile += -r $(OVERRIDES)
tpgtools_compile += --overrides $(OVERRIDES)/tpgtools/overrides
else
tpgtools_compile += --overrides "overrides"
endif

UNAME := $(shell uname)

# The inplace editing semantics are different between linux and osx.
Expand All @@ -53,7 +60,7 @@ mmv1:

tpgtools:
cd tpgtools;\
go run . --path "api" --overrides "overrides" --output $(OUTPUT_PATH) --version $(VERSION) $(tpgtools_compile)
go run . --path "api" --output $(OUTPUT_PATH) --version $(VERSION) $(tpgtools_compile)

validator:
cd mmv1;\
Expand Down
8 changes: 8 additions & 0 deletions mmv1/provider/terraform.rb
Original file line number Diff line number Diff line change
Expand Up @@ -315,5 +315,13 @@ def full_resource_name(data)
"#{product_name}_#{name}"
end
end

# Returns the extension for DCL packages for the given version. This is needed
# as the DCL uses "alpha" for preview resources, while we use "private"
def dcl_version(version)
return '' if version == 'ga'
return '/beta' if version == 'beta'
return '/alpha' if verison == 'private'
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"testing"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
gkehub "github.com/GoogleCloudPlatform/declarative-resource-client-library/services/google/gkehub/beta"
gkehub "github.com/GoogleCloudPlatform/declarative-resource-client-library/services/google/gkehub<%= dcl_version(version) -%>"
)

func TestAccGkeHubFeatureMembership_gkehubFeatureAcmUpdate(t *testing.T) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"testing"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
gkehub "github.com/GoogleCloudPlatform/declarative-resource-client-library/services/google/gkehub/beta"
gkehub "github.com/GoogleCloudPlatform/declarative-resource-client-library/services/google/gkehub<%= dcl_version(version) -%>"
)

func TestAccGKEHubFeature_gkehubFeatureMciUpdate(t *testing.T) {
Expand Down
3 changes: 3 additions & 0 deletions mmv1/third_party/terraform/utils/provider.go.erb
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,9 @@ end # products.each do
"google_monitoring_monitored_project": resourceMonitoringMonitoredProject(),
<% end -%>
"google_org_policy_policy": resourceOrgPolicyPolicy(),
<% if version == 'private' -%>
"google_os_config_os_policy_assignment": resourceOsConfigOsPolicyAssignment(),
<% end -%>
"google_privateca_certificate_template": resourcePrivatecaCertificateTemplate(),
},
// ------------------------------------
Expand Down
8 changes: 5 additions & 3 deletions tpgtools/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ func main() {
}
if *version == GA_VERSION {
terraformResourceDirectory = "google"
} else if *version == ALPHA_VERSION {
terraformResourceDirectory = "google-private"
}

for _, resource := range resourcesForVersion {
Expand Down Expand Up @@ -266,10 +268,10 @@ func generateSerializationLogic(specs map[Version][]*Resource) {
for _, res := range resList {
var pkgName, pkgPath string
pkgName = res.Package() + v.SerializationSuffix
if v == BETA_VERSION {
pkgPath = path.Join(res.Package(), v.V)
} else {
if v == GA_VERSION {
pkgPath = res.Package()
} else {
pkgPath = path.Join(res.Package(), v.V)
}

if _, ok := packageMap[pkgPath]; !ok {
Expand Down
18 changes: 9 additions & 9 deletions tpgtools/product.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package main

import (
"log"
"regexp"
"strings"

"github.com/golang/glog"
Expand All @@ -18,6 +17,9 @@ type ProductMetadata struct {
// ProductName is the case accounted (snake case) name of the product
// that the resource belongs to.
ProductName string
// DCL name for the product. Used for correctly casing product name for
// references within the DCL (BasePath etc)
DCLProductName string
}

var productOverrides map[string]Overrides = make(map[string]Overrides, 0)
Expand All @@ -28,19 +30,17 @@ func GetProductMetadataFromDocument(document *openapi.Document, packagePath stri
productOverrides[packagePath] = loadOverrides(packagePath, "tpgtools_product.yaml")
}
title := getProductTitle(document.Info.Title, packagePath)
productMetadata := NewProductMetadata(packagePath, jsonToSnakeCase(title))
productMetadata := NewProductMetadata(packagePath, title)
return productMetadata
}

func NewProductMetadata(packagePath, productName string) *ProductMetadata {
if regexp.MustCompile("[A-Z]+").Match([]byte(productName)) {
log.Fatalln("error - expected product name to be snakecase")
}
packageName := strings.Split(packagePath, "/")[0]
return &ProductMetadata{
PackagePath: packagePath,
PackageName: packageName,
ProductName: productName,
PackagePath: packagePath,
PackageName: packageName,
ProductName: jsonToSnakeCase(productName),
DCLProductName: productName,
}
}

Expand Down Expand Up @@ -125,7 +125,7 @@ func getProductTitle(documentTitle, packagePath string) string {
// ProductType is the title-cased product name of a resource. For example,
// "NetworkServices".
func (pm *ProductMetadata) ProductType() string {
return snakeToTitleCase(pm.ProductName)
return pm.DCLProductName
}

func (pm *ProductMetadata) DocsSection() string {
Expand Down
14 changes: 4 additions & 10 deletions tpgtools/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,12 +185,6 @@ func (r Resource) TerraformName() string {
return "google_" + r.Path()
}

// Type is the title-cased name of a resource, for printing information about
// the type". For example, "Instance".
func (r Resource) Type() string {
return snakeToTitleCase(r.DCLName())
}

// PathType is the title-cased name of a resource preceded by its package,
// often used to namespace functions. For example, "RedisInstance".
func (r Resource) PathType() string {
Expand Down Expand Up @@ -663,7 +657,7 @@ func (r Resource) getSamples(docs bool) []Sample {
}

func (r *Resource) getSampleAccessoryFolder() string {
resourceType := strings.ToLower(r.Type())
resourceType := strings.ToLower(r.DCLTitle())
packageName := strings.ToLower(r.productMetadata.PackageName)
sampleAccessoryFolder := path.Join(*tPath, packageName, "samples", resourceType)
return sampleAccessoryFolder
Expand Down Expand Up @@ -754,7 +748,7 @@ func (r *Resource) loadDCLSamples() []Sample {
sampleAccessoryFolder := r.getSampleAccessoryFolder()
packagePath := r.productMetadata.PackagePath
version := r.versionMetadata.V
resourceType := r.Type()
resourceType := r.DCLTitle()
sampleFriendlyMetaPath := path.Join(sampleAccessoryFolder, "meta.yaml")
samples := []Sample{}

Expand All @@ -763,7 +757,7 @@ func (r *Resource) loadDCLSamples() []Sample {
}

// Samples appear in the root product folder
packagePath = strings.Split(packagePath, "beta")[0]
packagePath = strings.Split(packagePath, "/")[0]
samplesPath := path.Join(*fPath, packagePath, "samples")
files, err := ioutil.ReadDir(samplesPath)
if err != nil {
Expand Down Expand Up @@ -810,7 +804,7 @@ func (r *Resource) loadDCLSamples() []Sample {

if !versionMatch {
continue
} else if primaryResourceName != resourceType {
} else if !strings.EqualFold(primaryResourceName, resourceType) {
glog.Errorf("skipping %s since no match with %s.", primaryResourceName, resourceType)
continue
}
Expand Down
13 changes: 13 additions & 0 deletions tpgtools/serialization_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,21 @@ import (

cloudresourcemanager "github.com/GoogleCloudPlatform/declarative-resource-client-library/services/google/cloudresourcemanager"
cloudresourcemanagerBeta "github.com/GoogleCloudPlatform/declarative-resource-client-library/services/google/cloudresourcemanager/beta"
cloudresourcemanagerAlpha "github.com/GoogleCloudPlatform/declarative-resource-client-library/services/google/cloudresourcemanager/alpha"
)

func serializeAlphaProjectToHCL(r cloudresourcemanagerAlpha.Project, hasGAEquivalent bool) (string, error) {
b, err := json.Marshal(r)
if err != nil {
return "", err
}
var m map[string]interface{}
if err := json.Unmarshal(b, &m); err != nil {
return "", err
}
return serializeProjectToHCL(m, hasGAEquivalent)
}

func serializeBetaProjectToHCL(r cloudresourcemanagerBeta.Project, hasGAEquivalent bool) (string, error) {
b, err := json.Marshal(r)
if err != nil {
Expand Down
40 changes: 24 additions & 16 deletions tpgtools/templates/resource.go.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ func resource{{$.PathType}}Create(d *schema.ResourceData, meta interface{}) erro
{{- end -}}
{{ end }}

obj := &{{$.Package}}.{{$.Type}}{
obj := &{{$.Package}}.{{$.DCLTitle}}{
{{- range $v := .Properties }}
{{- if and ($v.Settable) ($v.StateGetter) }}
{{$v.PackageName}}: {{$v.StateGetter}},
Expand Down Expand Up @@ -269,17 +269,17 @@ should be converted to use the DCL's ID method, so normalization can be uniform.
{{- if $.AppendToBasePath }}
client.Config.BasePath += "{{$.AppendToBasePath}}"
{{- end }}
res, err := client.Apply{{$.Type}}(context.Background(), obj, createDirective...)
res, err := client.Apply{{$.DCLTitle}}(context.Background(), obj, createDirective...)

if _, ok := err.(dcl.DiffAfterApplyError); ok {
log.Printf("[DEBUG] Diff after apply returned from the DCL: %s", err)
} else if err != nil {
// The resource didn't actually create
d.SetId("")
return fmt.Errorf("Error creating {{$.Type}}: %s", err)
return fmt.Errorf("Error creating {{$.DCLTitle}}: %s", err)
}

log.Printf("[DEBUG] Finished creating {{$.Type}} %q: %#v", d.Id(), res)
log.Printf("[DEBUG] Finished creating {{$.DCLTitle}} %q: %#v", d.Id(), res)

{{ if $.HasServerGeneratedName }}
{{ range $v := .Properties -}}
Expand Down Expand Up @@ -318,7 +318,7 @@ func resource{{$.PathType}}Read(d *schema.ResourceData, meta interface{}) error
{{- end -}}
{{ end }}

obj := &{{$.Package}}.{{$.Type}}{
obj := &{{$.Package}}.{{$.DCLTitle}}{
{{- range $v := .Properties }}
{{- if ($v.StateGetter) }}
{{$v.PackageName}}: {{$v.StateGetter}},
Expand All @@ -343,7 +343,7 @@ func resource{{$.PathType}}Read(d *schema.ResourceData, meta interface{}) error
{{- if $.AppendToBasePath }}
client.Config.BasePath += "{{$.AppendToBasePath}}"
{{- end }}
res, err := client.Get{{$.Type}}(context.Background(), obj)
res, err := client.Get{{$.DCLTitle}}(context.Background(), obj)
if err != nil {
resourceName := fmt.Sprintf("{{$.PathType}} %q", d.Id())
return handleNotFoundDCLError(err, d, resourceName)
Expand Down Expand Up @@ -373,7 +373,7 @@ func resource{{$.PathType}}Update(d *schema.ResourceData, meta interface{}) erro
{{- end -}}
{{ end }}

obj := &{{$.Package}}.{{$.Type}}{
obj := &{{$.Package}}.{{$.DCLTitle}}{
{{- range $v := .Properties }}
{{- if ($v.StateGetter) }}
{{$v.PackageName}}: {{$v.StateGetter}},
Expand All @@ -383,7 +383,7 @@ func resource{{$.PathType}}Update(d *schema.ResourceData, meta interface{}) erro

{{- if $.StateHint }}
// Construct state hint from old values
old := &{{$.Package}}.{{$.Type}}{
old := &{{$.Package}}.{{$.DCLTitle}}{
{{- range $v := .Properties }}
{{- if ($v.StateGetter) }}
{{$v.PackageName}}: {{$v.ChangeStateGetter}},
Expand Down Expand Up @@ -419,17 +419,17 @@ func resource{{$.PathType}}Update(d *schema.ResourceData, meta interface{}) erro
{{- if $.AppendToBasePath }}
client.Config.BasePath += "{{$.AppendToBasePath}}"
{{- end }}
res, err := client.Apply{{$.Type}}(context.Background(), obj, directive...)
res, err := client.Apply{{$.DCLTitle}}(context.Background(), obj, directive...)

if _, ok := err.(dcl.DiffAfterApplyError); ok {
log.Printf("[DEBUG] Diff after apply returned from the DCL: %s", err)
} else if err != nil {
// The resource didn't actually create
d.SetId("")
return fmt.Errorf("Error updating {{$.Type}}: %s", err)
return fmt.Errorf("Error updating {{$.DCLTitle}}: %s", err)
}

log.Printf("[DEBUG] Finished creating {{$.Type}} %q: %#v", d.Id(), res)
log.Printf("[DEBUG] Finished creating {{$.DCLTitle}} %q: %#v", d.Id(), res)

return resource{{$.PathType}}Read(d, meta)
}
Expand All @@ -447,7 +447,7 @@ func resource{{$.PathType}}Delete(d *schema.ResourceData, meta interface{}) erro
{{- end -}}
{{ end }}

obj := &{{$.Package}}.{{$.Type}}{
obj := &{{$.Package}}.{{$.DCLTitle}}{
{{- range $v := .Properties }}
{{- if ($v.StateGetter) }}
{{$v.PackageName}}: {{$v.StateGetter}},
Expand Down Expand Up @@ -480,7 +480,7 @@ func resource{{$.PathType}}Delete(d *schema.ResourceData, meta interface{}) erro
}
{{- end }}

log.Printf("[DEBUG] Deleting {{$.Type}} %q", d.Id())
log.Printf("[DEBUG] Deleting {{$.DCLTitle}} %q", d.Id())
userAgent, err := generateUserAgentString(d, config.userAgent)
if err != nil {
return err
Expand All @@ -498,11 +498,11 @@ func resource{{$.PathType}}Delete(d *schema.ResourceData, meta interface{}) erro
{{- if $.AppendToBasePath }}
client.Config.BasePath += "{{$.AppendToBasePath}}"
{{- end }}
if err := client.Delete{{$.Type}}(context.Background(), obj); err != nil {
return fmt.Errorf("Error deleting {{$.Type}}: %s", err)
if err := client.Delete{{$.DCLTitle}}(context.Background(), obj); err != nil {
return fmt.Errorf("Error deleting {{$.DCLTitle}}: %s", err)
}

log.Printf("[DEBUG] Finished deleting {{$.Type}} %q", d.Id())
log.Printf("[DEBUG] Finished deleting {{$.DCLTitle}} %q", d.Id())
return nil
}

Expand Down Expand Up @@ -560,7 +560,11 @@ func expand{{$.PathType}}{{$v.PackagePath}}Collapsed(d *schema.ResourceData) *{{
{{ if $v.IsArray -}}
func expand{{$.PathType}}{{$v.PackagePath}}Array(o interface{}) []{{$.Package}}.{{$v.ObjectType}} {
if o == nil {
{{- if $v.Computed }}
return nil
{{- else }}
return make([]{{$.Package}}.{{$v.ObjectType}}, 0)
{{- end }}
}

{{ if $v.IsSet -}}
Expand All @@ -569,7 +573,11 @@ func expand{{$.PathType}}{{$v.PackagePath}}Array(o interface{}) []{{$.Package}}.

objs := o.([]interface{})
if len(objs) == 0 {
{{- if $v.Computed }}
return nil
{{- else }}
return make([]{{$.Package}}.{{$v.ObjectType}}, 0)
{{- end }}
}

items := make([]{{$.Package}}.{{$v.ObjectType}}, 0, len(objs))
Expand Down
2 changes: 1 addition & 1 deletion tpgtools/templates/resource.html.markdown.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ This resource provides the following

## Import
{{/* TODO excluded imports */}}
{{$.Type}} can be imported using any of these accepted formats:
{{$.DCLTitle}} can be imported using any of these accepted formats:

```
{{- range $format := $.ImportFormats }}
Expand Down
8 changes: 4 additions & 4 deletions tpgtools/templates/serialization.go.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ func DCLToTerraformSampleName(service, resource string) (string, string, error)
{{- range $res := $resList }}
{{- if not $res.IsAlternateLocation }}
case "{{$res.DCLPackage}}{{replace $res.DCLName "_" "" -1}}":
return "{{$res.ProductType }}", "{{ $res.Type }}", nil
return "{{$res.ProductType }}", "{{ $res.DCLTitle }}", nil
{{- end }}
{{- end }}
default:
Expand All @@ -95,7 +95,7 @@ func ConvertSampleJSONToHCL(resourceType string, version string, hasGAEquivalent
switch resourceType {
{{- range $res := $resList }}
case "{{$res.PathType}}":
r := &{{$res.Package}}{{$version.SerializationSuffix}}.{{$res.Type}}{}
r := &{{$res.Package}}{{$version.SerializationSuffix}}.{{$res.DCLTitle}}{}
if err := json.Unmarshal(b, r); err != nil {
return "", err
}
Expand All @@ -112,7 +112,7 @@ func ConvertSampleJSONToHCL(resourceType string, version string, hasGAEquivalent
switch resourceType {
{{- range $res := $resList }}
case "{{$res.PathType}}":
r := &{{$res.Package}}{{$version.SerializationSuffix}}.{{$res.Type}}{}
r := &{{$res.Package}}{{$version.SerializationSuffix}}.{{$res.DCLTitle}}{}
if err := json.Unmarshal(b, r); err != nil {
return "", err
}
Expand All @@ -139,7 +139,7 @@ func ConvertSampleJSONToHCL(resourceType string, version string, hasGAEquivalent
// the crucial point is that `terraform import; terraform apply` will not produce
// any changes. We do not validate that the resource specified will pass terraform
// validation unless is an object returned from the API after an Apply.
func {{ $res.PathType}}{{$version.SerializationSuffix}}AsHCL(r {{$res.Package}}{{$version.SerializationSuffix}}.{{$res.Type}}, hasGAEquivalent bool) (string, error) {
func {{ $res.PathType}}{{$version.SerializationSuffix}}AsHCL(r {{$res.Package}}{{$version.SerializationSuffix}}.{{$res.DCLTitle}}, hasGAEquivalent bool) (string, error) {
outputConfig := "resource \"{{$res.TerraformName}}\" \"output\" {\n"
{{- range $field := $res.Properties}}
{{- if $field.Settable }}
Expand Down
Loading

0 comments on commit a0343e2

Please sign in to comment.