Skip to content

Commit 00eb669

Browse files
feat(iam): add new data source iam_policy
1 parent 97801bb commit 00eb669

File tree

8 files changed

+235
-18
lines changed

8 files changed

+235
-18
lines changed

docs/data-sources/iam_policy.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
---
2+
subcategory: "IAM"
3+
page_title: "Scaleway: scaleway_iam_policy"
4+
---
5+
6+
# scaleway_iam_policy
7+
8+
Use this data source to get information on an existing IAM policy based on its ID.
9+
For more information refer to the [IAM API documentation](https://developers.scaleway.com/en/products/iam/api/).
10+
11+
## Example Usage
12+
13+
```hcl
14+
# Get policy by id
15+
data "scaleway_iam_policy" "find_by_id" {
16+
policy_id = "11111111-1111-1111-1111-111111111111"
17+
}
18+
```
19+
20+
## Argument Reference
21+
22+
- `policy_id` - The ID of the IAM policy.
23+
24+
## Attributes Reference
25+
26+
In addition to all above arguments, the following attributes are exported:
27+
28+
- `id` - The ID of the IAM policy.
29+
- `created_at` - The date and time of the creation of the IAM policy.
30+
- `updated_at` - The date and time of the last update of the IAM policy.
31+
- `editable` - Whether the IAM policy is editable.

internal/acctest/fixtures.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ func FakeSideProjectProviders(ctx context.Context, tt *TestTools, project *accou
5757
// CreateFakeIAMManager creates a temporary project with a temporary IAM application and policy manager.
5858
//
5959
// The returned function is a cleanup function that should be called when to delete the project.
60-
func CreateFakeIAMManager(tt *TestTools) (*account.Project, *iam.APIKey, FakeSideProjectTerminateFunc, error) {
60+
func CreateFakeIAMManager(tt *TestTools) (*account.Project, *iam.APIKey, *iam.Policy, FakeSideProjectTerminateFunc, error) {
6161
terminateFunctions := []FakeSideProjectTerminateFunc{}
6262
terminate := func() error {
6363
for i := len(terminateFunctions) - 1; i >= 0; i-- {
@@ -81,10 +81,10 @@ func CreateFakeIAMManager(tt *TestTools) (*account.Project, *iam.APIKey, FakeSid
8181
})
8282
if err != nil {
8383
if err := terminate(); err != nil {
84-
return nil, nil, nil, err
84+
return nil, nil, nil, nil, err
8585
}
8686

87-
return nil, nil, nil, err
87+
return nil, nil, nil, nil, err
8888
}
8989

9090
terminateFunctions = append(terminateFunctions, func() error {
@@ -100,10 +100,10 @@ func CreateFakeIAMManager(tt *TestTools) (*account.Project, *iam.APIKey, FakeSid
100100
})
101101
if err != nil {
102102
if err := terminate(); err != nil {
103-
return nil, nil, nil, err
103+
return nil, nil, nil, nil, err
104104
}
105105

106-
return nil, nil, nil, err
106+
return nil, nil, nil, nil, err
107107
}
108108

109109
terminateFunctions = append(terminateFunctions, func() error {
@@ -124,10 +124,10 @@ func CreateFakeIAMManager(tt *TestTools) (*account.Project, *iam.APIKey, FakeSid
124124
})
125125
if err != nil {
126126
if err := terminate(); err != nil {
127-
return nil, nil, nil, err
127+
return nil, nil, nil, nil, err
128128
}
129129

130-
return nil, nil, nil, err
130+
return nil, nil, nil, nil, err
131131
}
132132

133133
terminateFunctions = append(terminateFunctions, func() error {
@@ -142,10 +142,10 @@ func CreateFakeIAMManager(tt *TestTools) (*account.Project, *iam.APIKey, FakeSid
142142
})
143143
if err != nil {
144144
if err := terminate(); err != nil {
145-
return nil, nil, nil, err
145+
return nil, nil, nil, nil, err
146146
}
147147

148-
return nil, nil, nil, err
148+
return nil, nil, nil, nil, err
149149
}
150150

151151
terminateFunctions = append(terminateFunctions, func() error {
@@ -154,7 +154,7 @@ func CreateFakeIAMManager(tt *TestTools) (*account.Project, *iam.APIKey, FakeSid
154154
})
155155
})
156156

157-
return project, iamAPIKey, terminate, nil
157+
return project, iamAPIKey, iamPolicy, terminate, nil
158158
}
159159

160160
type FakeSideProjectTerminateFunc func() error
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package iam
2+
3+
import (
4+
"context"
5+
6+
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
7+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
8+
iam "github.com/scaleway/scaleway-sdk-go/api/iam/v1alpha1"
9+
"github.com/scaleway/scaleway-sdk-go/scw"
10+
"github.com/scaleway/terraform-provider-scaleway/v2/internal/datasource"
11+
"github.com/scaleway/terraform-provider-scaleway/v2/internal/types"
12+
"github.com/scaleway/terraform-provider-scaleway/v2/internal/verify"
13+
)
14+
15+
func DataSourcePolicy() *schema.Resource {
16+
// Generate datasource schema from resource
17+
dsSchema := datasource.SchemaFromResourceSchema(ResourcePolicy().Schema)
18+
datasource.AddOptionalFieldsToSchema(dsSchema, "name", "organization_id")
19+
20+
dsSchema["name"].ConflictsWith = []string{"policy_id"}
21+
dsSchema["policy_id"] = &schema.Schema{
22+
Type: schema.TypeString,
23+
Optional: true,
24+
Description: "The ID of the policy",
25+
ValidateDiagFunc: verify.IsUUID(),
26+
}
27+
28+
return &schema.Resource{
29+
ReadContext: DataSourceIamPolicyRead,
30+
Schema: dsSchema,
31+
}
32+
}
33+
34+
func DataSourceIamPolicyRead(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics {
35+
iamAPI := NewAPI(m)
36+
37+
policyID, policyIDExists := d.GetOk("policy_id")
38+
if !policyIDExists {
39+
policyName := d.Get("name").(string)
40+
41+
res, err := iamAPI.ListPolicies(&iam.ListPoliciesRequest{
42+
PolicyName: types.ExpandStringPtr(policyName),
43+
OrganizationID: *types.ExpandStringPtr(d.Get("organization_id")),
44+
}, scw.WithContext(ctx))
45+
if err != nil {
46+
return diag.FromErr(err)
47+
}
48+
49+
foundPolicy, err := datasource.FindExact(
50+
res.Policies,
51+
func(s *iam.Policy) bool { return s.Name == policyName },
52+
policyName,
53+
)
54+
if err != nil {
55+
return diag.FromErr(err)
56+
}
57+
58+
policyID = foundPolicy.ID
59+
}
60+
61+
d.SetId(policyID.(string))
62+
63+
err := d.Set("policy_id", policyID)
64+
if err != nil {
65+
return diag.FromErr(err)
66+
}
67+
68+
diags := resourceIamPolicyRead(ctx, d, m)
69+
if diags != nil {
70+
return append(diags, diag.Errorf("failed to read iam policy state")...)
71+
}
72+
73+
if d.Id() == "" {
74+
return diag.Errorf("iam policy (%s) not found", policyID)
75+
}
76+
77+
return nil
78+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package iam_test
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
7+
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
8+
"github.com/hashicorp/terraform-plugin-testing/terraform"
9+
"github.com/scaleway/terraform-provider-scaleway/v2/internal/acctest"
10+
"github.com/stretchr/testify/require"
11+
)
12+
13+
func TestAccDataSourcePolicy_Basic(t *testing.T) {
14+
tt := acctest.NewTestTools(t)
15+
defer tt.Cleanup()
16+
17+
ctx := t.Context()
18+
project, iamAPIKey, iamPolicy, terminateFakeSideProject, err := acctest.CreateFakeIAMManager(tt)
19+
require.NoError(t, err)
20+
21+
resource.ParallelTest(t, resource.TestCase{
22+
PreCheck: func() { acctest.PreCheck(t) },
23+
ProtoV6ProviderFactories: acctest.FakeSideProjectProviders(ctx, tt, project, iamAPIKey),
24+
CheckDestroy: resource.ComposeAggregateTestCheckFunc(
25+
func(_ *terraform.State) error {
26+
return terminateFakeSideProject()
27+
},
28+
testAccCheckIamPolicyDestroy(tt),
29+
),
30+
Steps: []resource.TestStep{
31+
{
32+
Config: fmt.Sprintf(`
33+
resource "scaleway_iam_policy" "main" {
34+
name = "%s"
35+
description = "a description"
36+
application_id = "%s"
37+
rule {
38+
organization_id = "%s"
39+
permission_set_names = ["IAMManager"]
40+
}
41+
provider = side
42+
}
43+
44+
data "scaleway_iam_policy" "by_name" {
45+
name = "${scaleway_iam_policy.main.name}"
46+
}
47+
48+
data "scaleway_iam_policy" "by_id" {
49+
policy_id = "${scaleway_iam_policy.main.id}"
50+
}`, iamPolicy.Name, *iamPolicy.ApplicationID, project.OrganizationID),
51+
Check: resource.ComposeTestCheckFunc(
52+
// Check by name
53+
testAccCheckIamPolicyExists(tt, "data.scaleway_iam_policy.by_name"),
54+
resource.TestCheckResourceAttr("data.scaleway_iam_policy.by_name", "name", iamPolicy.Name),
55+
resource.TestCheckResourceAttr("data.scaleway_iam_policy.by_name", "description", "a description"),
56+
resource.TestCheckResourceAttr("data.scaleway_iam_policy.by_name", "application_id", *iamPolicy.ApplicationID),
57+
resource.TestCheckResourceAttr("data.scaleway_iam_policy.by_name", "rule.0.organization_id", project.OrganizationID),
58+
// Check by id
59+
testAccCheckIamPolicyExists(tt, "data.scaleway_iam_policy.by_id"),
60+
resource.TestCheckResourceAttr("data.scaleway_iam_policy.by_id", "name", iamPolicy.Name),
61+
resource.TestCheckResourceAttr("data.scaleway_iam_policy.by_id", "description", "a description"),
62+
resource.TestCheckResourceAttr("data.scaleway_iam_policy.by_id", "application_id", *iamPolicy.ApplicationID),
63+
resource.TestCheckResourceAttr("data.scaleway_iam_policy.by_id", "rule.0.organization_id", project.OrganizationID),
64+
65+
// Ensure both refer to the same policy
66+
resource.TestCheckResourceAttrPair(
67+
"data.scaleway_iam_policy.by_name",
68+
"id",
69+
"data.scaleway_iam_policy.by_id",
70+
"id",
71+
),
72+
),
73+
},
74+
},
75+
})
76+
}

internal/services/iam/policy_test.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ func TestAccPolicy_Basic(t *testing.T) {
1818
defer tt.Cleanup()
1919

2020
ctx := t.Context()
21-
project, iamAPIKey, terminateFakeSideProject, err := acctest.CreateFakeIAMManager(tt)
21+
project, iamAPIKey, _, terminateFakeSideProject, err := acctest.CreateFakeIAMManager(tt)
2222
require.NoError(t, err)
2323

2424
resource.ParallelTest(t, resource.TestCase{
@@ -92,7 +92,7 @@ func TestAccPolicy_NoUpdate(t *testing.T) {
9292
defer tt.Cleanup()
9393

9494
ctx := t.Context()
95-
project, iamAPIKey, terminateFakeSideProject, err := acctest.CreateFakeIAMManager(tt)
95+
project, iamAPIKey, _, terminateFakeSideProject, err := acctest.CreateFakeIAMManager(tt)
9696
require.NoError(t, err)
9797

9898
resource.ParallelTest(t, resource.TestCase{
@@ -155,7 +155,7 @@ func TestAccPolicy_ChangeLinkedEntity(t *testing.T) {
155155
defer tt.Cleanup()
156156

157157
ctx := t.Context()
158-
project, iamAPIKey, terminateFakeSideProject, err := acctest.CreateFakeIAMManager(tt)
158+
project, iamAPIKey, _, terminateFakeSideProject, err := acctest.CreateFakeIAMManager(tt)
159159
require.NoError(t, err)
160160

161161
randAppName := "tf-tests-scaleway-iam-app-policy-permissions"
@@ -261,7 +261,7 @@ func TestAccPolicy_ChangePermissions(t *testing.T) {
261261
defer tt.Cleanup()
262262

263263
ctx := t.Context()
264-
project, iamAPIKey, terminateFakeSideProject, err := acctest.CreateFakeIAMManager(tt)
264+
project, iamAPIKey, _, terminateFakeSideProject, err := acctest.CreateFakeIAMManager(tt)
265265
require.NoError(t, err)
266266

267267
resource.ParallelTest(t, resource.TestCase{
@@ -352,7 +352,7 @@ func TestAccPolicy_ProjectID(t *testing.T) {
352352
defer tt.Cleanup()
353353

354354
ctx := t.Context()
355-
project, iamAPIKey, terminateFakeSideProject, err := acctest.CreateFakeIAMManager(tt)
355+
project, iamAPIKey, _, terminateFakeSideProject, err := acctest.CreateFakeIAMManager(tt)
356356
require.NoError(t, err)
357357

358358
resource.ParallelTest(t, resource.TestCase{
@@ -418,7 +418,7 @@ func TestAccPolicy_Condition(t *testing.T) {
418418
defer tt.Cleanup()
419419

420420
ctx := t.Context()
421-
project, iamAPIKey, terminateFakeSideProject, err := acctest.CreateFakeIAMManager(tt)
421+
project, iamAPIKey, _, terminateFakeSideProject, err := acctest.CreateFakeIAMManager(tt)
422422
require.NoError(t, err)
423423

424424
resource.ParallelTest(t, resource.TestCase{
@@ -513,7 +513,7 @@ func TestAccPolicy_ChangeRulePrincipal(t *testing.T) {
513513
defer tt.Cleanup()
514514

515515
ctx := t.Context()
516-
project, iamAPIKey, terminateFakeSideProject, err := acctest.CreateFakeIAMManager(tt)
516+
project, iamAPIKey, _, terminateFakeSideProject, err := acctest.CreateFakeIAMManager(tt)
517517
require.NoError(t, err)
518518

519519
resource.ParallelTest(t, resource.TestCase{

internal/services/secret/secret_data_source_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ func TestAccDataSourceSecret_Basic(t *testing.T) {
1616

1717
ctx := t.Context()
1818
secretName := "scalewayDataSourceSecret"
19-
project, iamAPIKey, terminateFakeSideProject, err := acctest.CreateFakeIAMManager(tt)
19+
project, iamAPIKey, _, terminateFakeSideProject, err := acctest.CreateFakeIAMManager(tt)
2020
require.NoError(t, err)
2121

2222
resource.ParallelTest(t, resource.TestCase{

provider/sdkv2.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,7 @@ func SDKProvider(config *Config) plugin.ProviderFunc {
281281
"scaleway_function_namespace": function.DataSourceNamespace(),
282282
"scaleway_iam_application": iam.DataSourceApplication(),
283283
"scaleway_iam_group": iam.DataSourceGroup(),
284+
"scaleway_iam_policy": iam.DataSourcePolicy(),
284285
"scaleway_iam_ssh_key": iam.DataSourceSSHKey(),
285286
"scaleway_iam_user": iam.DataSourceUser(),
286287
"scaleway_iam_api_key": iam.DataSourceAPIKey(),
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
---
2+
subcategory: "IAM"
3+
page_title: "Scaleway: scaleway_iam_policy"
4+
---
5+
6+
# scaleway_iam_policy
7+
8+
Use this data source to get information on an existing IAM policy based on its ID.
9+
For more information refer to the [IAM API documentation](https://developers.scaleway.com/en/products/iam/api/).
10+
11+
## Example Usage
12+
13+
```hcl
14+
# Get policy by id
15+
data "scaleway_iam_policy" "find_by_id" {
16+
policy_id = "11111111-1111-1111-1111-111111111111"
17+
}
18+
```
19+
20+
## Argument Reference
21+
22+
- `policy_id` - The ID of the IAM policy.
23+
24+
## Attributes Reference
25+
26+
In addition to all above arguments, the following attributes are exported:
27+
28+
- `id` - The ID of the IAM policy.
29+
- `created_at` - The date and time of the creation of the IAM policy.
30+
- `updated_at` - The date and time of the last update of the IAM policy.
31+
- `editable` - Whether the IAM policy is editable.

0 commit comments

Comments
 (0)