Skip to content

Commit d525d9f

Browse files
committed
fix(container): explicitely require project_id at the resource level
1 parent ee4eaf3 commit d525d9f

File tree

12 files changed

+534
-345
lines changed

12 files changed

+534
-345
lines changed

internal/acctest/acctest.go

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,57 @@ func NewTestTools(t *testing.T) *TestTools {
3434
}
3535

3636
// Create a http client with recording capabilities
37-
httpClient, cleanup, err := getHTTPRecoder(t, folder, *UpdateCassettes)
37+
httpClient, cleanup, err := getHTTPRecorder(t, folder, *UpdateCassettes, cassetteMatcher)
3838
require.NoError(t, err)
3939

4040
// Create meta that will be passed in the provider config
4141
m, err := meta.NewMeta(ctx, &meta.Config{
4242
ProviderSchema: nil,
4343
TerraformVersion: "terraform-tests",
4444
HTTPClient: httpClient,
45+
ForceProjectID: "00000000-0000-0000-0000-000000000000",
46+
})
47+
require.NoError(t, err)
48+
49+
if !*UpdateCassettes {
50+
tmp := 0 * time.Second
51+
transport.DefaultWaitRetryInterval = &tmp
52+
}
53+
54+
return &TestTools{
55+
T: t,
56+
Meta: m,
57+
ProviderFactories: map[string]func() (*schema.Provider, error){
58+
"scaleway": func() (*schema.Provider, error) {
59+
return provider.Provider(&provider.Config{Meta: m})(), nil
60+
},
61+
},
62+
Cleanup: cleanup,
63+
}
64+
}
65+
66+
/*
67+
Tested resources that depends on a projectID in the query parameters should use this function
68+
Otherwise, tests will fail because the projectID will not match the ones in the recorded cassette queries
69+
*/
70+
func NewTestToolsWithoutDefaultProjectID(t *testing.T) *TestTools {
71+
t.Helper()
72+
73+
ctx := t.Context()
74+
75+
folder, err := os.Getwd()
76+
if err != nil {
77+
t.Fatalf("cannot detect working directory for testing")
78+
}
79+
80+
httpClient, cleanup, err := getHTTPRecorder(t, folder, *UpdateCassettes, cassetteMatcherWithoutProjectID)
81+
require.NoError(t, err)
82+
83+
m, err := meta.NewMeta(ctx, &meta.Config{
84+
ProviderSchema: nil,
85+
TerraformVersion: "terraform-tests",
86+
HTTPClient: httpClient,
87+
ForceProjectID: "00000000-0000-0000-0000-000000000000",
4588
})
4689
require.NoError(t, err)
4790

internal/acctest/vcr.go

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,30 @@ func cassetteMatcher(actual *http.Request, expected cassette.Request) bool {
235235
cassetteBodyMatcher(actual, expected)
236236
}
237237

238+
// cassetteMatcherWithoutProjectID strip the project_id from the query to match the query of the recorded cassette
239+
func cassetteMatcherWithoutProjectID(actual *http.Request, expected cassette.Request) bool {
240+
expectedURL, _ := url.Parse(expected.URL)
241+
actualURL := actual.URL
242+
actualURLValues := actualURL.Query()
243+
expectedURLValues := expectedURL.Query()
244+
245+
for _, query := range QueryMatcherIgnore {
246+
actualURLValues.Del(query)
247+
expectedURLValues.Del(query)
248+
}
249+
250+
actualURLValues.Del("project_id")
251+
expectedURLValues.Del("project_id")
252+
253+
actualURL.RawQuery = actualURLValues.Encode()
254+
expectedURL.RawQuery = expectedURLValues.Encode()
255+
256+
return actual.Method == expected.Method &&
257+
actual.URL.Path == expectedURL.Path &&
258+
actualURL.RawQuery == expectedURL.RawQuery &&
259+
cassetteBodyMatcher(actual, expected)
260+
}
261+
238262
func cassetteSensitiveFieldsAnonymizer(i *cassette.Interaction) error {
239263
var jsonBody map[string]interface{}
240264

@@ -260,13 +284,13 @@ func cassetteSensitiveFieldsAnonymizer(i *cassette.Interaction) error {
260284
return nil
261285
}
262286

263-
// getHTTPRecoder creates a new httpClient that records all HTTP requests in a cassette.
287+
// getHTTPRecorder creates a new httpClient that records all HTTP requests in a cassette.
264288
// This cassette is then replayed whenever tests are executed again. This means that once the
265289
// requests are recorded in the cassette, no more real HTTP requests must be made to run the tests.
266290
//
267291
// It is important to add a `defer cleanup()` so the given cassette files are correctly
268292
// closed and saved after the requests.
269-
func getHTTPRecoder(t *testing.T, pkgFolder string, update bool) (client *http.Client, cleanup func(), err error) {
293+
func getHTTPRecorder(t *testing.T, pkgFolder string, update bool, matcherFunc cassette.MatcherFunc) (client *http.Client, cleanup func(), err error) {
270294
t.Helper()
271295

272296
recorderMode := recorder.ModeReplayOnly
@@ -297,7 +321,7 @@ func getHTTPRecoder(t *testing.T, pkgFolder string, update bool) (client *http.C
297321
}(r)
298322

299323
// Add custom matcher for requests and cassettes
300-
r.SetMatcher(cassetteMatcher)
324+
r.SetMatcher(matcherFunc)
301325

302326
// Add a filter which removes Authorization headers from all requests:
303327
r.AddHook(func(i *cassette.Interaction) error {

internal/services/account/project_data_source_test.go

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -95,30 +95,6 @@ func TestAccDataSourceProject_Default(t *testing.T) {
9595
})
9696
}
9797

98-
func TestAccDataSourceProject_Extract(t *testing.T) {
99-
tt := acctest.NewTestTools(t)
100-
defer tt.Cleanup()
101-
102-
projectID, projectIDExists := tt.Meta.ScwClient().GetDefaultProjectID()
103-
if !projectIDExists {
104-
t.Skip("no default project ID")
105-
}
106-
107-
resource.ParallelTest(t, resource.TestCase{
108-
PreCheck: func() { acctest.PreCheck(t) },
109-
ProviderFactories: tt.ProviderFactories,
110-
Steps: []resource.TestStep{
111-
{
112-
Config: `data scaleway_account_project "project" {}`,
113-
Check: resource.ComposeTestCheckFunc(
114-
resource.TestCheckResourceAttr("data.scaleway_account_project.project", "id", projectID),
115-
resource.TestCheckResourceAttrSet("data.scaleway_account_project.project", "name"),
116-
),
117-
},
118-
},
119-
})
120-
}
121-
12298
func TestAccDataSourceProject_List(t *testing.T) {
12399
tt := acctest.NewTestTools(t)
124100
defer tt.Cleanup()

internal/services/billing/consumption_data_source_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ import (
1010
)
1111

1212
func TestAccDataSourceConsumption_Basic(t *testing.T) {
13-
tt := acctest.NewTestTools(t)
13+
// somehow the project_id is not set in the query parameters locally when the organization_id is set
14+
tt := acctest.NewTestToolsWithoutDefaultProjectID(t)
1415
defer tt.Cleanup()
1516

1617
resource.ParallelTest(t, resource.TestCase{

internal/services/container/container_data_source.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"github.com/scaleway/scaleway-sdk-go/scw"
1010
"github.com/scaleway/terraform-provider-scaleway/v2/internal/datasource"
1111
"github.com/scaleway/terraform-provider-scaleway/v2/internal/locality"
12+
"github.com/scaleway/terraform-provider-scaleway/v2/internal/meta"
1213
"github.com/scaleway/terraform-provider-scaleway/v2/internal/types"
1314
"github.com/scaleway/terraform-provider-scaleway/v2/internal/verify"
1415
)
@@ -58,11 +59,16 @@ func DataSourceContainerRead(ctx context.Context, d *schema.ResourceData, m inte
5859
if !ok {
5960
containerName := d.Get("name").(string)
6061

62+
projectID, _, err := meta.ExtractProjectID(d, m)
63+
if err != nil {
64+
return diag.FromErr(err)
65+
}
66+
6167
res, err := api.ListContainers(&container.ListContainersRequest{
6268
Region: region,
6369
Name: types.ExpandStringPtr(containerName),
6470
NamespaceID: locality.ExpandID(namespaceID),
65-
ProjectID: types.ExpandStringPtr(d.Get("project_id")),
71+
ProjectID: types.ExpandStringPtr(projectID),
6672
}, scw.WithContext(ctx))
6773
if err != nil {
6874
return diag.FromErr(err)

internal/services/container/container_data_source_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import (
88
)
99

1010
func TestAccDataSourceContainer_Basic(t *testing.T) {
11-
tt := acctest.NewTestTools(t)
11+
tt := acctest.NewTestToolsWithoutDefaultProjectID(t)
1212
defer tt.Cleanup()
1313

1414
resource.ParallelTest(t, resource.TestCase{
@@ -30,7 +30,7 @@ func TestAccDataSourceContainer_Basic(t *testing.T) {
3030
namespace_id = scaleway_container_namespace.main.id
3131
name = scaleway_container.main.name
3232
}
33-
33+
3434
data "scaleway_container" "by_id" {
3535
namespace_id = scaleway_container_namespace.main.id
3636
container_id = scaleway_container.main.id
@@ -51,7 +51,7 @@ func TestAccDataSourceContainer_Basic(t *testing.T) {
5151
}
5252

5353
func TestAccDataSourceContainer_HealthCheck(t *testing.T) {
54-
tt := acctest.NewTestTools(t)
54+
tt := acctest.NewTestToolsWithoutDefaultProjectID(t)
5555
defer tt.Cleanup()
5656

5757
resource.ParallelTest(t, resource.TestCase{

internal/services/container/container_test.go

Lines changed: 29 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import (
1212
"github.com/scaleway/terraform-provider-scaleway/v2/internal/acctest"
1313
"github.com/scaleway/terraform-provider-scaleway/v2/internal/httperrors"
1414
"github.com/scaleway/terraform-provider-scaleway/v2/internal/services/container"
15-
containerchecks "github.com/scaleway/terraform-provider-scaleway/v2/internal/services/container/testfuncs"
1615
)
1716

1817
func TestAccContainer_Basic(t *testing.T) {
@@ -220,51 +219,32 @@ func TestAccContainer_WithIMG(t *testing.T) {
220219
Steps: []resource.TestStep{
221220
{
222221
Config: fmt.Sprintf(`
223-
resource scaleway_container_namespace main {
224-
name = "%s"
225-
description = "test container"
226-
}
227-
`, containerNamespace),
228-
},
229-
{
230-
Config: fmt.Sprintf(`
231-
resource scaleway_container_namespace main {
232-
name = "%s"
233-
description = "test container"
234-
}
235-
`, containerNamespace),
236-
Check: resource.ComposeTestCheckFunc(
237-
containerchecks.TestConfigContainerNamespace(tt, "scaleway_container_namespace.main"),
238-
),
239-
},
240-
{
241-
Config: fmt.Sprintf(`
242-
resource scaleway_container_namespace main {
243-
name = "%s"
244-
description = "test container"
245-
}
246-
247-
resource scaleway_container main {
248-
name = "my-container-02"
249-
description = "environment variables test"
250-
namespace_id = scaleway_container_namespace.main.id
251-
registry_image = "${scaleway_container_namespace.main.registry_endpoint}/nginx:test"
252-
port = 80
253-
cpu_limit = 140
254-
memory_limit = 256
255-
min_scale = 3
256-
max_scale = 5
257-
timeout = 600
258-
max_concurrency = 80
259-
privacy = "private"
260-
protocol = "h2c"
261-
deploy = true
262-
263-
environment_variables = {
264-
"foo" = "var"
265-
}
266-
}
267-
`, containerNamespace),
222+
resource scaleway_container_namespace main {
223+
name = "%s"
224+
description = "test container"
225+
}
226+
227+
resource scaleway_container main {
228+
name = "my-container-02"
229+
description = "environment variables test"
230+
namespace_id = scaleway_container_namespace.main.id
231+
registry_image = "docker.io/library/nginx:latest"
232+
port = 80
233+
cpu_limit = 140
234+
memory_limit = 256
235+
min_scale = 3
236+
max_scale = 5
237+
timeout = 600
238+
max_concurrency = 80
239+
privacy = "private"
240+
protocol = "h2c"
241+
deploy = true
242+
243+
environment_variables = {
244+
"foo" = "var"
245+
}
246+
}
247+
`, containerNamespace),
268248
Check: resource.ComposeTestCheckFunc(
269249
isContainerPresent(tt, "scaleway_container.main"),
270250
acctest.CheckResourceAttrUUID("scaleway_container.main", "id"),
@@ -493,7 +473,7 @@ func TestAccContainer_ScalingOption(t *testing.T) {
493473
{
494474
Config: `
495475
resource scaleway_container_namespace main {}
496-
476+
497477
resource scaleway_container main {
498478
namespace_id = scaleway_container_namespace.main.id
499479
deploy = false
@@ -512,7 +492,7 @@ func TestAccContainer_ScalingOption(t *testing.T) {
512492
{
513493
Config: `
514494
resource scaleway_container_namespace main {}
515-
495+
516496
resource scaleway_container main {
517497
namespace_id = scaleway_container_namespace.main.id
518498
deploy = false
@@ -534,7 +514,7 @@ func TestAccContainer_ScalingOption(t *testing.T) {
534514
{
535515
Config: `
536516
resource scaleway_container_namespace main {}
537-
517+
538518
resource scaleway_container main {
539519
namespace_id = scaleway_container_namespace.main.id
540520
deploy = false

internal/services/container/namespace.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"github.com/scaleway/terraform-provider-scaleway/v2/internal/dsf"
1313
"github.com/scaleway/terraform-provider-scaleway/v2/internal/httperrors"
1414
"github.com/scaleway/terraform-provider-scaleway/v2/internal/locality/regional"
15+
"github.com/scaleway/terraform-provider-scaleway/v2/internal/meta"
1516
"github.com/scaleway/terraform-provider-scaleway/v2/internal/services/account"
1617
"github.com/scaleway/terraform-provider-scaleway/v2/internal/services/registry"
1718
"github.com/scaleway/terraform-provider-scaleway/v2/internal/types"
@@ -108,12 +109,17 @@ func ResourceContainerNamespaceCreate(ctx context.Context, d *schema.ResourceDat
108109
return diag.FromErr(err)
109110
}
110111

112+
projectId, _, err := meta.ExtractProjectID(d, m)
113+
if err != nil {
114+
return diag.FromErr(err)
115+
}
116+
111117
createReq := &container.CreateNamespaceRequest{
112118
Description: types.ExpandStringPtr(d.Get("description").(string)),
113119
EnvironmentVariables: types.ExpandMapPtrStringString(d.Get("environment_variables")),
114120
SecretEnvironmentVariables: expandContainerSecrets(d.Get("secret_environment_variables")),
115121
Name: types.ExpandOrGenerateString(d.Get("name").(string), "ns"),
116-
ProjectID: d.Get("project_id").(string),
122+
ProjectID: projectId,
117123
Region: region,
118124
}
119125

internal/services/container/namespace_data_source.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
container "github.com/scaleway/scaleway-sdk-go/api/container/v1beta1"
99
"github.com/scaleway/scaleway-sdk-go/scw"
1010
"github.com/scaleway/terraform-provider-scaleway/v2/internal/datasource"
11+
"github.com/scaleway/terraform-provider-scaleway/v2/internal/meta"
1112
"github.com/scaleway/terraform-provider-scaleway/v2/internal/types"
1213
"github.com/scaleway/terraform-provider-scaleway/v2/internal/verify"
1314
)
@@ -43,10 +44,15 @@ func DataSourceContainerNamespaceRead(ctx context.Context, d *schema.ResourceDat
4344
if !ok {
4445
namespaceName := d.Get("name").(string)
4546

47+
projectID, _, err := meta.ExtractProjectID(d, m)
48+
if err != nil {
49+
return diag.FromErr(err)
50+
}
51+
4652
res, err := api.ListNamespaces(&container.ListNamespacesRequest{
4753
Region: region,
4854
Name: types.ExpandStringPtr(namespaceName),
49-
ProjectID: types.ExpandStringPtr(d.Get("project_id")),
55+
ProjectID: types.ExpandStringPtr(projectID),
5056
}, scw.WithContext(ctx))
5157
if err != nil {
5258
return diag.FromErr(err)

internal/services/container/namespace_data_source_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import (
88
)
99

1010
func TestAccDataSourceNamespace_Basic(t *testing.T) {
11-
tt := acctest.NewTestTools(t)
11+
tt := acctest.NewTestToolsWithoutDefaultProjectID(t)
1212
defer tt.Cleanup()
1313

1414
resource.ParallelTest(t, resource.TestCase{
@@ -21,11 +21,11 @@ func TestAccDataSourceNamespace_Basic(t *testing.T) {
2121
resource "scaleway_container_namespace" "main" {
2222
name = "test-cr-data"
2323
}
24-
24+
2525
data "scaleway_container_namespace" "by_name" {
2626
name = scaleway_container_namespace.main.name
2727
}
28-
28+
2929
data "scaleway_container_namespace" "by_id" {
3030
namespace_id = scaleway_container_namespace.main.id
3131
}

0 commit comments

Comments
 (0)