Skip to content

Commit 9291f34

Browse files
committed
fix it
1 parent 6d5814e commit 9291f34

File tree

5 files changed

+1343
-375
lines changed

5 files changed

+1343
-375
lines changed

internal/services/jobs/definition.go

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"github.com/scaleway/scaleway-sdk-go/scw"
1414
"github.com/scaleway/terraform-provider-scaleway/v2/internal/dsf"
1515
"github.com/scaleway/terraform-provider-scaleway/v2/internal/httperrors"
16+
"github.com/scaleway/terraform-provider-scaleway/v2/internal/locality"
1617
"github.com/scaleway/terraform-provider-scaleway/v2/internal/locality/regional"
1718
"github.com/scaleway/terraform-provider-scaleway/v2/internal/services/account"
1819
"github.com/scaleway/terraform-provider-scaleway/v2/internal/types"
@@ -95,13 +96,23 @@ func ResourceDefinition() *schema.Resource {
9596
Type: schema.TypeSet,
9697
Optional: true,
9798
Description: "A reference to a Secret Manager secret.",
99+
Set: func(v interface{}) int {
100+
secret := v.(map[string]interface{})
101+
if secret["environment"] != "" {
102+
return schema.HashString(locality.ExpandID(secret["secret_id"].(string)) + secret["secret_version"].(string) + secret["environment"].(string))
103+
}
104+
return schema.HashString(locality.ExpandID(secret["secret_id"].(string)) + secret["secret_version"].(string) + secret["file"].(string))
105+
},
98106
Elem: &schema.Resource{
99107
Schema: map[string]*schema.Schema{
100108
"secret_id": {
101-
Type: schema.TypeString,
102-
Description: "The secret UUID.",
103-
Required: true,
104-
ValidateFunc: validation.IsUUID,
109+
Type: schema.TypeString,
110+
Description: "The secret unique identifier, it could be formatted as region/UUID or UUID. In case the region is passed, it must be the same as the job definition.",
111+
Required: true,
112+
DiffSuppressOnRefresh: true,
113+
DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool {
114+
return locality.ExpandID(old) == locality.ExpandID(new)
115+
},
105116
},
106117
"secret_reference_id": {
107118
Type: schema.TypeString,
@@ -123,7 +134,7 @@ func ResourceDefinition() *schema.Resource {
123134
Type: schema.TypeString,
124135
Optional: true,
125136
Description: "An environment variable containing the secret value.",
126-
ValidateFunc: validation.StringMatch(regexp.MustCompile(`^[A-Z]+(_[A-Z]+)*$`), "environment variable must be composed of uppercase letters separated by an underscore"),
137+
ValidateFunc: validation.StringMatch(regexp.MustCompile(`^[A-Z|0-9]+(_[A-Z|0-9]+)*$`), "environment variable must be composed of uppercase letters separated by an underscore"),
127138
},
128139
},
129140
},
@@ -171,7 +182,7 @@ func ResourceJobDefinitionCreate(ctx context.Context, d *schema.ResourceData, m
171182
}
172183

173184
if rawSecretReference, ok := d.GetOk("secret_reference"); ok {
174-
if err := CreateJobDefinitionSecret(rawSecretReference, api, region, definition.ID); err != nil {
185+
if err := CreateJobDefinitionSecret(ctx, api, expandJobDefinitionSecret(rawSecretReference), region, definition.ID); err != nil {
175186
return diag.FromErr(err)
176187
}
177188
}
@@ -304,21 +315,29 @@ func ResourceJobDefinitionUpdate(ctx context.Context, d *schema.ResourceData, m
304315
}
305316

306317
if d.HasChange("secret_reference") {
307-
oldRawSecretRefs, _ := d.GetChange("secret_reference")
318+
oldRawSecretRefs, newRawSecretRefs := d.GetChange("secret_reference")
319+
308320
oldSecretRefs := expandJobDefinitionSecret(oldRawSecretRefs)
321+
newSecretRefs := expandJobDefinitionSecret(newRawSecretRefs)
309322

310-
for _, oldSecretRef := range oldSecretRefs {
311-
if err := api.DeleteJobDefinitionSecret(&jobs.DeleteJobDefinitionSecretRequest{
323+
toCreate, toDelete, err := DiffJobDefinitionSecrets(oldSecretRefs, newSecretRefs)
324+
if err != nil {
325+
return diag.FromErr(err)
326+
}
327+
328+
for _, secret := range toDelete {
329+
deleteReq := &jobs.DeleteJobDefinitionSecretRequest{
312330
Region: region,
313331
JobDefinitionID: id,
314-
SecretID: oldSecretRef.SecretReferenceID,
315-
}); err != nil {
332+
SecretID: secret.SecretReferenceID,
333+
}
334+
if err := api.DeleteJobDefinitionSecret(deleteReq, scw.WithContext(ctx)); err != nil {
316335
return diag.FromErr(err)
317336
}
318337
}
319338

320-
if rawSecretReference, ok := d.GetOk("secret_reference"); ok {
321-
if err := CreateJobDefinitionSecret(rawSecretReference, api, region, id); err != nil {
339+
if len(toCreate) > 0 {
340+
if err := CreateJobDefinitionSecret(ctx, api, toCreate, region, id); err != nil {
322341
return diag.FromErr(err)
323342
}
324343
}

internal/services/jobs/definition_test.go

Lines changed: 178 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,12 @@ import (
88
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
99
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
1010
jobsSDK "github.com/scaleway/scaleway-sdk-go/api/jobs/v1alpha1"
11+
"github.com/scaleway/scaleway-sdk-go/scw"
1112
"github.com/scaleway/terraform-provider-scaleway/v2/internal/acctest"
1213
"github.com/scaleway/terraform-provider-scaleway/v2/internal/httperrors"
14+
"github.com/scaleway/terraform-provider-scaleway/v2/internal/locality/regional"
1315
"github.com/scaleway/terraform-provider-scaleway/v2/internal/services/jobs"
16+
"github.com/stretchr/testify/assert"
1417
)
1518

1619
func TestAccJobDefinition_Basic(t *testing.T) {
@@ -179,23 +182,19 @@ func TestAccJobDefinition_SecretReference(t *testing.T) {
179182
secret_id = scaleway_secret.main.id
180183
data = "your_secret"
181184
}
182-
locals {
183-
parts = split("/", scaleway_secret.main.id)
184-
secret_uuid = local.parts[1]
185-
}
186185
187186
resource scaleway_job_definition main {
188187
name = "test-jobs-job-definition-secret"
189188
cpu_limit = 120
190189
memory_limit = 256
191190
image_uri = "docker.io/alpine:latest"
192191
secret_reference {
193-
secret_id = local.secret_uuid
192+
secret_id = scaleway_secret.main.id
194193
secret_version = "latest"
195194
file = "/home/dev/env"
196195
}
197196
secret_reference {
198-
secret_id = local.secret_uuid
197+
secret_id = scaleway_secret.main.id
199198
secret_version = "latest"
200199
environment = "SOME_ENV"
201200
}
@@ -220,25 +219,21 @@ func TestAccJobDefinition_SecretReference(t *testing.T) {
220219
secret_id = scaleway_secret.main.id
221220
data = "your_secret"
222221
}
223-
locals {
224-
parts = split("/", scaleway_secret.main.id)
225-
secret_uuid = local.parts[1]
226-
}
227222
228223
resource scaleway_job_definition main {
229224
name = "test-jobs-job-definition-secret"
230225
cpu_limit = 120
231226
memory_limit = 256
232227
image_uri = "docker.io/alpine:latest"
233228
secret_reference {
234-
secret_id = local.secret_uuid
229+
secret_id = split("/", scaleway_secret.main.id)[1]
235230
secret_version = "latest"
236-
file = "/home/dev/new_env"
231+
file = "/home/dev/secret_file"
237232
}
238233
secret_reference {
239-
secret_id = local.secret_uuid
234+
secret_id = scaleway_secret.main.id
240235
secret_version = "latest"
241-
environment = "SOME_ENV"
236+
environment = "ANOTHER_ENV"
242237
}
243238
}
244239
`,
@@ -247,8 +242,39 @@ func TestAccJobDefinition_SecretReference(t *testing.T) {
247242
acctest.CheckResourceAttrUUID("scaleway_job_definition.main", "id"),
248243
resource.TestCheckResourceAttr("scaleway_job_definition.main", "name", "test-jobs-job-definition-secret"),
249244
resource.TestCheckResourceAttr("scaleway_job_definition.main", "secret_reference.#", "2"),
250-
resource.TestCheckResourceAttr("scaleway_job_definition.main", "secret_reference.0.file", "/home/dev/new_env"),
251-
resource.TestCheckResourceAttr("scaleway_job_definition.main", "secret_reference.1.environment", "SOME_ENV"),
245+
resource.TestCheckResourceAttr("scaleway_job_definition.main", "secret_reference.0.file", "/home/dev/secret_file"),
246+
resource.TestCheckResourceAttr("scaleway_job_definition.main", "secret_reference.1.environment", "ANOTHER_ENV"),
247+
),
248+
},
249+
{
250+
Config: `
251+
resource "scaleway_secret" "main" {
252+
name = "job-secret"
253+
path = "/one"
254+
}
255+
resource "scaleway_secret_version" "main" {
256+
secret_id = scaleway_secret.main.id
257+
data = "your_secret"
258+
}
259+
260+
resource scaleway_job_definition main {
261+
name = "test-jobs-job-definition-secret"
262+
cpu_limit = 120
263+
memory_limit = 256
264+
image_uri = "docker.io/alpine:latest"
265+
secret_reference {
266+
secret_id = scaleway_secret.main.id
267+
secret_version = "latest"
268+
file = "/home/dev/secret_file"
269+
}
270+
}
271+
`,
272+
Check: resource.ComposeTestCheckFunc(
273+
testAccCheckJobDefinitionExists(tt, "scaleway_job_definition.main"),
274+
acctest.CheckResourceAttrUUID("scaleway_job_definition.main", "id"),
275+
resource.TestCheckResourceAttr("scaleway_job_definition.main", "name", "test-jobs-job-definition-secret"),
276+
resource.TestCheckResourceAttr("scaleway_job_definition.main", "secret_reference.#", "1"),
277+
resource.TestCheckResourceAttr("scaleway_job_definition.main", "secret_reference.0.file", "/home/dev/secret_file"),
252278
),
253279
},
254280
},
@@ -267,24 +293,20 @@ func TestAccJobDefinition_WrongSecretReference(t *testing.T) {
267293
{
268294
Config: `
269295
resource "scaleway_secret" "main" {
270-
name = "job-secret"
296+
name = "wrong-job-secret"
271297
}
272298
resource "scaleway_secret_version" "main" {
273299
secret_id = scaleway_secret.main.id
274300
data = "your_secret"
275301
}
276-
locals {
277-
parts = split("/", scaleway_secret.main.id)
278-
secret_uuid = local.parts[1]
279-
}
280302
281303
resource scaleway_job_definition main {
282304
name = "test-jobs-job-definition-secret"
283305
cpu_limit = 120
284306
memory_limit = 256
285307
image_uri = "docker.io/alpine:latest"
286308
secret_reference {
287-
secret_id = local.secret_uuid
309+
secret_id = scaleway_secret.main.id
288310
secret_version = "1"
289311
}
290312
}
@@ -294,24 +316,20 @@ func TestAccJobDefinition_WrongSecretReference(t *testing.T) {
294316
{
295317
Config: `
296318
resource "scaleway_secret" "main" {
297-
name = "job-secret"
319+
name = "wrong-job-secret"
298320
}
299321
resource "scaleway_secret_version" "main" {
300322
secret_id = scaleway_secret.main.id
301323
data = "your_secret"
302324
}
303-
locals {
304-
parts = split("/", scaleway_secret.main.id)
305-
secret_uuid = local.parts[1]
306-
}
307325
308326
resource scaleway_job_definition main {
309327
name = "test-jobs-job-definition-secret"
310328
cpu_limit = 120
311329
memory_limit = 256
312330
image_uri = "docker.io/alpine:latest"
313331
secret_reference {
314-
secret_id = local.secret_uuid
332+
secret_id = scaleway_secret.main.id
315333
secret_version = "1"
316334
environment = "SOME_ENV"
317335
file = "/home/dev/env"
@@ -377,3 +395,135 @@ func testAccCheckJobDefinitionDestroy(tt *acctest.TestTools) resource.TestCheckF
377395
return nil
378396
}
379397
}
398+
399+
func TestCreateJobDefinitionSecret(t *testing.T) {
400+
jobSecrets := []jobs.JobDefinitionSecret{
401+
{
402+
SecretID: regional.NewID("fr-par", "11111111-1111-1111-1111-111111111111"),
403+
SecretVersion: "1",
404+
Environment: "SOME_ENV",
405+
},
406+
{
407+
SecretID: regional.NewID("nl-ams", "11111111-1111-1111-1111-111111111111"),
408+
SecretVersion: "1",
409+
File: "/home/dev/env",
410+
},
411+
}
412+
413+
api := jobsSDK.NewAPI(&scw.Client{})
414+
region := scw.RegionFrPar
415+
jobID := "22222222-2222-2222-2222-222222222222"
416+
417+
err := jobs.CreateJobDefinitionSecret(t.Context(), api, jobSecrets, region, jobID)
418+
assert.ErrorContains(t, err, fmt.Sprintf("the secret id %s is in the region %s, expected %s", jobSecrets[1].SecretID, jobSecrets[1].SecretID.Region, region))
419+
}
420+
421+
func TestDiffJobDefinitionSecrets(t *testing.T) {
422+
testCases := []struct {
423+
name string
424+
oldSecretRefs []jobs.JobDefinitionSecret
425+
newSecretRefs []jobs.JobDefinitionSecret
426+
expectedToCreate []jobs.JobDefinitionSecret
427+
expectedToDelete []jobs.JobDefinitionSecret
428+
}{
429+
{
430+
name: "no changes",
431+
oldSecretRefs: []jobs.JobDefinitionSecret{
432+
{
433+
SecretID: regional.NewID("fr-par", "11111111-1111-1111-1111-111111111111"),
434+
SecretVersion: "1",
435+
Environment: "SOME_ENV",
436+
},
437+
},
438+
newSecretRefs: []jobs.JobDefinitionSecret{
439+
{
440+
SecretID: regional.NewID("fr-par", "11111111-1111-1111-1111-111111111111"),
441+
SecretVersion: "1",
442+
Environment: "SOME_ENV",
443+
},
444+
},
445+
expectedToCreate: []jobs.JobDefinitionSecret{},
446+
expectedToDelete: []jobs.JobDefinitionSecret{},
447+
},
448+
{
449+
name: "create secret",
450+
oldSecretRefs: []jobs.JobDefinitionSecret{
451+
{
452+
SecretID: regional.NewID("fr-par", "11111111-1111-1111-1111-111111111111"),
453+
SecretVersion: "1",
454+
Environment: "SOME_ENV",
455+
},
456+
},
457+
newSecretRefs: []jobs.JobDefinitionSecret{
458+
{
459+
SecretID: regional.NewID("fr-par", "11111111-1111-1111-1111-111111111111"),
460+
SecretVersion: "1",
461+
Environment: "SOME_ENV",
462+
},
463+
{
464+
SecretID: regional.NewID("fr-par", "11111111-1111-1111-1111-111111111111"),
465+
SecretVersion: "1",
466+
Environment: "ANOTHER_ENV",
467+
},
468+
},
469+
expectedToCreate: []jobs.JobDefinitionSecret{
470+
{
471+
SecretID: regional.NewID("fr-par", "11111111-1111-1111-1111-111111111111"),
472+
SecretVersion: "1",
473+
Environment: "ANOTHER_ENV",
474+
},
475+
},
476+
expectedToDelete: []jobs.JobDefinitionSecret{},
477+
},
478+
{
479+
name: "delete and create secret",
480+
oldSecretRefs: []jobs.JobDefinitionSecret{
481+
{
482+
SecretID: regional.NewID("fr-par", "11111111-1111-1111-1111-111111111111"),
483+
SecretVersion: "1",
484+
Environment: "SOME_ENV",
485+
},
486+
{
487+
SecretID: regional.NewID("fr-par", "11111111-1111-1111-1111-111111111111"),
488+
SecretVersion: "1",
489+
Environment: "ANOTHER_ENV",
490+
},
491+
},
492+
newSecretRefs: []jobs.JobDefinitionSecret{
493+
{
494+
SecretID: regional.NewID("fr-par", "11111111-1111-1111-1111-111111111111"),
495+
SecretVersion: "1",
496+
File: "/home/dev/env",
497+
},
498+
{
499+
SecretID: regional.NewID("fr-par", "11111111-1111-1111-1111-111111111111"),
500+
SecretVersion: "1",
501+
Environment: "ANOTHER_ENV",
502+
},
503+
},
504+
expectedToCreate: []jobs.JobDefinitionSecret{
505+
{
506+
SecretID: regional.NewID("fr-par", "11111111-1111-1111-1111-111111111111"),
507+
SecretVersion: "1",
508+
File: "/home/dev/env",
509+
},
510+
},
511+
expectedToDelete: []jobs.JobDefinitionSecret{
512+
{
513+
SecretID: regional.NewID("fr-par", "11111111-1111-1111-1111-111111111111"),
514+
SecretVersion: "1",
515+
Environment: "SOME_ENV",
516+
},
517+
},
518+
},
519+
}
520+
521+
for _, testCase := range testCases {
522+
t.Run(testCase.name, func(t *testing.T) {
523+
toCreate, toDelete, err := jobs.DiffJobDefinitionSecrets(testCase.oldSecretRefs, testCase.newSecretRefs)
524+
assert.NoError(t, err)
525+
assert.Equal(t, testCase.expectedToCreate, toCreate)
526+
assert.Equal(t, testCase.expectedToDelete, toDelete)
527+
})
528+
}
529+
}

0 commit comments

Comments
 (0)