From b7ed12293fd328a214e87e6ef1c6dfd10c4fec85 Mon Sep 17 00:00:00 2001 From: Andrew Starr-Bochicchio Date: Tue, 19 Jan 2021 17:52:29 -0500 Subject: [PATCH] apps: Add support for global env vars (Fixes: #549). (#550) --- digitalocean/app_spec.go | 11 +++ .../resource_digitalocean_app_test.go | 95 ++++++++++++++++--- docs/resources/app.md | 5 + go.sum | 3 - 4 files changed, 100 insertions(+), 14 deletions(-) diff --git a/digitalocean/app_spec.go b/digitalocean/app_spec.go index 1a77d794b..481941510 100644 --- a/digitalocean/app_spec.go +++ b/digitalocean/app_spec.go @@ -47,6 +47,12 @@ func appSpecSchema() map[string]*schema.Schema { Optional: true, Elem: appSpecDatabaseSchema(), }, + "env": { + Type: schema.TypeSet, + Optional: true, + Elem: appSpecEnvSchema(), + Set: schema.HashResource(appSpecEnvSchema()), + }, } } @@ -421,6 +427,7 @@ func expandAppSpec(config []interface{}) *godo.AppSpec { StaticSites: expandAppSpecStaticSites(appSpecConfig["static_site"].([]interface{})), Workers: expandAppSpecWorkers(appSpecConfig["worker"].([]interface{})), Databases: expandAppSpecDatabases(appSpecConfig["database"].([]interface{})), + Envs: expandAppEnvs(appSpecConfig["env"].(*schema.Set).List()), } return appSpec @@ -452,6 +459,10 @@ func flattenAppSpec(spec *godo.AppSpec) []map[string]interface{} { r["database"] = flattenAppSpecDatabases((*spec).Databases) } + if len((*spec).Envs) > 0 { + r["env"] = flattenAppEnvs((*spec).Envs) + } + result = append(result, r) } diff --git a/digitalocean/resource_digitalocean_app_test.go b/digitalocean/resource_digitalocean_app_test.go index 96d6c5a15..10e66fed6 100644 --- a/digitalocean/resource_digitalocean_app_test.go +++ b/digitalocean/resource_digitalocean_app_test.go @@ -161,19 +161,19 @@ func TestAccDigitalOceanApp_Envs(t *testing.T) { oneEnv := ` env { - key = "FOO" + key = "COMPONENT_FOO" value = "bar" } ` twoEnvs := ` env { - key = "FOO" + key = "COMPONENT_FOO" value = "bar" } env { - key = "FIZZ" + key = "COMPONENT_FIZZ" value = "pop" scope = "BUILD_TIME" } @@ -181,7 +181,36 @@ func TestAccDigitalOceanApp_Envs(t *testing.T) { oneEnvUpdated := ` env { - key = "FOO" + key = "COMPONENT_FOO" + value = "baz" + scope = "RUN_TIME" + type = "GENERAL" + } +` + + oneAppEnv := ` + env { + key = "APP_FOO" + value = "bar" + } +` + + twoAppEnvs := ` + env { + key = "APP_FOO" + value = "bar" + } + + env { + key = "APP_FIZZ" + value = "pop" + scope = "BUILD_TIME" + } +` + + oneAppEnvUpdated := ` + env { + key = "APP_FOO" value = "baz" scope = "RUN_TIME" type = "GENERAL" @@ -194,7 +223,7 @@ func TestAccDigitalOceanApp_Envs(t *testing.T) { CheckDestroy: testAccCheckDigitalOceanAppDestroy, Steps: []resource.TestStep{ { - Config: fmt.Sprintf(testAccCheckDigitalOceanAppConfig_Envs, appName, oneEnv), + Config: fmt.Sprintf(testAccCheckDigitalOceanAppConfig_Envs, appName, oneEnv, oneAppEnv), Check: resource.ComposeTestCheckFunc( testAccCheckDigitalOceanAppExists("digitalocean_app.foobar", &app), resource.TestCheckResourceAttr( @@ -205,7 +234,18 @@ func TestAccDigitalOceanApp_Envs(t *testing.T) { "digitalocean_app.foobar", "spec.0.service.0.env.*", map[string]string{ - "key": "FOO", + "key": "COMPONENT_FOO", + "value": "bar", + "scope": "RUN_AND_BUILD_TIME", + }, + ), + resource.TestCheckResourceAttr( + "digitalocean_app.foobar", "spec.0.env.#", "1"), + setutil.TestCheckTypeSetElemNestedAttrs( + "digitalocean_app.foobar", + "spec.0.env.*", + map[string]string{ + "key": "APP_FOO", "value": "bar", "scope": "RUN_AND_BUILD_TIME", }, @@ -213,7 +253,7 @@ func TestAccDigitalOceanApp_Envs(t *testing.T) { ), }, { - Config: fmt.Sprintf(testAccCheckDigitalOceanAppConfig_Envs, appName, twoEnvs), + Config: fmt.Sprintf(testAccCheckDigitalOceanAppConfig_Envs, appName, twoEnvs, twoAppEnvs), Check: resource.ComposeTestCheckFunc( testAccCheckDigitalOceanAppExists("digitalocean_app.foobar", &app), resource.TestCheckResourceAttr( @@ -224,7 +264,7 @@ func TestAccDigitalOceanApp_Envs(t *testing.T) { "digitalocean_app.foobar", "spec.0.service.0.env.*", map[string]string{ - "key": "FOO", + "key": "COMPONENT_FOO", "value": "bar", "scope": "RUN_AND_BUILD_TIME", }, @@ -233,7 +273,27 @@ func TestAccDigitalOceanApp_Envs(t *testing.T) { "digitalocean_app.foobar", "spec.0.service.0.env.*", map[string]string{ - "key": "FIZZ", + "key": "COMPONENT_FIZZ", + "value": "pop", + "scope": "BUILD_TIME", + }, + ), + resource.TestCheckResourceAttr( + "digitalocean_app.foobar", "spec.0.env.#", "2"), + setutil.TestCheckTypeSetElemNestedAttrs( + "digitalocean_app.foobar", + "spec.0.env.*", + map[string]string{ + "key": "APP_FOO", + "value": "bar", + "scope": "RUN_AND_BUILD_TIME", + }, + ), + setutil.TestCheckTypeSetElemNestedAttrs( + "digitalocean_app.foobar", + "spec.0.env.*", + map[string]string{ + "key": "APP_FIZZ", "value": "pop", "scope": "BUILD_TIME", }, @@ -241,7 +301,7 @@ func TestAccDigitalOceanApp_Envs(t *testing.T) { ), }, { - Config: fmt.Sprintf(testAccCheckDigitalOceanAppConfig_Envs, appName, oneEnvUpdated), + Config: fmt.Sprintf(testAccCheckDigitalOceanAppConfig_Envs, appName, oneEnvUpdated, oneAppEnvUpdated), Check: resource.ComposeTestCheckFunc( testAccCheckDigitalOceanAppExists("digitalocean_app.foobar", &app), resource.TestCheckResourceAttr( @@ -252,7 +312,18 @@ func TestAccDigitalOceanApp_Envs(t *testing.T) { "digitalocean_app.foobar", "spec.0.service.0.env.*", map[string]string{ - "key": "FOO", + "key": "COMPONENT_FOO", + "value": "baz", + "scope": "RUN_TIME", + }, + ), + resource.TestCheckResourceAttr( + "digitalocean_app.foobar", "spec.0.env.#", "1"), + setutil.TestCheckTypeSetElemNestedAttrs( + "digitalocean_app.foobar", + "spec.0.env.*", + map[string]string{ + "key": "APP_FOO", "value": "baz", "scope": "RUN_TIME", }, @@ -487,6 +558,8 @@ resource "digitalocean_app" "foobar" { %s } + +%s } }` diff --git a/docs/resources/app.md b/docs/resources/app.md index 257e44f5e..5a355eb97 100644 --- a/docs/resources/app.md +++ b/docs/resources/app.md @@ -122,6 +122,11 @@ The following arguments are supported: - `name` - (Required) The name of the app. Must be unique across all apps in the same account. - `region` - The slug for the DigitalOcean data center region hosting the app. - `domains` - A list of hostnames where the application will be available. + - `env` - Describes an app-wide environment variable made available to all components. + * `key` - The name of the environment variable. + * `value` - The value of the environment variable. + * `scope` - The visibility scope of the environment variable. One of `RUN_TIME`, `BUILD_TIME`, or `RUN_AND_BUILD_TIME` (default). + * `type` - The type of the environment variable, `GENERAL` or `SECRET`. A spec can contain multiple components. diff --git a/go.sum b/go.sum index f00c9baf4..e0f57e3c5 100644 --- a/go.sum +++ b/go.sum @@ -89,7 +89,6 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= @@ -118,7 +117,6 @@ github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3 h1:GV+pQPG/EUUbkh47niozDcADz6go/dUwhVzdUQHIVRw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -237,7 +235,6 @@ github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaO github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mitchellh/cli v1.1.1 h1:J64v/xD7Clql+JVKSvkYojLOXu1ibnY9ZjGLwSt/89w= github.com/mitchellh/cli v1.1.1/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=