Skip to content

Commit 9baa358

Browse files
committed
fix(function): support secret_environment_variable state
1 parent 6bacb2f commit 9baa358

File tree

6 files changed

+551
-800
lines changed

6 files changed

+551
-800
lines changed

internal/services/function/function.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,9 @@ func ResourceFunction() *schema.Resource {
7777
Type: schema.TypeString,
7878
ValidateFunc: validation.StringLenBetween(0, 1000),
7979
},
80-
ValidateDiagFunc: validation.MapKeyLenBetween(0, 100),
80+
ValidateDiagFunc: validation.MapKeyLenBetween(0, 100),
81+
DiffSuppressFunc: dsf.CompareArgon2idPasswordAndHash,
82+
DiffSuppressOnRefresh: true,
8183
},
8284
"privacy": {
8385
Type: schema.TypeString,
@@ -307,6 +309,7 @@ func ResourceFunctionRead(ctx context.Context, d *schema.ResourceData, m interfa
307309
_ = d.Set("http_option", f.HTTPOption)
308310
_ = d.Set("namespace_id", f.NamespaceID)
309311
_ = d.Set("sandbox", f.Sandbox)
312+
_ = d.Set("secret_environment_variables", flattenFunctionSecrets(f.SecretEnvironmentVariables))
310313

311314
return diags
312315
}
@@ -340,7 +343,8 @@ func ResourceFunctionUpdate(ctx context.Context, d *schema.ResourceData, m inter
340343
}
341344

342345
if d.HasChanges("secret_environment_variables") {
343-
req.SecretEnvironmentVariables = expandFunctionsSecrets(d.Get("secret_environment_variables"))
346+
oldEnv, newEnv := d.GetChange("secret_environment_variables")
347+
req.SecretEnvironmentVariables = filterSecretEnvsToPatch(expandFunctionsSecrets(oldEnv), expandFunctionsSecrets(newEnv))
344348
updated = true
345349
}
346350

internal/services/function/function_test.go

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
package function_test
22

33
import (
4+
"errors"
45
"fmt"
56
"testing"
67

8+
"github.com/alexedwards/argon2id"
79
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
810
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
911
functionSDK "github.com/scaleway/scaleway-sdk-go/api/function/v1beta1"
@@ -142,7 +144,7 @@ func TestAccFunction_EnvironmentVariables(t *testing.T) {
142144
Check: resource.ComposeTestCheckFunc(
143145
testAccCheckFunctionExists(tt, "scaleway_function.main"),
144146
resource.TestCheckResourceAttr("scaleway_function.main", "environment_variables.test", "test"),
145-
resource.TestCheckResourceAttr("scaleway_function.main", "secret_environment_variables.test_secret", "test_secret"),
147+
passwordMatchHash("scaleway_function.main", "secret_environment_variables.test_secret", "test_secret"),
146148
),
147149
},
148150
{
@@ -167,7 +169,7 @@ func TestAccFunction_EnvironmentVariables(t *testing.T) {
167169
Check: resource.ComposeTestCheckFunc(
168170
testAccCheckFunctionExists(tt, "scaleway_function.main"),
169171
resource.TestCheckResourceAttr("scaleway_function.main", "environment_variables.foo", "bar"),
170-
resource.TestCheckResourceAttr("scaleway_function.main", "secret_environment_variables.foo_secret", "bar_secret"),
172+
passwordMatchHash("scaleway_function.main", "secret_environment_variables.foo_secret", "bar_secret"),
171173
),
172174
},
173175
},
@@ -457,3 +459,23 @@ func testAccCheckFunctionDestroy(tt *acctest.TestTools) resource.TestCheckFunc {
457459
return nil
458460
}
459461
}
462+
463+
func passwordMatchHash(parent string, key string, password string) resource.TestCheckFunc {
464+
return func(state *terraform.State) error {
465+
rs, ok := state.RootModule().Resources[parent]
466+
if !ok {
467+
return fmt.Errorf("resource container not found: %s", parent)
468+
}
469+
470+
match, err := argon2id.ComparePasswordAndHash(password, rs.Primary.Attributes[key])
471+
if err != nil {
472+
return err
473+
}
474+
475+
if !match {
476+
return errors.New("password and hash do not match")
477+
}
478+
479+
return nil
480+
}
481+
}

internal/services/function/helpers.go renamed to internal/services/function/helpers_function.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"net/http"
88
"net/http/httputil"
99
"os"
10+
"slices"
1011
"strings"
1112
"time"
1213

@@ -174,3 +175,39 @@ func retryCreateFunctionDomain(ctx context.Context, functionAPI *function.API, r
174175
}
175176
}
176177
}
178+
179+
func flattenFunctionSecrets(secrets []*function.SecretHashedValue) interface{} {
180+
if len(secrets) == 0 {
181+
return nil
182+
}
183+
184+
flattenedSecrets := make(map[string]interface{})
185+
for _, secret := range secrets {
186+
flattenedSecrets[secret.Key] = secret.HashedValue
187+
}
188+
189+
return flattenedSecrets
190+
}
191+
192+
func filterSecretEnvsToPatch(oldEnv []*function.Secret, newEnv []*function.Secret) []*function.Secret {
193+
toPatch := []*function.Secret{}
194+
// create and update - ignore hashed values
195+
for _, env := range newEnv {
196+
if env.Value != nil && strings.HasPrefix(*env.Value, "$argon2id") {
197+
continue
198+
}
199+
200+
toPatch = append(toPatch, env)
201+
}
202+
203+
// delete
204+
for _, env := range oldEnv {
205+
if !slices.ContainsFunc(newEnv, func(s *function.Secret) bool {
206+
return s.Key == env.Key
207+
}) {
208+
toPatch = append(toPatch, &function.Secret{Key: env.Key, Value: nil})
209+
}
210+
}
211+
212+
return toPatch
213+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package function
2+
3+
import (
4+
"testing"
5+
6+
functionSDK "github.com/scaleway/scaleway-sdk-go/api/function/v1beta1"
7+
"github.com/stretchr/testify/assert"
8+
)
9+
10+
func TestFilterSecretEnvsToPatch(t *testing.T) {
11+
testSecret := "test_secret"
12+
secretToDelete := "secret_to_delete"
13+
updatedSecret := "updated_secret"
14+
newSecret := "new_secret"
15+
16+
oldEnv := []*functionSDK.Secret{
17+
{Key: testSecret, Value: &testSecret},
18+
{Key: secretToDelete, Value: &secretToDelete},
19+
}
20+
newEnv := []*functionSDK.Secret{
21+
{Key: testSecret, Value: &updatedSecret},
22+
{Key: newSecret, Value: &newSecret},
23+
}
24+
25+
toPatch := filterSecretEnvsToPatch(oldEnv, newEnv)
26+
assert.Equal(t, []*functionSDK.Secret{
27+
{Key: testSecret, Value: &updatedSecret},
28+
{Key: newSecret, Value: &newSecret},
29+
{Key: secretToDelete, Value: nil},
30+
}, toPatch)
31+
}

0 commit comments

Comments
 (0)