diff --git a/.changelog/6589.txt b/.changelog/6589.txt new file mode 100644 index 00000000000..488319529a5 --- /dev/null +++ b/.changelog/6589.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +appengine: added support for `service_account` field to `google_app_engine_standard_app_version` resource +``` diff --git a/google/resource_app_engine_standard_app_version.go b/google/resource_app_engine_standard_app_version.go index 2029fa2982e..a9cfebb38c2 100644 --- a/google/resource_app_engine_standard_app_version.go +++ b/google/resource_app_engine_standard_app_version.go @@ -399,6 +399,12 @@ Modules API set_num_instances() you must use 'lifecycle.ignore_changes = ["manua Please see the app.yaml reference for valid values at 'https://cloud.google.com/appengine/docs/standard//config/appref'\ Substitute '' with 'python', 'java', 'php', 'ruby', 'go' or 'nodejs'.`, }, + "service_account": { + Type: schema.TypeString, + Computed: true, + Optional: true, + Description: `The identity that the deployed version will run as. Admin API will use the App Engine Appspot service account as default if this field is neither provided in app.yaml file nor through CLI flag.`, + }, "threadsafe": { Type: schema.TypeBool, Optional: true, @@ -476,6 +482,12 @@ func resourceAppEngineStandardAppVersionCreate(d *schema.ResourceData, meta inte } else if v, ok := d.GetOkExists("runtime"); !isEmptyValue(reflect.ValueOf(runtimeProp)) && (ok || !reflect.DeepEqual(v, runtimeProp)) { obj["runtime"] = runtimeProp } + serviceAccountProp, err := expandAppEngineStandardAppVersionServiceAccount(d.Get("service_account"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("service_account"); !isEmptyValue(reflect.ValueOf(serviceAccountProp)) && (ok || !reflect.DeepEqual(v, serviceAccountProp)) { + obj["serviceAccount"] = serviceAccountProp + } threadsafeProp, err := expandAppEngineStandardAppVersionThreadsafe(d.Get("threadsafe"), d, config) if err != nil { return err @@ -668,6 +680,9 @@ func resourceAppEngineStandardAppVersionRead(d *schema.ResourceData, meta interf if err := d.Set("runtime", flattenAppEngineStandardAppVersionRuntime(res["runtime"], d, config)); err != nil { return fmt.Errorf("Error reading StandardAppVersion: %s", err) } + if err := d.Set("service_account", flattenAppEngineStandardAppVersionServiceAccount(res["serviceAccount"], d, config)); err != nil { + return fmt.Errorf("Error reading StandardAppVersion: %s", err) + } if err := d.Set("app_engine_apis", flattenAppEngineStandardAppVersionAppEngineApis(res["appEngineApis"], d, config)); err != nil { return fmt.Errorf("Error reading StandardAppVersion: %s", err) } @@ -730,6 +745,12 @@ func resourceAppEngineStandardAppVersionUpdate(d *schema.ResourceData, meta inte } else if v, ok := d.GetOkExists("runtime"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, runtimeProp)) { obj["runtime"] = runtimeProp } + serviceAccountProp, err := expandAppEngineStandardAppVersionServiceAccount(d.Get("service_account"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("service_account"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, serviceAccountProp)) { + obj["serviceAccount"] = serviceAccountProp + } threadsafeProp, err := expandAppEngineStandardAppVersionThreadsafe(d.Get("threadsafe"), d, config) if err != nil { return err @@ -961,6 +982,10 @@ func flattenAppEngineStandardAppVersionRuntime(v interface{}, d *schema.Resource return v } +func flattenAppEngineStandardAppVersionServiceAccount(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + func flattenAppEngineStandardAppVersionAppEngineApis(v interface{}, d *schema.ResourceData, config *Config) interface{} { return v } @@ -1361,6 +1386,10 @@ func expandAppEngineStandardAppVersionRuntime(v interface{}, d TerraformResource return v, nil } +func expandAppEngineStandardAppVersionServiceAccount(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + func expandAppEngineStandardAppVersionThreadsafe(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } diff --git a/google/resource_app_engine_standard_app_version_generated_test.go b/google/resource_app_engine_standard_app_version_generated_test.go index 788a39f574e..fc74d785192 100644 --- a/google/resource_app_engine_standard_app_version_generated_test.go +++ b/google/resource_app_engine_standard_app_version_generated_test.go @@ -51,6 +51,23 @@ func TestAccAppEngineStandardAppVersion_appEngineStandardAppVersionExample(t *te func testAccAppEngineStandardAppVersion_appEngineStandardAppVersionExample(context map[string]interface{}) string { return Nprintf(` +resource "google_service_account" "custom_service_account" { + account_id = "tf-test-my-account%{random_suffix}" + display_name = "Custom Service Account" +} + +resource "google_project_iam_member" "gae_api" { + project = google_service_account.custom_service_account.project + role = "roles/compute.networkUser" + member = "serviceAccount:${google_service_account.custom_service_account.email}" +} + +resource "google_project_iam_member" "storage_viewer" { + project = google_service_account.custom_service_account.project + role = "roles/storage.objectViewer" + member = "serviceAccount:${google_service_account.custom_service_account.email}" +} + resource "google_app_engine_standard_app_version" "myapp_v1" { version_id = "v1" service = "myapp" @@ -85,6 +102,7 @@ resource "google_app_engine_standard_app_version" "myapp_v1" { } delete_service_on_destroy = true + service_account = google_service_account.custom_service_account.email } resource "google_app_engine_standard_app_version" "myapp_v2" { @@ -112,6 +130,7 @@ resource "google_app_engine_standard_app_version" "myapp_v2" { } noop_on_destroy = true + service_account = google_service_account.custom_service_account.email } resource "google_storage_bucket" "bucket" { diff --git a/website/docs/r/app_engine_standard_app_version.html.markdown b/website/docs/r/app_engine_standard_app_version.html.markdown index 719e09a3849..60ff64c3883 100644 --- a/website/docs/r/app_engine_standard_app_version.html.markdown +++ b/website/docs/r/app_engine_standard_app_version.html.markdown @@ -36,6 +36,23 @@ To get more information about StandardAppVersion, see: ```hcl +resource "google_service_account" "custom_service_account" { + account_id = "my-account" + display_name = "Custom Service Account" +} + +resource "google_project_iam_member" "gae_api" { + project = google_service_account.custom_service_account.project + role = "roles/compute.networkUser" + member = "serviceAccount:${google_service_account.custom_service_account.email}" +} + +resource "google_project_iam_member" "storage_viewer" { + project = google_service_account.custom_service_account.project + role = "roles/storage.objectViewer" + member = "serviceAccount:${google_service_account.custom_service_account.email}" +} + resource "google_app_engine_standard_app_version" "myapp_v1" { version_id = "v1" service = "myapp" @@ -70,6 +87,7 @@ resource "google_app_engine_standard_app_version" "myapp_v1" { } delete_service_on_destroy = true + service_account = google_service_account.custom_service_account.email } resource "google_app_engine_standard_app_version" "myapp_v2" { @@ -97,6 +115,7 @@ resource "google_app_engine_standard_app_version" "myapp_v2" { } noop_on_destroy = true + service_account = google_service_account.custom_service_account.email } resource "google_storage_bucket" "bucket" { @@ -184,6 +203,10 @@ The following arguments are supported: (Optional) Relative name of the version within the service. For example, `v1`. Version names can contain only lowercase letters, numbers, or hyphens. Reserved names,"default", "latest", and any name with the prefix "ah-". +* `service_account` - + (Optional) + The identity that the deployed version will run as. Admin API will use the App Engine Appspot service account as default if this field is neither provided in app.yaml file nor through CLI flag. + * `threadsafe` - (Optional) Whether multiple requests can be dispatched to this version at once.