Skip to content

Commit 128eada

Browse files
khanali21modular-magician
authored andcommitted
App Engine Service Split Traffic resource
Signed-off-by: Modular Magician <[email protected]>
1 parent a0dfdc8 commit 128eada

6 files changed

+675
-17
lines changed

google/provider.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -437,9 +437,9 @@ func Provider() terraform.ResourceProvider {
437437
return provider
438438
}
439439

440-
// Generated resources: 80
440+
// Generated resources: 81
441441
// Generated IAM resources: 33
442-
// Total generated resources: 113
442+
// Total generated resources: 114
443443
func ResourceMap() map[string]*schema.Resource {
444444
resourceMap, _ := ResourceMapWithErrors()
445445
return resourceMap
@@ -453,6 +453,7 @@ func ResourceMapWithErrors() (map[string]*schema.Resource, error) {
453453
"google_access_context_manager_service_perimeter": resourceAccessContextManagerServicePerimeter(),
454454
"google_app_engine_domain_mapping": resourceAppEngineDomainMapping(),
455455
"google_app_engine_firewall_rule": resourceAppEngineFirewallRule(),
456+
"google_app_engine_service_split_traffic": resourceAppEngineServiceSplitTraffic(),
456457
"google_app_engine_standard_app_version": resourceAppEngineStandardAppVersion(),
457458
"google_bigquery_dataset": resourceBigQueryDataset(),
458459
"google_bigquery_data_transfer_config": resourceBigqueryDataTransferConfig(),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,352 @@
1+
// ----------------------------------------------------------------------------
2+
//
3+
// *** AUTO GENERATED CODE *** AUTO GENERATED CODE ***
4+
//
5+
// ----------------------------------------------------------------------------
6+
//
7+
// This file is automatically generated by Magic Modules and manual
8+
// changes will be clobbered when the file is regenerated.
9+
//
10+
// Please read more about how to change this file in
11+
// .github/CONTRIBUTING.md.
12+
//
13+
// ----------------------------------------------------------------------------
14+
15+
package google
16+
17+
import (
18+
"fmt"
19+
"log"
20+
"reflect"
21+
"strings"
22+
"time"
23+
24+
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
25+
"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
26+
"google.golang.org/api/appengine/v1"
27+
)
28+
29+
func resourceAppEngineServiceSplitTraffic() *schema.Resource {
30+
return &schema.Resource{
31+
Create: resourceAppEngineServiceSplitTrafficCreate,
32+
Read: resourceAppEngineServiceSplitTrafficRead,
33+
Update: resourceAppEngineServiceSplitTrafficUpdate,
34+
Delete: resourceAppEngineServiceSplitTrafficDelete,
35+
36+
Importer: &schema.ResourceImporter{
37+
State: resourceAppEngineServiceSplitTrafficImport,
38+
},
39+
40+
Timeouts: &schema.ResourceTimeout{
41+
Create: schema.DefaultTimeout(4 * time.Minute),
42+
Update: schema.DefaultTimeout(4 * time.Minute),
43+
Delete: schema.DefaultTimeout(4 * time.Minute),
44+
},
45+
46+
Schema: map[string]*schema.Schema{
47+
"split": {
48+
Type: schema.TypeList,
49+
Required: true,
50+
MaxItems: 1,
51+
Elem: &schema.Resource{
52+
Schema: map[string]*schema.Schema{
53+
"allocations": {
54+
Type: schema.TypeMap,
55+
Required: true,
56+
Elem: &schema.Schema{Type: schema.TypeString},
57+
},
58+
"shard_by": {
59+
Type: schema.TypeString,
60+
Optional: true,
61+
ValidateFunc: validation.StringInSlice([]string{"UNSPECIFIED", "COOKIE", "IP", "RANDOM", ""}, false),
62+
},
63+
},
64+
},
65+
},
66+
"migrate_traffic": {
67+
Type: schema.TypeBool,
68+
Optional: true,
69+
},
70+
"name": {
71+
Type: schema.TypeString,
72+
Optional: true,
73+
},
74+
"service_id": {
75+
Type: schema.TypeString,
76+
Optional: true,
77+
},
78+
"project": {
79+
Type: schema.TypeString,
80+
Optional: true,
81+
Computed: true,
82+
ForceNew: true,
83+
},
84+
},
85+
}
86+
}
87+
88+
func resourceAppEngineServiceSplitTrafficCreate(d *schema.ResourceData, meta interface{}) error {
89+
config := meta.(*Config)
90+
91+
obj := make(map[string]interface{})
92+
nameProp, err := expandAppEngineServiceSplitTrafficName(d.Get("name"), d, config)
93+
if err != nil {
94+
return err
95+
} else if v, ok := d.GetOkExists("name"); !isEmptyValue(reflect.ValueOf(nameProp)) && (ok || !reflect.DeepEqual(v, nameProp)) {
96+
obj["name"] = nameProp
97+
}
98+
idProp, err := expandAppEngineServiceSplitTrafficServiceId(d.Get("service_id"), d, config)
99+
if err != nil {
100+
return err
101+
} else if v, ok := d.GetOkExists("service_id"); !isEmptyValue(reflect.ValueOf(idProp)) && (ok || !reflect.DeepEqual(v, idProp)) {
102+
obj["id"] = idProp
103+
}
104+
splitProp, err := expandAppEngineServiceSplitTrafficSplit(d.Get("split"), d, config)
105+
if err != nil {
106+
return err
107+
} else if v, ok := d.GetOkExists("split"); !isEmptyValue(reflect.ValueOf(splitProp)) && (ok || !reflect.DeepEqual(v, splitProp)) {
108+
obj["split"] = splitProp
109+
}
110+
111+
lockName, err := replaceVars(d, config, "apps/{{project}}/services/{{service_id}}")
112+
if err != nil {
113+
return err
114+
}
115+
mutexKV.Lock(lockName)
116+
defer mutexKV.Unlock(lockName)
117+
118+
url, err := replaceVars(d, config, "{{AppEngineBasePath}}apps/{{project}}/services/{{service_id}}?migrateTraffic={{migrate_traffic}}&updateMask=split")
119+
if err != nil {
120+
return err
121+
}
122+
123+
log.Printf("[DEBUG] Creating new ServiceSplitTraffic: %#v", obj)
124+
project, err := getProject(d, config)
125+
if err != nil {
126+
return err
127+
}
128+
res, err := sendRequestWithTimeout(config, "PATCH", project, url, obj, d.Timeout(schema.TimeoutCreate))
129+
if err != nil {
130+
return fmt.Errorf("Error creating ServiceSplitTraffic: %s", err)
131+
}
132+
133+
// Store the ID now
134+
id, err := replaceVars(d, config, "{{service_id}}")
135+
if err != nil {
136+
return fmt.Errorf("Error constructing id: %s", err)
137+
}
138+
d.SetId(id)
139+
140+
op := &appengine.Operation{}
141+
err = Convert(res, op)
142+
if err != nil {
143+
return err
144+
}
145+
146+
waitErr := appEngineOperationWaitTime(
147+
config.clientAppEngine, op, project, "Creating ServiceSplitTraffic",
148+
int(d.Timeout(schema.TimeoutCreate).Minutes()))
149+
150+
if waitErr != nil {
151+
// The resource didn't actually create
152+
d.SetId("")
153+
return fmt.Errorf("Error waiting to create ServiceSplitTraffic: %s", waitErr)
154+
}
155+
156+
log.Printf("[DEBUG] Finished creating ServiceSplitTraffic %q: %#v", d.Id(), res)
157+
158+
return resourceAppEngineServiceSplitTrafficRead(d, meta)
159+
}
160+
161+
func resourceAppEngineServiceSplitTrafficRead(d *schema.ResourceData, meta interface{}) error {
162+
config := meta.(*Config)
163+
164+
url, err := replaceVars(d, config, "{{AppEngineBasePath}}apps/{{project}}/services/{{name}}")
165+
if err != nil {
166+
return err
167+
}
168+
169+
project, err := getProject(d, config)
170+
if err != nil {
171+
return err
172+
}
173+
res, err := sendRequest(config, "GET", project, url, nil)
174+
if err != nil {
175+
return handleNotFoundError(err, d, fmt.Sprintf("AppEngineServiceSplitTraffic %q", d.Id()))
176+
}
177+
178+
if err := d.Set("project", project); err != nil {
179+
return fmt.Errorf("Error reading ServiceSplitTraffic: %s", err)
180+
}
181+
182+
if err := d.Set("name", flattenAppEngineServiceSplitTrafficName(res["name"], d)); err != nil {
183+
return fmt.Errorf("Error reading ServiceSplitTraffic: %s", err)
184+
}
185+
186+
return nil
187+
}
188+
189+
func resourceAppEngineServiceSplitTrafficUpdate(d *schema.ResourceData, meta interface{}) error {
190+
config := meta.(*Config)
191+
192+
project, err := getProject(d, config)
193+
if err != nil {
194+
return err
195+
}
196+
197+
obj := make(map[string]interface{})
198+
nameProp, err := expandAppEngineServiceSplitTrafficName(d.Get("name"), d, config)
199+
if err != nil {
200+
return err
201+
} else if v, ok := d.GetOkExists("name"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, nameProp)) {
202+
obj["name"] = nameProp
203+
}
204+
idProp, err := expandAppEngineServiceSplitTrafficServiceId(d.Get("service_id"), d, config)
205+
if err != nil {
206+
return err
207+
} else if v, ok := d.GetOkExists("service_id"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, idProp)) {
208+
obj["id"] = idProp
209+
}
210+
splitProp, err := expandAppEngineServiceSplitTrafficSplit(d.Get("split"), d, config)
211+
if err != nil {
212+
return err
213+
} else if v, ok := d.GetOkExists("split"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, splitProp)) {
214+
obj["split"] = splitProp
215+
}
216+
217+
lockName, err := replaceVars(d, config, "apps/{{project}}/services/{{service_id}}")
218+
if err != nil {
219+
return err
220+
}
221+
mutexKV.Lock(lockName)
222+
defer mutexKV.Unlock(lockName)
223+
224+
url, err := replaceVars(d, config, "{{AppEngineBasePath}}apps/{{project}}/services/{{service_id}}?migrateTraffic={{migrate_traffic}}")
225+
if err != nil {
226+
return err
227+
}
228+
229+
log.Printf("[DEBUG] Updating ServiceSplitTraffic %q: %#v", d.Id(), obj)
230+
updateMask := []string{}
231+
232+
if d.HasChange("name") {
233+
updateMask = append(updateMask, "name")
234+
}
235+
236+
if d.HasChange("service_id") {
237+
updateMask = append(updateMask, "id")
238+
}
239+
240+
if d.HasChange("split") {
241+
updateMask = append(updateMask, "split")
242+
}
243+
// updateMask is a URL parameter but not present in the schema, so replaceVars
244+
// won't set it
245+
url, err = addQueryParams(url, map[string]string{"updateMask": strings.Join(updateMask, ",")})
246+
if err != nil {
247+
return err
248+
}
249+
res, err := sendRequestWithTimeout(config, "PATCH", project, url, obj, d.Timeout(schema.TimeoutUpdate))
250+
251+
if err != nil {
252+
return fmt.Errorf("Error updating ServiceSplitTraffic %q: %s", d.Id(), err)
253+
}
254+
255+
op := &appengine.Operation{}
256+
err = Convert(res, op)
257+
if err != nil {
258+
return err
259+
}
260+
261+
err = appEngineOperationWaitTime(
262+
config.clientAppEngine, op, project, "Updating ServiceSplitTraffic",
263+
int(d.Timeout(schema.TimeoutUpdate).Minutes()))
264+
265+
if err != nil {
266+
return err
267+
}
268+
269+
return resourceAppEngineServiceSplitTrafficRead(d, meta)
270+
}
271+
272+
func resourceAppEngineServiceSplitTrafficDelete(d *schema.ResourceData, meta interface{}) error {
273+
log.Printf("[WARNING] AppEngine ServiceSplitTraffic resources"+
274+
" cannot be deleted from GCP. The resource %s will be removed from Terraform"+
275+
" state, but will still be present on the server.", d.Id())
276+
d.SetId("")
277+
278+
return nil
279+
}
280+
281+
func resourceAppEngineServiceSplitTrafficImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
282+
config := meta.(*Config)
283+
if err := parseImportId([]string{
284+
"apps/(?P<project>[^/]+)/services/(?P<service_id>[^/]+)",
285+
"(?P<project>[^/]+)/(?P<service_id>[^/]+)",
286+
"(?P<service_id>[^/]+)",
287+
}, d, config); err != nil {
288+
return nil, err
289+
}
290+
291+
// Replace import id for the resource id
292+
id, err := replaceVars(d, config, "{{service_id}}")
293+
if err != nil {
294+
return nil, fmt.Errorf("Error constructing id: %s", err)
295+
}
296+
d.SetId(id)
297+
298+
return []*schema.ResourceData{d}, nil
299+
}
300+
301+
func flattenAppEngineServiceSplitTrafficName(v interface{}, d *schema.ResourceData) interface{} {
302+
return v
303+
}
304+
305+
func expandAppEngineServiceSplitTrafficName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
306+
return v, nil
307+
}
308+
309+
func expandAppEngineServiceSplitTrafficServiceId(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
310+
return v, nil
311+
}
312+
313+
func expandAppEngineServiceSplitTrafficSplit(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
314+
l := v.([]interface{})
315+
if len(l) == 0 || l[0] == nil {
316+
return nil, nil
317+
}
318+
raw := l[0]
319+
original := raw.(map[string]interface{})
320+
transformed := make(map[string]interface{})
321+
322+
transformedShardBy, err := expandAppEngineServiceSplitTrafficSplitShardBy(original["shard_by"], d, config)
323+
if err != nil {
324+
return nil, err
325+
} else if val := reflect.ValueOf(transformedShardBy); val.IsValid() && !isEmptyValue(val) {
326+
transformed["shardBy"] = transformedShardBy
327+
}
328+
329+
transformedAllocations, err := expandAppEngineServiceSplitTrafficSplitAllocations(original["allocations"], d, config)
330+
if err != nil {
331+
return nil, err
332+
} else if val := reflect.ValueOf(transformedAllocations); val.IsValid() && !isEmptyValue(val) {
333+
transformed["allocations"] = transformedAllocations
334+
}
335+
336+
return transformed, nil
337+
}
338+
339+
func expandAppEngineServiceSplitTrafficSplitShardBy(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
340+
return v, nil
341+
}
342+
343+
func expandAppEngineServiceSplitTrafficSplitAllocations(v interface{}, d TerraformResourceData, config *Config) (map[string]string, error) {
344+
if v == nil {
345+
return map[string]string{}, nil
346+
}
347+
m := make(map[string]string)
348+
for k, val := range v.(map[string]interface{}) {
349+
m[k] = val.(string)
350+
}
351+
return m, nil
352+
}

0 commit comments

Comments
 (0)