Skip to content

Commit

Permalink
Convert templates for custom_update, decoders, encoders, extra_schema…
Browse files Browse the repository at this point in the history
…_entry, post_create (GoogleCloudPlatform#10463)
  • Loading branch information
zli82016 authored and pcostell committed Jul 16, 2024
1 parent 8bc8a6d commit 29e97f5
Show file tree
Hide file tree
Showing 176 changed files with 3,754 additions and 9 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
{{- /*
The license inside this block applies to this file
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.
*/}}
userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent)
if err != nil {
return err
}

billingProject := ""

d.Partial(true)

if d.HasChange("roles") {
url, err := tpgresource.ReplaceVars(d, config, "{{"{{"}}CloudIdentityBasePath{{"}}"}}{{"{{"}}name{{"}}"}}:modifyMembershipRoles")
if err != nil {
return err
}

// err == nil indicates that the billing_project value was found
if bp, err := tpgresource.GetBillingProject(d, config); err == nil {
billingProject = bp
}

// Return object for modifyMembershipRoles (we build request object from scratch, without using `obj`)
b, a := d.GetChange("roles")
before := b.(*schema.Set)
after := a.(*schema.Set)

ignoreUpdateR := make(map[string]struct{})
addRoleList := after.Difference(before).List()
removeRoleList := before.Difference(after).List()

var updateRolesParams []map[string]interface{}
for _, addR := range addRoleList {
ar := addR.(map[string]interface{})["name"].(string)
ae := addR.(map[string]interface{})["expiry_detail"].([]interface {})
for _, removeR := range removeRoleList {
if ar == removeR.(map[string]interface{})["name"].(string) {
ignoreUpdateR[ar] = struct{}{}
var updateR map[string]interface{}
if len(ae) == 0 {
updateR = map[string]interface{}{"name": ar}
} else {
updateR = map[string]interface{}{"name": ar, "expiry_detail": ae[0]}
}
updateP := map[string]interface{}{"field_mask": "expiryDetail.expire_time", "membership_role": updateR}
updateRolesParams = append(updateRolesParams, updateP)
}
}
}

var addRoles []map[string]interface{}
for _, r := range addRoleList {
name := r.(map[string]interface{})["name"].(string)
if _, ignore := ignoreUpdateR[name]; ignore {
continue
}
expiryDetail := r.(map[string]interface{})["expiry_detail"].([]interface {})
if len(expiryDetail) == 0 {
addRoles = append(addRoles, map[string]interface{}{"name": name})
} else {
addRoles = append(addRoles, map[string]interface{}{"name": name, "expiry_detail": expiryDetail[0]})
}
}
var removeRoles []string
for _, r := range removeRoleList {
name := r.(map[string]interface{})["name"].(string)
if _, ignore := ignoreUpdateR[name]; ignore {
continue
}
removeRoles = append(removeRoles, name)
}

// ref: https://cloud.google.com/identity/docs/reference/rest/v1/groups.memberships/modifyMembershipRoles#request-body
// Only single operation per request is allowed.
if len(removeRoles) > 0 {
res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
Config: config,
Method: "POST",
Project: billingProject,
RawURL: url,
UserAgent: userAgent,
Body: map[string]interface{}{"removeRoles": removeRoles},
Timeout: d.Timeout(schema.TimeoutUpdate),
})
if err != nil {
return fmt.Errorf("Error removing GroupMembership %q: %s", d.Id(), err)
} else {
log.Printf("[DEBUG] Finished removing GroupMembership %q: %#v", d.Id(), res)
}
}
if len(updateRolesParams) > 0 {
res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
Config: config,
Method: "POST",
Project: billingProject,
RawURL: url,
UserAgent: userAgent,
Body: map[string]interface{}{"updateRolesParams": updateRolesParams},
Timeout: d.Timeout(schema.TimeoutUpdate),
})
if err != nil {
return fmt.Errorf("Error updating GroupMembership %q: %s", d.Id(), err)
} else {
log.Printf("[DEBUG] Finished updating GroupMembership %q: %#v", d.Id(), res)
}
}
if len(addRoles) > 0 {
res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
Config: config,
Method: "POST",
Project: billingProject,
RawURL: url,
UserAgent: userAgent,
Body: map[string]interface{}{"addRoles": addRoles},
Timeout: d.Timeout(schema.TimeoutUpdate),
})
if err != nil {
return fmt.Errorf("Error adding GroupMembership %q: %s", d.Id(), err)
} else {
log.Printf("[DEBUG] Finished adding GroupMembership %q: %#v", d.Id(), res)
}
}
}

d.Partial(false)

return resourceCloudIdentityGroupMembershipRead(d, meta)
18 changes: 18 additions & 0 deletions mmv1/templates/terraform/custom_update/go/secret_version.go.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{{- /*
The license inside this block applies to this file
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.
*/}}
_, err := expandSecretManagerSecretVersionEnabled(d.Get("enabled"), d, config)
if err != nil {
return err
}

return resourceSecretManagerSecretVersionRead(d, meta)
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// The problem we're trying to solve here is that this property is a Project,
// and there are a lot of ways to specify a Project, including the ID vs
// Number, which is something that we can't address in a diffsuppress.
// Since we can't enforce a particular method of entering the project,
// we're just going to have to use whatever the user entered, whether
// it's project/projectName, project/12345, projectName, or 12345.
// The normal behavior of this method would be 'return res' - and that's
// what we'll fall back to if any of our conditions aren't met. Those
// conditions are:
// 1) if the new or old values contain '/', the prefix of that is 'projects'.
// 2) if either is non-numeric, a project with that ID exists.
// 3) the project IDs represented by both the new and old values are the same.
config := meta.(*transport_tpg.Config)

userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent)
if err != nil {
return nil, err
}

new := res["parent"].(string)
old := d.Get("parent").(string)
if strings.HasPrefix(new, "projects/") {
new = strings.Split(new, "/")[1]
}
if strings.HasPrefix(old, "projects/") {
old = strings.Split(old, "/")[1]
}
log.Printf("[DEBUG] Trying to figure out whether to use %s or %s", old, new)
// If there's still a '/' in there, the value must not be a project ID.
if strings.Contains(old, "/") || strings.Contains(new, "/") {
return res, nil
}
// If 'old' isn't entirely numeric, let's assume it's a project ID.
// If it's a project ID
var oldProjId int64
var newProjId int64
if oldVal, err := tpgresource.StringToFixed64(old); err == nil {
log.Printf("[DEBUG] The old value was a real number: %d", oldVal)
oldProjId = oldVal
} else {
pOld, err := config.NewResourceManagerClient(userAgent).Projects.Get(old).Do()
if err != nil {
return res, nil
}
oldProjId = pOld.ProjectNumber
}
if newVal, err := tpgresource.StringToFixed64(new); err == nil {
log.Printf("[DEBUG] The new value was a real number: %d", newVal)
newProjId = newVal
} else {
pNew, err := config.NewResourceManagerClient(userAgent).Projects.Get(new).Do()
if err != nil {
return res, nil
}
newProjId = pNew.ProjectNumber
}
if newProjId == oldProjId {
res["parent"] = d.Get("parent")
}
return res, nil
38 changes: 38 additions & 0 deletions mmv1/templates/terraform/decoders/go/backend_service.go.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{{- /*
The license inside this block applies to this file
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.
*/}}
// We need to pretend IAP isn't there if it's disabled for Terraform to maintain
// BC behaviour with the handwritten resource.
v, ok := res["iap"]
if !ok || v == nil {
delete(res, "iap")
return res, nil
}
m := v.(map[string]interface{})
if ok && m["enabled"] == false {
delete(res, "iap")
}

// Requests with consistentHash will error for specific values of
// localityLbPolicy. However, the API will not remove it if the backend
// service is updated to from supporting to non-supporting localityLbPolicy
// (e.g. RING_HASH to RANDOM), which causes an error on subsequent update.
// In order to prevent errors, we ignore any consistentHash returned
// from the API when the localityLbPolicy doesn't support it.
if v, ok := res["localityLbPolicy"]; ok {
lbPolicy := v.(string)
if lbPolicy != "MAGLEV" && lbPolicy != "RING_HASH" {
delete(res, "consistentHash")
}
}

return res, nil
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{{- /*
The license inside this block applies to this file
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.
*/}}
if paramMap, ok := res["params"]; ok {
params := paramMap.(map[string]interface{})
for _, sp := range sensitiveParams {
if _, apiOk := params[sp]; apiOk {
if _, exists := d.GetOkExists("sensitive_params.0." + sp); exists {
delete(params, sp)
} else {
params[sp] = d.Get("params." + sp)
}
}
}
}

return res, nil
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
res["billing_account"] = strings.TrimPrefix(res["billingAccountName"].(string), "billingAccounts/")
return res, nil
21 changes: 21 additions & 0 deletions mmv1/templates/terraform/decoders/go/cloud_run.go.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{{- /*
The license inside this block applies to this file
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.
*/}}
// metadata is not present if the API returns an error
if obj, ok := res["metadata"]; ok {
if meta, ok := obj.(map[string]interface{}); ok {
res["name"] = meta["name"]
} else {
return nil, fmt.Errorf("Unable to decode 'metadata' block from API response.")
}
}
return res, nil
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
res["name"] = tpgresource.GetResourceNameFromSelfLink(res["name"].(string))
return res, nil
2 changes: 2 additions & 0 deletions mmv1/templates/terraform/decoders/go/compute_network.go.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
res["numericId"] = res["id"] // stores unique id into numericId attribute before it's changed to path format
return res, nil
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Since both sslCertificates and certificateManagerCertificates maps to the same API field (sslCertificates), we need to check the types
// of certificates that exist in the array and decide whether to change the field to certificateManagerCertificate or not.
// The decoder logic depends on the fact that the API does not allow mixed type of certificates and it returns
// certificate manager certificates in the format of //certificatemanager.googleapis.com/projects/*/locations/*/certificates/*
if sslCertificates, ok := res["sslCertificates"].([]interface{}); ok && len(sslCertificates) > 0 {
regPat, _ := regexp.Compile("//certificatemanager.googleapis.com/projects/(.*)/locations/(.*)/certificates/(.*)")

if regPat.MatchString(sslCertificates[0].(string)) {
// It is enough to check only the type of one of the provided certificates beacuse all the certificates should be the same type.
log.Printf("[DEBUG] The field sslCertificates contains certificateManagerCertificates, the field name will be converted to certificateManagerCertificates")
res["certificateManagerCertificates"] = res["sslCertificates"]
delete(res, "sslCertificates")
}
}
return res, nil
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Since both sslCertificates and certificateManagerCertificates maps to the same API field (sslCertificates), we need to check the types
// of certificates that exist in the array and decide whether to change the field to certificateManagerCertificate or not.
// The decoder logic depends on the fact that the API does not allow mixed type of certificates and it returns
// certificate manager certificates in the format of //certificatemanager.googleapis.com/projects/*/locations/*/certificates/*
if sslCertificates, ok := res["sslCertificates"].([]interface{}); ok && len(sslCertificates) > 0 {
regPat, _ := regexp.Compile("//certificatemanager.googleapis.com/projects/(.*)/locations/(.*)/certificates/(.*)")

if regPat.MatchString(sslCertificates[0].(string)) {
// It is enough to check only the type of one of the provided certificates beacuse all the certificates should be the same type.
log.Printf("[DEBUG] The field sslCertificates contains certificateManagerCertificates, the field name will be converted to certificateManagerCertificates")
res["certificateManagerCertificates"] = res["sslCertificates"]
delete(res, "sslCertificates")
}
}
return res, nil
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{{- /*
The license inside this block applies to this file
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.
*/}}
{{- if eq $.TargetVersionName "ga" }}
// Field was renamed in GA API
res["attestationAuthority"] = res["attestation"]
delete(res, "attestation")
{{- else }}
// decoder logic only in GA provider
{{- end }}

return res, nil
Loading

0 comments on commit 29e97f5

Please sign in to comment.