@@ -67,7 +67,7 @@ func ResolveParameters(
67
67
//
68
68
// This is how the form should look to the user on their workspace settings page.
69
69
// This is the original form truth that our validations should initially be based on.
70
- output , diags := renderer .Render (ctx , ownerID , values . ValuesMap () )
70
+ output , diags := renderer .Render (ctx , ownerID , previousValuesMap )
71
71
if diags .HasErrors () {
72
72
// Top level diagnostics should break the build. Previous values (and new) should
73
73
// always be valid. If there is a case where this is not true, then this has to
@@ -81,6 +81,7 @@ func ResolveParameters(
81
81
//
82
82
// To enforce these, the user's input values are trimmed based on the
83
83
// mutability and ephemeral parameters defined in the template version.
84
+ wasImmutable := make (map [string ]struct {})
84
85
for _ , parameter := range output .Parameters {
85
86
// Ephemeral parameters should not be taken from the previous build.
86
87
// They must always be explicitly set in every build.
@@ -98,6 +99,7 @@ func ResolveParameters(
98
99
//
99
100
// We do this so the next form render uses the original immutable value.
100
101
if ! firstBuild && ! parameter .Mutable {
102
+ wasImmutable [parameter .Name ] = struct {}{}
101
103
delete (values , parameter .Name )
102
104
prev , ok := previousValuesMap [parameter .Name ]
103
105
if ok {
@@ -123,7 +125,12 @@ func ResolveParameters(
123
125
for _ , parameter := range output .Parameters {
124
126
parameterNames [parameter .Name ] = struct {}{}
125
127
126
- if ! firstBuild && ! parameter .Mutable {
128
+ // Immutability is sourced from the current `mutable` argument, and also the
129
+ // previous parameter's `mutable` argument. This means you cannot flip an
130
+ // `immutable` parameter to `mutable` in a single build. This is to preserve the
131
+ // original mutability of the parameter.
132
+ _ , wi := wasImmutable [parameter .Name ]
133
+ if ! firstBuild && (! parameter .Mutable || wi ) {
127
134
originalValue , ok := originalValues [parameter .Name ]
128
135
// Immutable parameters should not be changed after the first build.
129
136
// If the value matches the original value, that is fine.
@@ -137,13 +144,19 @@ func ResolveParameters(
137
144
if parameter .Source != nil {
138
145
src = & parameter .Source .HCLBlock ().TypeRange
139
146
}
147
+ errTitle := "Immutable"
148
+ // In the strange case someone flips mutability from `true` to `false`.
149
+ // Change the error title to indicate that this was previously immutable.
150
+ if wi && parameter .Mutable {
151
+ errTitle = "Previously immutable"
152
+ }
140
153
141
154
// An immutable parameter was changed, which is not allowed.
142
155
// Add a failed diagnostic to the output.
143
156
parameterError .Extend (parameter .Name , hcl.Diagnostics {
144
157
& hcl.Diagnostic {
145
158
Severity : hcl .DiagError ,
146
- Summary : "Immutable parameter changed" ,
159
+ Summary : fmt . Sprintf ( "%s parameter changed", errTitle ) ,
147
160
Detail : fmt .Sprintf ("Parameter %q is not mutable, so it can't be updated after creating a workspace." , parameter .Name ),
148
161
Subject : src ,
149
162
},
0 commit comments