Skip to content

Commit 17610bf

Browse files
modular-magicianRay Xumegan07
authored
Add support for Apigee Sharedflow (#7202) (#13938)
* added sharedflows mmv1 with error * fix indentation issue for sharedflow * add semi auto generated resourceApigeeSharedFlow * remove sharedflow mmv1 and add sharedflow manual provider * adding files for debugging review, test have issue * adding files for debugging review, test have issue * update test, doc, provider for apigee * Update api.yaml remove empty new line * Update api.yaml * Rename resource_apigee_shared_flow_generated_test.go to resource_apigee_shared_flow_test.go * Update resource_apigee_shared_flow.go update import regex, change debug messages to log.Printf * Update mmv1/third_party/terraform/utils/provider.go.erb * update PR to address comments * update test * fix sharedflow attribute update issue, add sharedflow deployment * Update apigee_shared_flow_deployment.html.markdown minor doc fix * Update mmv1/third_party/terraform/utils/provider.go.erb * Update mmv1/third_party/terraform/website/docs/r/apigee_shared_flow.html.markdown * Update resource_apigee_shared_flow_test.go remove commented out (unused) line of code * Delete api.yaml remove api.yaml as it is not needed for handwritten resource. Current repo structure no longer uses aggregated api.yaml * Rename apigee_shared_flow.html.markdown to apigee_sharedflow.html.markdown * Rename apigee_shared_flow_deployment.html.markdown to apigee_sharedflow_deployment.html.markdown * Rename resource_apigee_shared_flow.go to resource_apigee_sharedflow.go * Rename resource_apigee_shared_flow_deployment_test.go to resource_apigee_sharedflow_deployment_test.go * Rename resource_apigee_shared_flow_test.go to resource_apigee_sharedflow_test.go * Rename resource_apigee_shared_flow_sweeper_test.go to resource_apigee_sharedflow_sweeper_test.go * Update resource_apigee_sharedflow.go remove comment lines * Update mmv1/third_party/terraform/resources/resource_apigee_sharedflow.go * Update resource_apigee_sharedflow_deployment_test.go remove unused debugging log * update function name to capitalize * Update resource_apigee_sharedflow_deployment_test.go remove fmt.print * add flowhook * move flowhook doc * Update mmv1/third_party/terraform/tests/resource_apigee_flowhook_test.go * Update mmv1/third_party/terraform/website/docs/r/apigee_flowhook.html.markdown * Update mmv1/third_party/terraform/website/docs/r/apigee_flowhook.html.markdown * Update mmv1/third_party/terraform/tests/resource_apigee_flowhook_test.go * Update resource_apigee_flowhook_test.go remove fmt.print * update some resource attribute properties * Update apigee_flowhook.html.markdown updated `description` and `continue_on_error` as optional * update referenced function naming case --------- Signed-off-by: Modular Magician <[email protected]> Co-authored-by: Ray Xu <[email protected]> Co-authored-by: megan07 <[email protected]>
1 parent 1505df8 commit 17610bf

14 files changed

+1830
-0
lines changed

.changelog/7202.txt

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
```release-note:enhancement
2+
apigee: Added support for resource apigee sharedflow
3+
https://cloud.google.com/apigee/docs/reference/apis/apigee/rest/v1/organizations.sharedflows
4+
5+
Using handwritten approach as create API requires a file to be uploaded as `octet-stream` and mmv1 does not support this pattern
6+
7+
Using direct api call instead of golang library because golang library for this api is broken see: b/265084250
8+
9+
Other relevant background/bugs:
10+
Apigee Sharedflow get method response missing `latestRevisionId` field b/266146203
11+
(recently fixed) Apigee SharedFlow Create Documentation issue b/256739387
12+
```

google/provider.go

+3
Original file line numberDiff line numberDiff line change
@@ -1438,6 +1438,9 @@ func ResourceMapWithErrors() (map[string]*schema.Resource, error) {
14381438
map[string]*schema.Resource{
14391439
// ####### START handwritten resources ###########
14401440
"google_app_engine_application": ResourceAppEngineApplication(),
1441+
"google_apigee_sharedflow": ResourceApigeeSharedFlow(),
1442+
"google_apigee_sharedflow_deployment": ResourceApigeeSharedFlowDeployment(),
1443+
"google_apigee_flowhook": ResourceApigeeFlowhook(),
14411444
"google_bigquery_table": ResourceBigQueryTable(),
14421445
"google_bigtable_gc_policy": ResourceBigtableGCPolicy(),
14431446
"google_bigtable_instance": ResourceBigtableInstance(),

google/resource_apigee_flowhook.go

+240
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,240 @@
1+
package google
2+
3+
import (
4+
"fmt"
5+
"log"
6+
"reflect"
7+
"time"
8+
9+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
10+
)
11+
12+
func ResourceApigeeFlowhook() *schema.Resource {
13+
return &schema.Resource{
14+
Create: resourceApigeeFlowhookCreate,
15+
Read: resourceApigeeFlowhookRead,
16+
Delete: resourceApigeeFlowhookDelete,
17+
18+
Importer: &schema.ResourceImporter{
19+
State: resourceApigeeFlowhookImport,
20+
},
21+
22+
Timeouts: &schema.ResourceTimeout{
23+
Create: schema.DefaultTimeout(20 * time.Minute),
24+
Delete: schema.DefaultTimeout(20 * time.Minute),
25+
},
26+
27+
Schema: map[string]*schema.Schema{
28+
"description": {
29+
Type: schema.TypeString,
30+
Optional: true,
31+
ForceNew: true,
32+
Description: `Description of the flow hook.`,
33+
},
34+
"environment": {
35+
Type: schema.TypeString,
36+
Required: true,
37+
ForceNew: true,
38+
Description: `The resource ID of the environment.`,
39+
},
40+
"flow_hook_point": {
41+
Type: schema.TypeString,
42+
Required: true,
43+
ForceNew: true,
44+
Description: `Where in the API call flow the flow hook is invoked. Must be one of PreProxyFlowHook, PostProxyFlowHook, PreTargetFlowHook, or PostTargetFlowHook.`,
45+
},
46+
"org_id": {
47+
Type: schema.TypeString,
48+
Required: true,
49+
ForceNew: true,
50+
Description: `The Apigee Organization associated with the environment`,
51+
},
52+
"sharedflow": {
53+
Type: schema.TypeString,
54+
Required: true,
55+
ForceNew: true,
56+
Description: `Id of the Sharedflow attaching to a flowhook point.`,
57+
},
58+
"continue_on_error": {
59+
Type: schema.TypeBool,
60+
ForceNew: true,
61+
Optional: true,
62+
Default: true,
63+
Description: `Flag that specifies whether execution should continue if the flow hook throws an exception. Set to true to continue execution. Set to false to stop execution if the flow hook throws an exception. Defaults to true.`,
64+
},
65+
},
66+
UseJSONNumber: true,
67+
}
68+
}
69+
70+
func resourceApigeeFlowhookCreate(d *schema.ResourceData, meta interface{}) error {
71+
config := meta.(*Config)
72+
userAgent, err := generateUserAgentString(d, config.UserAgent)
73+
if err != nil {
74+
return err
75+
}
76+
77+
obj := make(map[string]interface{})
78+
descriptionProp, err := expandApigeeFlowhookDescription(d.Get("description"), d, config)
79+
if err != nil {
80+
return err
81+
} else if v, ok := d.GetOkExists("description"); !isEmptyValue(reflect.ValueOf(descriptionProp)) && (ok || !reflect.DeepEqual(v, descriptionProp)) {
82+
obj["description"] = descriptionProp
83+
}
84+
sharedflowProp, err := expandApigeeFlowhookSharedflow(d.Get("sharedflow"), d, config)
85+
if err != nil {
86+
return err
87+
} else if v, ok := d.GetOkExists("sharedflow"); !isEmptyValue(reflect.ValueOf(sharedflowProp)) && (ok || !reflect.DeepEqual(v, sharedflowProp)) {
88+
obj["sharedFlow"] = sharedflowProp
89+
}
90+
continue_on_errorProp, err := expandApigeeFlowhookContinueOnError(d.Get("continue_on_error"), d, config)
91+
if err != nil {
92+
return err
93+
} else if v, ok := d.GetOkExists("continue_on_error"); !isEmptyValue(reflect.ValueOf(continue_on_errorProp)) && (ok || !reflect.DeepEqual(v, continue_on_errorProp)) {
94+
obj["continueOnError"] = continue_on_errorProp
95+
}
96+
97+
url, err := replaceVars(d, config, "{{ApigeeBasePath}}organizations/{{org_id}}/environments/{{environment}}/flowhooks/{{flow_hook_point}}")
98+
if err != nil {
99+
return err
100+
}
101+
102+
log.Printf("[DEBUG] Creating new Flowhook: %#v", obj)
103+
billingProject := ""
104+
105+
// err == nil indicates that the billing_project value was found
106+
if bp, err := getBillingProject(d, config); err == nil {
107+
billingProject = bp
108+
}
109+
110+
res, err := SendRequestWithTimeout(config, "PUT", billingProject, url, userAgent, obj, d.Timeout(schema.TimeoutCreate))
111+
if err != nil {
112+
return fmt.Errorf("Error creating Flowhook: %s", err)
113+
}
114+
115+
// Store the ID now
116+
id, err := replaceVars(d, config, "organizations/{{org_id}}/environments/{{environment}}/flowhooks/{{flow_hook_point}}")
117+
if err != nil {
118+
return fmt.Errorf("Error constructing id: %s", err)
119+
}
120+
d.SetId(id)
121+
122+
log.Printf("[DEBUG] Finished creating Flowhook %q: %#v", d.Id(), res)
123+
124+
return resourceApigeeFlowhookRead(d, meta)
125+
}
126+
127+
func resourceApigeeFlowhookRead(d *schema.ResourceData, meta interface{}) error {
128+
config := meta.(*Config)
129+
userAgent, err := generateUserAgentString(d, config.UserAgent)
130+
if err != nil {
131+
return err
132+
}
133+
134+
url, err := replaceVars(d, config, "{{ApigeeBasePath}}organizations/{{org_id}}/environments/{{environment}}/flowhooks/{{flow_hook_point}}")
135+
if err != nil {
136+
return err
137+
}
138+
139+
billingProject := ""
140+
141+
// err == nil indicates that the billing_project value was found
142+
if bp, err := getBillingProject(d, config); err == nil {
143+
billingProject = bp
144+
}
145+
146+
res, err := SendRequest(config, "GET", billingProject, url, userAgent, nil)
147+
if err != nil {
148+
return handleNotFoundError(err, d, fmt.Sprintf("ApigeeFlowhook %q", d.Id()))
149+
}
150+
if res["sharedFlow"] == nil || res["sharedFlow"].(string) == "" {
151+
//if response does not contain shared_flow field, then nothing is attached to this flowhook, we treat this "binding" resource non-existent
152+
d.SetId("")
153+
return nil
154+
}
155+
if err := d.Set("description", flattenApigeeFlowhookDescription(res["description"], d, config)); err != nil {
156+
return fmt.Errorf("Error reading Flowhook: %s", err)
157+
}
158+
if err := d.Set("sharedflow", flattenApigeeFlowhookSharedflow(res["sharedFlow"], d, config)); err != nil {
159+
return fmt.Errorf("Error reading Flowhook: %s", err)
160+
}
161+
if err := d.Set("continue_on_error", flattenApigeeFlowhookContinueOnError(res["continueOnError"], d, config)); err != nil {
162+
return fmt.Errorf("Error reading Flowhook: %s", err)
163+
}
164+
165+
return nil
166+
}
167+
168+
func resourceApigeeFlowhookDelete(d *schema.ResourceData, meta interface{}) error {
169+
config := meta.(*Config)
170+
userAgent, err := generateUserAgentString(d, config.UserAgent)
171+
if err != nil {
172+
return err
173+
}
174+
175+
billingProject := ""
176+
177+
url, err := replaceVars(d, config, "{{ApigeeBasePath}}organizations/{{org_id}}/environments/{{environment}}/flowhooks/{{flow_hook_point}}")
178+
if err != nil {
179+
return err
180+
}
181+
182+
var obj map[string]interface{}
183+
log.Printf("[DEBUG] Deleting Flowhook %q", d.Id())
184+
185+
// err == nil indicates that the billing_project value was found
186+
if bp, err := getBillingProject(d, config); err == nil {
187+
billingProject = bp
188+
}
189+
190+
res, err := SendRequestWithTimeout(config, "DELETE", billingProject, url, userAgent, obj, d.Timeout(schema.TimeoutDelete))
191+
if err != nil {
192+
return handleNotFoundError(err, d, "Flowhook")
193+
}
194+
195+
log.Printf("[DEBUG] Finished deleting Flowhook %q: %#v", d.Id(), res)
196+
return nil
197+
}
198+
199+
func resourceApigeeFlowhookImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
200+
config := meta.(*Config)
201+
if err := parseImportId([]string{
202+
"organizations/(?P<org_id>[^/]+)/environments/(?P<environment>[^/]+)/flowhooks/(?P<flow_hook_point>[^/]+)",
203+
"(?P<org_id>[^/]+)/(?P<environment>[^/]+)/(?P<flow_hook_point>[^/]+)",
204+
}, d, config); err != nil {
205+
return nil, err
206+
}
207+
208+
// Replace import id for the resource id
209+
id, err := replaceVars(d, config, "organizations/{{org_id}}/environments/{{environment}}/flowhooks/{{flow_hook_point}}")
210+
if err != nil {
211+
return nil, fmt.Errorf("Error constructing id: %s", err)
212+
}
213+
d.SetId(id)
214+
215+
return []*schema.ResourceData{d}, nil
216+
}
217+
218+
func flattenApigeeFlowhookDescription(v interface{}, d *schema.ResourceData, config *Config) interface{} {
219+
return v
220+
}
221+
222+
func flattenApigeeFlowhookSharedflow(v interface{}, d *schema.ResourceData, config *Config) interface{} {
223+
return v
224+
}
225+
226+
func flattenApigeeFlowhookContinueOnError(v interface{}, d *schema.ResourceData, config *Config) interface{} {
227+
return v
228+
}
229+
230+
func expandApigeeFlowhookDescription(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
231+
return v, nil
232+
}
233+
234+
func expandApigeeFlowhookSharedflow(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
235+
return v, nil
236+
}
237+
238+
func expandApigeeFlowhookContinueOnError(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
239+
return v, nil
240+
}

0 commit comments

Comments
 (0)