Skip to content

Commit f245c50

Browse files
Add ControlPlaneAccess support for Apigee (#12825) (#9709)
[upstream:208b384af6f750bfbf5435eb3749f48aa1de6b0c] Signed-off-by: Modular Magician <[email protected]>
1 parent a62de33 commit f245c50

7 files changed

+724
-2
lines changed

.changelog/12825.txt

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:new-resource
2+
`google_control_plane_access`
3+
```

google-beta/provider/provider_mmv1_resources.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -554,9 +554,9 @@ var handwrittenIAMDatasources = map[string]*schema.Resource{
554554
}
555555

556556
// Resources
557-
// Generated resources: 637
557+
// Generated resources: 638
558558
// Generated IAM resources: 312
559-
// Total generated resources: 949
559+
// Total generated resources: 950
560560
var generatedResources = map[string]*schema.Resource{
561561
"google_folder_access_approval_settings": accessapproval.ResourceAccessApprovalFolderSettings(),
562562
"google_organization_access_approval_settings": accessapproval.ResourceAccessApprovalOrganizationSettings(),
@@ -601,6 +601,7 @@ var generatedResources = map[string]*schema.Resource{
601601
"google_api_gateway_gateway_iam_policy": tpgiamresource.ResourceIamPolicy(apigateway.ApiGatewayGatewayIamSchema, apigateway.ApiGatewayGatewayIamUpdaterProducer, apigateway.ApiGatewayGatewayIdParseFunc),
602602
"google_apigee_addons_config": apigee.ResourceApigeeAddonsConfig(),
603603
"google_apigee_app_group": apigee.ResourceApigeeAppGroup(),
604+
"google_apigee_control_plane_access": apigee.ResourceApigeeControlPlaneAccess(),
604605
"google_apigee_developer": apigee.ResourceApigeeDeveloper(),
605606
"google_apigee_dns_zone": apigee.ResourceApigeeDnsZone(),
606607
"google_apigee_endpoint_attachment": apigee.ResourceApigeeEndpointAttachment(),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,338 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
// ----------------------------------------------------------------------------
5+
//
6+
// *** AUTO GENERATED CODE *** Type: MMv1 ***
7+
//
8+
// ----------------------------------------------------------------------------
9+
//
10+
// This code is generated by Magic Modules using the following:
11+
//
12+
// Configuration: https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/products/apigee/ControlPlaneAccess.yaml
13+
// Template: https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/templates/terraform/resource.go.tmpl
14+
//
15+
// DO NOT EDIT this file directly. Any changes made to this file will be
16+
// overwritten during the next generation cycle.
17+
//
18+
// ----------------------------------------------------------------------------
19+
20+
package apigee
21+
22+
import (
23+
"fmt"
24+
"log"
25+
"net/http"
26+
"reflect"
27+
"strings"
28+
"time"
29+
30+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
31+
32+
"github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource"
33+
transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport"
34+
)
35+
36+
func ResourceApigeeControlPlaneAccess() *schema.Resource {
37+
return &schema.Resource{
38+
Create: resourceApigeeControlPlaneAccessCreate,
39+
Read: resourceApigeeControlPlaneAccessRead,
40+
Update: resourceApigeeControlPlaneAccessUpdate,
41+
Delete: resourceApigeeControlPlaneAccessDelete,
42+
43+
Importer: &schema.ResourceImporter{
44+
State: resourceApigeeControlPlaneAccessImport,
45+
},
46+
47+
Timeouts: &schema.ResourceTimeout{
48+
Create: schema.DefaultTimeout(20 * time.Minute),
49+
Update: schema.DefaultTimeout(20 * time.Minute),
50+
Delete: schema.DefaultTimeout(20 * time.Minute),
51+
},
52+
53+
Schema: map[string]*schema.Schema{
54+
"name": {
55+
Type: schema.TypeString,
56+
Required: true,
57+
ForceNew: true,
58+
Description: `Name of the Apigee organization.`,
59+
},
60+
"analytics_publisher_identities": {
61+
Type: schema.TypeList,
62+
Optional: true,
63+
Description: `Array of service accounts authorized to publish analytics data to the control plane, each specified using the following format: 'serviceAccount:service-account-name'.
64+
65+
The 'service-account-name' is formatted like an email address. For example: serviceAccount@my_project_id.iam.gserviceaccount.com
66+
67+
You might specify multiple service accounts, for example, if you have multiple environments and wish to assign a unique service account to each one.`,
68+
Elem: &schema.Schema{
69+
Type: schema.TypeString,
70+
},
71+
},
72+
"synchronizer_identities": {
73+
Type: schema.TypeList,
74+
Optional: true,
75+
Description: `Array of service accounts to grant access to control plane resources (for the Synchronizer component), each specified using the following format: 'serviceAccount:service-account-name'.
76+
77+
The 'service-account-name' is formatted like an email address. For example: serviceAccount@my_project_id.iam.gserviceaccount.com
78+
79+
You might specify multiple service accounts, for example, if you have multiple environments and wish to assign a unique service account to each one.
80+
81+
The service accounts must have **Apigee Synchronizer Manager** role. See also [Create service accounts](https://cloud.google.com/apigee/docs/hybrid/v1.8/sa-about#create-the-service-accounts).`,
82+
Elem: &schema.Schema{
83+
Type: schema.TypeString,
84+
},
85+
},
86+
},
87+
UseJSONNumber: true,
88+
}
89+
}
90+
91+
func resourceApigeeControlPlaneAccessCreate(d *schema.ResourceData, meta interface{}) error {
92+
config := meta.(*transport_tpg.Config)
93+
userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent)
94+
if err != nil {
95+
return err
96+
}
97+
98+
obj := make(map[string]interface{})
99+
synchronizerIdentitiesProp, err := expandApigeeControlPlaneAccessSynchronizerIdentities(d.Get("synchronizer_identities"), d, config)
100+
if err != nil {
101+
return err
102+
} else if v, ok := d.GetOkExists("synchronizer_identities"); ok || !reflect.DeepEqual(v, synchronizerIdentitiesProp) {
103+
obj["synchronizerIdentities"] = synchronizerIdentitiesProp
104+
}
105+
analyticsPublisherIdentitiesProp, err := expandApigeeControlPlaneAccessAnalyticsPublisherIdentities(d.Get("analytics_publisher_identities"), d, config)
106+
if err != nil {
107+
return err
108+
} else if v, ok := d.GetOkExists("analytics_publisher_identities"); ok || !reflect.DeepEqual(v, analyticsPublisherIdentitiesProp) {
109+
obj["analyticsPublisherIdentities"] = analyticsPublisherIdentitiesProp
110+
}
111+
112+
url, err := tpgresource.ReplaceVars(d, config, "{{ApigeeBasePath}}organizations/{{name}}/controlPlaneAccess")
113+
if err != nil {
114+
return err
115+
}
116+
117+
log.Printf("[DEBUG] Creating new ControlPlaneAccess: %#v", obj)
118+
billingProject := ""
119+
120+
// err == nil indicates that the billing_project value was found
121+
if bp, err := tpgresource.GetBillingProject(d, config); err == nil {
122+
billingProject = bp
123+
}
124+
125+
headers := make(http.Header)
126+
res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
127+
Config: config,
128+
Method: "PATCH",
129+
Project: billingProject,
130+
RawURL: url,
131+
UserAgent: userAgent,
132+
Body: obj,
133+
Timeout: d.Timeout(schema.TimeoutCreate),
134+
Headers: headers,
135+
})
136+
if err != nil {
137+
return fmt.Errorf("Error creating ControlPlaneAccess: %s", err)
138+
}
139+
140+
// Store the ID now
141+
id, err := tpgresource.ReplaceVars(d, config, "organizations/{{name}}/controlPlaneAccess")
142+
if err != nil {
143+
return fmt.Errorf("Error constructing id: %s", err)
144+
}
145+
d.SetId(id)
146+
147+
// Use the resource in the operation response to populate
148+
// identity fields and d.Id() before read
149+
var opRes map[string]interface{}
150+
err = ApigeeOperationWaitTimeWithResponse(
151+
config, res, &opRes, "Creating ControlPlaneAccess", userAgent,
152+
d.Timeout(schema.TimeoutCreate))
153+
if err != nil {
154+
// The resource didn't actually create
155+
d.SetId("")
156+
157+
return fmt.Errorf("Error waiting to create ControlPlaneAccess: %s", err)
158+
}
159+
160+
// This may have caused the ID to update - update it if so.
161+
id, err = tpgresource.ReplaceVars(d, config, "organizations/{{name}}/controlPlaneAccess")
162+
if err != nil {
163+
return fmt.Errorf("Error constructing id: %s", err)
164+
}
165+
d.SetId(id)
166+
167+
log.Printf("[DEBUG] Finished creating ControlPlaneAccess %q: %#v", d.Id(), res)
168+
169+
return resourceApigeeControlPlaneAccessRead(d, meta)
170+
}
171+
172+
func resourceApigeeControlPlaneAccessRead(d *schema.ResourceData, meta interface{}) error {
173+
config := meta.(*transport_tpg.Config)
174+
userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent)
175+
if err != nil {
176+
return err
177+
}
178+
179+
url, err := tpgresource.ReplaceVars(d, config, "{{ApigeeBasePath}}organizations/{{name}}/controlPlaneAccess")
180+
if err != nil {
181+
return err
182+
}
183+
184+
billingProject := ""
185+
186+
// err == nil indicates that the billing_project value was found
187+
if bp, err := tpgresource.GetBillingProject(d, config); err == nil {
188+
billingProject = bp
189+
}
190+
191+
headers := make(http.Header)
192+
res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
193+
Config: config,
194+
Method: "GET",
195+
Project: billingProject,
196+
RawURL: url,
197+
UserAgent: userAgent,
198+
Headers: headers,
199+
})
200+
if err != nil {
201+
return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("ApigeeControlPlaneAccess %q", d.Id()))
202+
}
203+
204+
if err := d.Set("synchronizer_identities", flattenApigeeControlPlaneAccessSynchronizerIdentities(res["synchronizerIdentities"], d, config)); err != nil {
205+
return fmt.Errorf("Error reading ControlPlaneAccess: %s", err)
206+
}
207+
if err := d.Set("analytics_publisher_identities", flattenApigeeControlPlaneAccessAnalyticsPublisherIdentities(res["analyticsPublisherIdentities"], d, config)); err != nil {
208+
return fmt.Errorf("Error reading ControlPlaneAccess: %s", err)
209+
}
210+
211+
return nil
212+
}
213+
214+
func resourceApigeeControlPlaneAccessUpdate(d *schema.ResourceData, meta interface{}) error {
215+
config := meta.(*transport_tpg.Config)
216+
userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent)
217+
if err != nil {
218+
return err
219+
}
220+
221+
billingProject := ""
222+
223+
obj := make(map[string]interface{})
224+
synchronizerIdentitiesProp, err := expandApigeeControlPlaneAccessSynchronizerIdentities(d.Get("synchronizer_identities"), d, config)
225+
if err != nil {
226+
return err
227+
} else if v, ok := d.GetOkExists("synchronizer_identities"); ok || !reflect.DeepEqual(v, synchronizerIdentitiesProp) {
228+
obj["synchronizerIdentities"] = synchronizerIdentitiesProp
229+
}
230+
analyticsPublisherIdentitiesProp, err := expandApigeeControlPlaneAccessAnalyticsPublisherIdentities(d.Get("analytics_publisher_identities"), d, config)
231+
if err != nil {
232+
return err
233+
} else if v, ok := d.GetOkExists("analytics_publisher_identities"); ok || !reflect.DeepEqual(v, analyticsPublisherIdentitiesProp) {
234+
obj["analyticsPublisherIdentities"] = analyticsPublisherIdentitiesProp
235+
}
236+
237+
url, err := tpgresource.ReplaceVars(d, config, "{{ApigeeBasePath}}organizations/{{name}}/controlPlaneAccess")
238+
if err != nil {
239+
return err
240+
}
241+
242+
log.Printf("[DEBUG] Updating ControlPlaneAccess %q: %#v", d.Id(), obj)
243+
headers := make(http.Header)
244+
updateMask := []string{}
245+
246+
if d.HasChange("synchronizer_identities") {
247+
updateMask = append(updateMask, "synchronizerIdentities")
248+
}
249+
250+
if d.HasChange("analytics_publisher_identities") {
251+
updateMask = append(updateMask, "analyticsPublisherIdentities")
252+
}
253+
// updateMask is a URL parameter but not present in the schema, so ReplaceVars
254+
// won't set it
255+
url, err = transport_tpg.AddQueryParams(url, map[string]string{"updateMask": strings.Join(updateMask, ",")})
256+
if err != nil {
257+
return err
258+
}
259+
260+
// err == nil indicates that the billing_project value was found
261+
if bp, err := tpgresource.GetBillingProject(d, config); err == nil {
262+
billingProject = bp
263+
}
264+
265+
// if updateMask is empty we are not updating anything so skip the post
266+
if len(updateMask) > 0 {
267+
res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
268+
Config: config,
269+
Method: "PATCH",
270+
Project: billingProject,
271+
RawURL: url,
272+
UserAgent: userAgent,
273+
Body: obj,
274+
Timeout: d.Timeout(schema.TimeoutUpdate),
275+
Headers: headers,
276+
})
277+
278+
if err != nil {
279+
return fmt.Errorf("Error updating ControlPlaneAccess %q: %s", d.Id(), err)
280+
} else {
281+
log.Printf("[DEBUG] Finished updating ControlPlaneAccess %q: %#v", d.Id(), res)
282+
}
283+
284+
err = ApigeeOperationWaitTime(
285+
config, res, "Updating ControlPlaneAccess", userAgent,
286+
d.Timeout(schema.TimeoutUpdate))
287+
288+
if err != nil {
289+
return err
290+
}
291+
}
292+
293+
return resourceApigeeControlPlaneAccessRead(d, meta)
294+
}
295+
296+
func resourceApigeeControlPlaneAccessDelete(d *schema.ResourceData, meta interface{}) error {
297+
log.Printf("[WARNING] Apigee ControlPlaneAccess resources"+
298+
" cannot be deleted from Google Cloud. The resource %s will be removed from Terraform"+
299+
" state, but will still be present on Google Cloud.", d.Id())
300+
d.SetId("")
301+
302+
return nil
303+
}
304+
305+
func resourceApigeeControlPlaneAccessImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
306+
config := meta.(*transport_tpg.Config)
307+
if err := tpgresource.ParseImportId([]string{
308+
"^organizations/(?P<name>[^/]+)/controlPlaneAccess$",
309+
"^(?P<name>[^/]+)$",
310+
}, d, config); err != nil {
311+
return nil, err
312+
}
313+
314+
// Replace import id for the resource id
315+
id, err := tpgresource.ReplaceVars(d, config, "organizations/{{name}}/controlPlaneAccess")
316+
if err != nil {
317+
return nil, fmt.Errorf("Error constructing id: %s", err)
318+
}
319+
d.SetId(id)
320+
321+
return []*schema.ResourceData{d}, nil
322+
}
323+
324+
func flattenApigeeControlPlaneAccessSynchronizerIdentities(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
325+
return v
326+
}
327+
328+
func flattenApigeeControlPlaneAccessAnalyticsPublisherIdentities(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
329+
return v
330+
}
331+
332+
func expandApigeeControlPlaneAccessSynchronizerIdentities(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
333+
return v, nil
334+
}
335+
336+
func expandApigeeControlPlaneAccessAnalyticsPublisherIdentities(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
337+
return v, nil
338+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
resource: 'google_apigee_control_plane_access'
2+
generation_type: 'mmv1'
3+
source_file: 'products/apigee/ControlPlaneAccess.yaml'
4+
api_service_name: 'apigee.googleapis.com'
5+
api_version: 'v1'
6+
api_resource_type_kind: 'ControlPlaneAccess'
7+
fields:
8+
- field: 'analytics_publisher_identities'
9+
- field: 'name'
10+
provider_only: true
11+
- field: 'synchronizer_identities'

0 commit comments

Comments
 (0)