Skip to content

Commit d7a26f9

Browse files
committed
Add non-sensitive value attribute to environment variable resource
This change adds an alternative, non-sensitive `value` attribute to the environment variable resource. This allows users to view the value of non-sensitive environment variables. As I can't see the reason to have write-only, non-sensitive values, this combination is not allowed. Fixes #517
1 parent 7498c3a commit d7a26f9

File tree

3 files changed

+169
-3
lines changed

3 files changed

+169
-3
lines changed

docs/resources/environment_variable.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ resource "spacelift_environment_variable" "core-kubeconfig" {
5555
- `module_id` (String) ID of the module on which the environment variable is defined
5656
- `stack_id` (String) ID of the stack on which the environment variable is defined
5757
- `value` (String, Sensitive) Value of the environment variable. Defaults to an empty string.
58+
- `value_nonsensitive` (String) Value of the environment variable. Defaults to an empty string.
5859
- `write_only` (Boolean) Indicates whether the value is secret or not. Defaults to `true`.
5960

6061
### Read-Only

spacelift/resource_environment_variable.go

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,16 @@ func resourceEnvironmentVariable() *schema.Resource {
7474
Optional: true,
7575
Default: "",
7676
ForceNew: true,
77+
ConflictsWith: []string{"value_nonsensitive"},
78+
},
79+
"value_nonsensitive": {
80+
Type: schema.TypeString,
81+
Description: "Value of the environment variable. Defaults to an empty string.",
82+
Sensitive: false,
83+
Optional: true,
84+
Default: "",
85+
ForceNew: true,
86+
ConflictsWith: []string{"value"},
7787
},
7888
"write_only": {
7989
Type: schema.TypeBool,
@@ -93,12 +103,19 @@ func resourceEnvironmentVariable() *schema.Resource {
93103
}
94104

95105
func resourceEnvironmentVariableCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
106+
writeOnly := d.Get("write_only").(bool)
107+
108+
value, sensitive := resourceEnvironmentVariableValue(d)
109+
if !sensitive && writeOnly {
110+
return diag.Errorf("a non-sensitive environment variable cannot be write-only")
111+
}
112+
96113
variables := map[string]interface{}{
97114
"config": structs.ConfigInput{
98115
ID: toID(d.Get("name")),
99116
Type: structs.ConfigType("ENVIRONMENT_VARIABLE"),
100-
Value: toString(d.Get("value")),
101-
WriteOnly: graphql.Boolean(d.Get("write_only").(bool)),
117+
Value: value,
118+
WriteOnly: graphql.Boolean(writeOnly),
102119
Description: toOptionalString(d.Get("description")),
103120
},
104121
}
@@ -127,6 +144,13 @@ func resourceEnvironmentVariableCreate(ctx context.Context, d *schema.ResourceDa
127144
return resourceEnvironmentVariableCreateModule(ctx, d, meta.(*internal.Client), variables)
128145
}
129146

147+
func resourceEnvironmentVariableValue(d *schema.ResourceData) (graphql.String, bool) {
148+
if v, ok := d.GetOk("value_nonsensitive"); ok {
149+
return toString(v), false
150+
}
151+
return toString(d.Get("value")), true
152+
}
153+
130154
func resourceEnvironmentVariableCreateContext(ctx context.Context, d *schema.ResourceData, client *internal.Client, variables map[string]interface{}) diag.Diagnostics {
131155
var mutation struct {
132156
AddContextConfig structs.ConfigElement `graphql:"contextConfigAdd(context: $context, config: $config)"`
@@ -206,7 +230,11 @@ func resourceEnvironmentVariableRead(ctx context.Context, d *schema.ResourceData
206230
d.Set("write_only", element.WriteOnly)
207231

208232
if value := element.Value; value != nil {
209-
d.Set("value", *value)
233+
if _, ok := d.GetOk("value_nonsensitive"); ok {
234+
d.Set("value_nonsensitive", *value)
235+
} else {
236+
d.Set("value", *value)
237+
}
210238
} else {
211239
d.Set("value", element.Checksum)
212240
}

spacelift/resource_environment_variable_test.go

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package spacelift
22

33
import (
44
"fmt"
5+
"regexp"
56
"testing"
67

78
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
@@ -141,3 +142,139 @@ func TestEnvironmentVariableResource(t *testing.T) {
141142
})
142143
})
143144
}
145+
146+
func TestEnvironmentVariableResourceNonsensitiveValue(t *testing.T) {
147+
const resourceName = "spacelift_environment_variable.test"
148+
149+
t.Run("with a context", func(t *testing.T) {
150+
randomID := acctest.RandStringFromCharSet(5, acctest.CharSetAlphaNum)
151+
152+
config := func(description string) string {
153+
return fmt.Sprintf(`
154+
resource "spacelift_context" "test" {
155+
name = "My first context %s"
156+
}
157+
158+
resource "spacelift_environment_variable" "test" {
159+
context_id = spacelift_context.test.id
160+
name = "BACON"
161+
value_nonsensitive = "is tasty"
162+
write_only = false
163+
description = %s
164+
}
165+
`, randomID, description)
166+
}
167+
168+
testSteps(t, []resource.TestStep{
169+
{
170+
Config: config(`"Bacon is tasty"`),
171+
Check: Resource(
172+
resourceName,
173+
Attribute("id", IsNotEmpty()),
174+
Attribute("checksum", Equals("4d5d01ea427b10dd483e8fce5b5149fb5a9814e9ee614176b756ca4a65c8f154")),
175+
Attribute("context_id", Contains(randomID)),
176+
Attribute("name", Equals("BACON")),
177+
Attribute("value_nonsensitive", Equals("is tasty")),
178+
Attribute("write_only", Equals("false")),
179+
Attribute("description", Equals("Bacon is tasty")),
180+
AttributeNotPresent("value"),
181+
AttributeNotPresent("module_id"),
182+
AttributeNotPresent("stack_id"),
183+
),
184+
},
185+
})
186+
})
187+
188+
t.Run("with a module", func(t *testing.T) {
189+
randomID := acctest.RandStringFromCharSet(5, acctest.CharSetAlphaNum)
190+
191+
testSteps(t, []resource.TestStep{
192+
{
193+
Config: fmt.Sprintf(`
194+
resource "spacelift_module" "test" {
195+
name = "test-module-%s"
196+
branch = "master"
197+
repository = "terraform-bacon-tasty"
198+
}
199+
200+
resource "spacelift_environment_variable" "test" {
201+
module_id = spacelift_module.test.id
202+
name = "BACON"
203+
value_nonsensitive = "is tasty"
204+
write_only = false
205+
description = "Bacon is tasty"
206+
}
207+
`, randomID),
208+
Check: Resource(
209+
resourceName,
210+
Attribute("module_id", Equals(fmt.Sprintf("terraform-default-test-module-%s", randomID))),
211+
Attribute("value_nonsensitive", Equals("is tasty")),
212+
Attribute("write_only", Equals("false")),
213+
Attribute("description", Equals("Bacon is tasty")),
214+
AttributeNotPresent("value"),
215+
AttributeNotPresent("context_id"),
216+
AttributeNotPresent("stack_id"),
217+
),
218+
},
219+
})
220+
})
221+
222+
t.Run("with a stack", func(t *testing.T) {
223+
randomID := acctest.RandStringFromCharSet(5, acctest.CharSetAlphaNum)
224+
225+
testSteps(t, []resource.TestStep{
226+
{
227+
Config: fmt.Sprintf(`
228+
resource "spacelift_stack" "test" {
229+
branch = "master"
230+
repository = "demo"
231+
name = "Test stack %s"
232+
}
233+
234+
resource "spacelift_environment_variable" "test" {
235+
stack_id = spacelift_stack.test.id
236+
value_nonsensitive = "is tasty"
237+
write_only = false
238+
name = "BACON"
239+
description = "Bacon is tasty"
240+
}
241+
`, randomID),
242+
Check: Resource(
243+
resourceName,
244+
Attribute("stack_id", StartsWith("test-stack-")),
245+
Attribute("stack_id", Contains(randomID)),
246+
Attribute("value_nonsensitive", Equals("is tasty")),
247+
Attribute("description", Equals("Bacon is tasty")),
248+
AttributeNotPresent("value"),
249+
AttributeNotPresent("context_id"),
250+
AttributeNotPresent("module_id"),
251+
),
252+
},
253+
})
254+
})
255+
256+
t.Run("write only is not allowed", func(t *testing.T) {
257+
randomID := acctest.RandStringFromCharSet(5, acctest.CharSetAlphaNum)
258+
259+
testSteps(t, []resource.TestStep{
260+
{
261+
Config: fmt.Sprintf(`
262+
resource "spacelift_stack" "test" {
263+
branch = "master"
264+
repository = "demo"
265+
name = "Test stack %s"
266+
}
267+
268+
resource "spacelift_environment_variable" "test" {
269+
stack_id = spacelift_stack.test.id
270+
value_nonsensitive = "is tasty"
271+
write_only = true
272+
name = "BACON"
273+
description = "Bacon is tasty"
274+
}
275+
`, randomID),
276+
ExpectError: regexp.MustCompile("a non-sensitive environment variable cannot be write-only"),
277+
},
278+
})
279+
})
280+
}

0 commit comments

Comments
 (0)