diff --git a/internal/identity/identity.go b/internal/identity/identity.go index 503d70c9da..e563ebea79 100644 --- a/internal/identity/identity.go +++ b/internal/identity/identity.go @@ -33,6 +33,16 @@ func DefaultRegional() *schema.ResourceIdentity { }) } +func FlatIdentity(key, description string) *schema.ResourceIdentity { + return WrapSchemaMap(map[string]*schema.Schema{ + key: { + Type: schema.TypeString, + Description: description, + RequiredForImport: true, + }, + }) +} + func WrapSchemaMap(m map[string]*schema.Schema) *schema.ResourceIdentity { return &schema.ResourceIdentity{ SchemaFunc: func() map[string]*schema.Schema { diff --git a/internal/services/iam/api_key.go b/internal/services/iam/api_key.go index 4059a808cb..389f3dd4bd 100644 --- a/internal/services/iam/api_key.go +++ b/internal/services/iam/api_key.go @@ -9,6 +9,7 @@ import ( "github.com/scaleway/scaleway-sdk-go/scw" "github.com/scaleway/terraform-provider-scaleway/v2/internal/dsf" "github.com/scaleway/terraform-provider-scaleway/v2/internal/httperrors" + "github.com/scaleway/terraform-provider-scaleway/v2/internal/identity" "github.com/scaleway/terraform-provider-scaleway/v2/internal/services/account" "github.com/scaleway/terraform-provider-scaleway/v2/internal/types" "github.com/scaleway/terraform-provider-scaleway/v2/internal/verify" @@ -25,6 +26,7 @@ func ResourceAPIKey() *schema.Resource { }, SchemaVersion: 0, SchemaFunc: apiKeySchema, + Identity: identity.FlatIdentity("id", "Access Key"), } } @@ -109,7 +111,10 @@ func resourceIamAPIKeyCreate(ctx context.Context, d *schema.ResourceData, m any) _ = d.Set("secret_key", res.SecretKey) - d.SetId(res.AccessKey) + err = identity.SetFlatIdentity(d, "id", res.AccessKey) + if err != nil { + return diag.FromErr(err) + } return resourceIamAPIKeyRead(ctx, d, m) } @@ -117,7 +122,7 @@ func resourceIamAPIKeyCreate(ctx context.Context, d *schema.ResourceData, m any) func resourceIamAPIKeyRead(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { api := NewAPI(m) - res, err := api.GetAPIKey(&iam.GetAPIKeyRequest{ + apiKey, err := api.GetAPIKey(&iam.GetAPIKeyRequest{ AccessKey: d.Id(), }, scw.WithContext(ctx)) if err != nil { @@ -130,25 +135,29 @@ func resourceIamAPIKeyRead(ctx context.Context, d *schema.ResourceData, m any) d return diag.FromErr(err) } - _ = d.Set("description", res.Description) - _ = d.Set("created_at", types.FlattenTime(res.CreatedAt)) - _ = d.Set("updated_at", types.FlattenTime(res.UpdatedAt)) - _ = d.Set("expires_at", types.FlattenTime(res.ExpiresAt)) - _ = d.Set("access_key", res.AccessKey) + setAPIKeyState(d, apiKey) - if res.ApplicationID != nil { - _ = d.Set("application_id", res.ApplicationID) - } + return nil +} + +func setAPIKeyState(d *schema.ResourceData, apiKey *iam.APIKey) { + _ = d.Set("description", apiKey.Description) + _ = d.Set("created_at", types.FlattenTime(apiKey.CreatedAt)) + _ = d.Set("updated_at", types.FlattenTime(apiKey.UpdatedAt)) + _ = d.Set("expires_at", types.FlattenTime(apiKey.ExpiresAt)) + _ = d.Set("access_key", apiKey.AccessKey) - if res.UserID != nil { - _ = d.Set("user_id", res.UserID) + if apiKey.ApplicationID != nil { + _ = d.Set("application_id", apiKey.ApplicationID) } - _ = d.Set("editable", res.Editable) - _ = d.Set("creation_ip", res.CreationIP) - _ = d.Set("default_project_id", res.DefaultProjectID) + if apiKey.UserID != nil { + _ = d.Set("user_id", apiKey.UserID) + } - return nil + _ = d.Set("editable", apiKey.Editable) + _ = d.Set("creation_ip", apiKey.CreationIP) + _ = d.Set("default_project_id", apiKey.DefaultProjectID) } func resourceIamAPIKeyUpdate(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { diff --git a/internal/services/iam/application.go b/internal/services/iam/application.go index ec2c173b26..32d7e37327 100644 --- a/internal/services/iam/application.go +++ b/internal/services/iam/application.go @@ -8,6 +8,7 @@ import ( iam "github.com/scaleway/scaleway-sdk-go/api/iam/v1alpha1" "github.com/scaleway/scaleway-sdk-go/scw" "github.com/scaleway/terraform-provider-scaleway/v2/internal/httperrors" + "github.com/scaleway/terraform-provider-scaleway/v2/internal/identity" "github.com/scaleway/terraform-provider-scaleway/v2/internal/services/account" "github.com/scaleway/terraform-provider-scaleway/v2/internal/types" ) @@ -23,6 +24,7 @@ func ResourceApplication() *schema.Resource { }, SchemaVersion: 0, SchemaFunc: applicationSchema, + Identity: identity.FlatIdentity("id", "Application UUID"), } } @@ -79,7 +81,7 @@ func resourceIamApplicationCreate(ctx context.Context, d *schema.ResourceData, m return diag.FromErr(err) } - d.SetId(app.ID) + err = identity.SetFlatIdentity(d, "id", app.ID) return resourceIamApplicationRead(ctx, d, m) } @@ -100,6 +102,12 @@ func resourceIamApplicationRead(ctx context.Context, d *schema.ResourceData, m a return diag.FromErr(err) } + setApplicationState(d, app) + + return nil +} + +func setApplicationState(d *schema.ResourceData, app *iam.Application) { _ = d.Set("name", app.Name) _ = d.Set("description", app.Description) _ = d.Set("created_at", types.FlattenTime(app.CreatedAt)) @@ -107,8 +115,6 @@ func resourceIamApplicationRead(ctx context.Context, d *schema.ResourceData, m a _ = d.Set("organization_id", app.OrganizationID) _ = d.Set("editable", app.Editable) _ = d.Set("tags", types.FlattenSliceString(app.Tags)) - - return nil } func resourceIamApplicationUpdate(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { diff --git a/internal/services/iam/application_test.go b/internal/services/iam/application_test.go index a62f111598..e12a6d1204 100644 --- a/internal/services/iam/application_test.go +++ b/internal/services/iam/application_test.go @@ -55,6 +55,11 @@ func TestAccApplication_Basic(t *testing.T) { resource.TestCheckResourceAttr("scaleway_iam_application.main", "tags.#", "0"), ), }, + { + ResourceName: "scaleway_iam_application.main", + ImportState: true, + ImportStateVerify: true, + }, }, }) } diff --git a/internal/services/iam/group.go b/internal/services/iam/group.go index 39db1152a8..d6e8c8a81d 100644 --- a/internal/services/iam/group.go +++ b/internal/services/iam/group.go @@ -8,6 +8,7 @@ import ( iam "github.com/scaleway/scaleway-sdk-go/api/iam/v1alpha1" "github.com/scaleway/scaleway-sdk-go/scw" "github.com/scaleway/terraform-provider-scaleway/v2/internal/httperrors" + "github.com/scaleway/terraform-provider-scaleway/v2/internal/identity" "github.com/scaleway/terraform-provider-scaleway/v2/internal/services/account" "github.com/scaleway/terraform-provider-scaleway/v2/internal/types" "github.com/scaleway/terraform-provider-scaleway/v2/internal/verify" @@ -24,6 +25,7 @@ func ResourceGroup() *schema.Resource { }, SchemaVersion: 0, SchemaFunc: groupSchema, + Identity: identity.FlatIdentity("id", "Group UUID"), } } @@ -135,6 +137,12 @@ func resourceIamGroupRead(ctx context.Context, d *schema.ResourceData, m any) di return diag.FromErr(err) } + setGroupState(d, group) + + return nil +} + +func setGroupState(d *schema.ResourceData, group *iam.Group) { _ = d.Set("name", group.Name) _ = d.Set("description", group.Description) _ = d.Set("created_at", types.FlattenTime(group.CreatedAt)) @@ -146,8 +154,6 @@ func resourceIamGroupRead(ctx context.Context, d *schema.ResourceData, m any) di _ = d.Set("user_ids", group.UserIDs) _ = d.Set("application_ids", group.ApplicationIDs) } - - return nil } func resourceIamGroupUpdate(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { diff --git a/internal/services/iam/group_test.go b/internal/services/iam/group_test.go index 91d7c2f67c..b76d6bbee4 100644 --- a/internal/services/iam/group_test.go +++ b/internal/services/iam/group_test.go @@ -99,6 +99,11 @@ func TestAccGroup_Basic(t *testing.T) { resource.TestCheckResourceAttr("scaleway_iam_group.main_basic", "tags.#", "0"), ), }, + { + ResourceName: "scaleway_iam_group.main_basic", + ImportState: true, + ImportStateVerify: true, + }, }, }) } @@ -198,6 +203,11 @@ func TestAccGroup_Applications(t *testing.T) { resource.TestCheckNoResourceAttr("scaleway_iam_group.main_app", "application_ids.0"), ), }, + { + ResourceName: "scaleway_iam_group.main_app", + ImportState: true, + ImportStateVerify: true, + }, }, }) } @@ -290,6 +300,11 @@ func TestAccGroup_Users(t *testing.T) { resource.TestCheckNoResourceAttr("scaleway_iam_group.main_user", "user_ids.0"), ), }, + { + ResourceName: "scaleway_iam_group.main_user", + ImportState: true, + ImportStateVerify: true, + }, }, }) } @@ -459,6 +474,11 @@ func TestAccGroup_UsersAndApplications(t *testing.T) { resource.TestCheckNoResourceAttr("scaleway_iam_group.main_mix", "user_ids.0"), ), }, + { + ResourceName: "scaleway_iam_group.main_mix", + ImportState: true, + ImportStateVerify: true, + }, }, }) } diff --git a/internal/services/iam/policy.go b/internal/services/iam/policy.go index 39d0abfa30..85dfb56f82 100644 --- a/internal/services/iam/policy.go +++ b/internal/services/iam/policy.go @@ -9,6 +9,7 @@ import ( iam "github.com/scaleway/scaleway-sdk-go/api/iam/v1alpha1" "github.com/scaleway/scaleway-sdk-go/scw" "github.com/scaleway/terraform-provider-scaleway/v2/internal/httperrors" + "github.com/scaleway/terraform-provider-scaleway/v2/internal/identity" "github.com/scaleway/terraform-provider-scaleway/v2/internal/services/account" "github.com/scaleway/terraform-provider-scaleway/v2/internal/types" "github.com/scaleway/terraform-provider-scaleway/v2/internal/verify" @@ -25,6 +26,7 @@ func ResourcePolicy() *schema.Resource { }, SchemaVersion: 0, SchemaFunc: policySchema, + Identity: identity.FlatIdentity("id", "Policy UUID"), } } @@ -158,7 +160,7 @@ func resourceIamPolicyCreate(ctx context.Context, d *schema.ResourceData, m any) func resourceIamPolicyRead(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { api := NewAPI(m) - pol, err := api.GetPolicy(&iam.GetPolicyRequest{ + policy, err := api.GetPolicy(&iam.GetPolicyRequest{ PolicyID: d.Id(), }, scw.WithContext(ctx)) if err != nil { @@ -171,38 +173,42 @@ func resourceIamPolicyRead(ctx context.Context, d *schema.ResourceData, m any) d return diag.FromErr(err) } - _ = d.Set("name", pol.Name) - _ = d.Set("description", pol.Description) - _ = d.Set("created_at", types.FlattenTime(pol.CreatedAt)) - _ = d.Set("updated_at", types.FlattenTime(pol.UpdatedAt)) - _ = d.Set("organization_id", pol.OrganizationID) - _ = d.Set("editable", pol.Editable) - _ = d.Set("tags", types.FlattenSliceString(pol.Tags)) - - if pol.UserID != nil { - _ = d.Set("user_id", types.FlattenStringPtr(pol.UserID)) + rules, err := api.ListRules(&iam.ListRulesRequest{ + PolicyID: policy.ID, + }) + if err != nil { + return diag.FromErr(fmt.Errorf("failed to list policy's rules: %w", err)) } - if pol.GroupID != nil { - _ = d.Set("group_id", types.FlattenStringPtr(pol.GroupID)) - } + setPolicyState(d, policy, rules) - if pol.ApplicationID != nil { - _ = d.Set("application_id", types.FlattenStringPtr(pol.ApplicationID)) + return nil +} + +func setPolicyState(d *schema.ResourceData, policy *iam.Policy, rules *iam.ListRulesResponse) { + _ = d.Set("name", policy.Name) + _ = d.Set("description", policy.Description) + _ = d.Set("created_at", types.FlattenTime(policy.CreatedAt)) + _ = d.Set("updated_at", types.FlattenTime(policy.UpdatedAt)) + _ = d.Set("organization_id", policy.OrganizationID) + _ = d.Set("editable", policy.Editable) + _ = d.Set("tags", types.FlattenSliceString(policy.Tags)) + + if policy.UserID != nil { + _ = d.Set("user_id", types.FlattenStringPtr(policy.UserID)) } - _ = d.Set("no_principal", types.FlattenBoolPtr(pol.NoPrincipal)) + if policy.GroupID != nil { + _ = d.Set("group_id", types.FlattenStringPtr(policy.GroupID)) + } - listRules, err := api.ListRules(&iam.ListRulesRequest{ - PolicyID: pol.ID, - }) - if err != nil { - return diag.FromErr(fmt.Errorf("failed to list policy's rules: %w", err)) + if policy.ApplicationID != nil { + _ = d.Set("application_id", types.FlattenStringPtr(policy.ApplicationID)) } - _ = d.Set("rule", flattenPolicyRules(listRules.Rules)) + _ = d.Set("no_principal", types.FlattenBoolPtr(policy.NoPrincipal)) - return nil + _ = d.Set("rule", flattenPolicyRules(rules.Rules)) } func resourceIamPolicyUpdate(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { diff --git a/internal/services/iam/policy_test.go b/internal/services/iam/policy_test.go index 42541121e7..af2f9e7639 100644 --- a/internal/services/iam/policy_test.go +++ b/internal/services/iam/policy_test.go @@ -83,6 +83,11 @@ func TestAccPolicy_Basic(t *testing.T) { resource.TestCheckResourceAttr("scaleway_iam_policy.main", "tags.#", "0"), ), }, + { + ResourceName: "scaleway_iam_policy.main", + ImportState: true, + ImportStateVerify: true, + }, }, }) } diff --git a/internal/services/iam/ssh_key.go b/internal/services/iam/ssh_key.go index 3c64d6c838..5bd47504c0 100644 --- a/internal/services/iam/ssh_key.go +++ b/internal/services/iam/ssh_key.go @@ -10,6 +10,7 @@ import ( iam "github.com/scaleway/scaleway-sdk-go/api/iam/v1alpha1" "github.com/scaleway/scaleway-sdk-go/scw" "github.com/scaleway/terraform-provider-scaleway/v2/internal/httperrors" + "github.com/scaleway/terraform-provider-scaleway/v2/internal/identity" "github.com/scaleway/terraform-provider-scaleway/v2/internal/services/account" "github.com/scaleway/terraform-provider-scaleway/v2/internal/types" "golang.org/x/crypto/ssh" @@ -26,6 +27,7 @@ func ResourceSSKKey() *schema.Resource { }, SchemaVersion: 0, SchemaFunc: sshKeySchema, + Identity: identity.FlatIdentity("id", "SSH key UUID"), } } @@ -110,7 +112,10 @@ func resourceIamSSKKeyCreate(ctx context.Context, d *schema.ResourceData, m any) } } - d.SetId(res.ID) + err = identity.SetFlatIdentity(d, "id", res.ID) + if err != nil { + return diag.FromErr(err) + } return resourceIamSSHKeyRead(ctx, d, m) } diff --git a/internal/services/iam/ssh_key_test.go b/internal/services/iam/ssh_key_test.go index 1f6bda7674..2c1128c97a 100644 --- a/internal/services/iam/ssh_key_test.go +++ b/internal/services/iam/ssh_key_test.go @@ -50,6 +50,11 @@ func TestAccSSHKey_basic(t *testing.T) { resource.TestCheckResourceAttr("scaleway_iam_ssh_key.main", "public_key", SSHKeyWithoutComment), ), }, + { + ResourceName: "scaleway_iam_ssh_key.main", + ImportState: true, + ImportStateVerify: true, + }, }, }) } @@ -77,6 +82,11 @@ func TestAccSSHKey_WithNewLine(t *testing.T) { resource.TestCheckResourceAttr("scaleway_iam_ssh_key.main", "public_key", SSHKeyWithoutComment), ), }, + { + ResourceName: "scaleway_iam_ssh_key.main", + ImportState: true, + ImportStateVerify: true, + }, }, }) } @@ -117,6 +127,11 @@ func TestAccSSHKey_ChangeResourceName(t *testing.T) { resource.TestCheckResourceAttr("scaleway_iam_ssh_key.second", "public_key", SSHKeyWithoutComment), ), }, + { + ResourceName: "scaleway_iam_ssh_key.second", + ImportState: true, + ImportStateVerify: true, + }, }, }) } @@ -175,6 +190,11 @@ func TestAccSSHKey_Disabled(t *testing.T) { resource.TestCheckResourceAttr("scaleway_iam_ssh_key.main", "disabled", "false"), ), }, + { + ResourceName: "scaleway_iam_ssh_key.main", + ImportState: true, + ImportStateVerify: true, + }, }, }) } diff --git a/internal/services/iam/user.go b/internal/services/iam/user.go index 6313a7a3f0..a762878dbd 100644 --- a/internal/services/iam/user.go +++ b/internal/services/iam/user.go @@ -9,6 +9,7 @@ import ( iam "github.com/scaleway/scaleway-sdk-go/api/iam/v1alpha1" "github.com/scaleway/scaleway-sdk-go/scw" "github.com/scaleway/terraform-provider-scaleway/v2/internal/httperrors" + "github.com/scaleway/terraform-provider-scaleway/v2/internal/identity" "github.com/scaleway/terraform-provider-scaleway/v2/internal/services/account" "github.com/scaleway/terraform-provider-scaleway/v2/internal/types" ) @@ -28,6 +29,7 @@ func ResourceUser() *schema.Resource { }, SchemaVersion: 0, SchemaFunc: userSchema, + Identity: identity.FlatIdentity("id", "User UUID"), } } @@ -184,7 +186,10 @@ func resourceIamUserCreate(ctx context.Context, d *schema.ResourceData, m any) d return diag.FromErr(err) } - d.SetId(user.ID) + err = identity.SetFlatIdentity(d, "id", user.ID) + if err != nil { + return diag.FromErr(err) + } return resourceIamUserRead(ctx, d, m) } @@ -205,6 +210,17 @@ func resourceIamUserRead(ctx context.Context, d *schema.ResourceData, m any) dia return diag.FromErr(err) } + err = identity.SetFlatIdentity(d, "id", user.ID) + if err != nil { + return diag.FromErr(err) + } + + setUserState(d, user) + + return nil +} + +func setUserState(d *schema.ResourceData, user *iam.User) { _ = d.Set("organization_id", user.OrganizationID) // User input data _ = d.Set("email", user.Email) @@ -224,8 +240,6 @@ func resourceIamUserRead(ctx context.Context, d *schema.ResourceData, m any) dia _ = d.Set("mfa", user.Mfa) _ = d.Set("account_root_user_id", user.AccountRootUserID) _ = d.Set("locked", user.Locked) - - return nil } func resourceIamUserUpdate(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { diff --git a/internal/services/iam/user_test.go b/internal/services/iam/user_test.go index e94d76e470..f20dd0c466 100644 --- a/internal/services/iam/user_test.go +++ b/internal/services/iam/user_test.go @@ -70,6 +70,11 @@ func TestAccUser_Member(t *testing.T) { resource.TestCheckResourceAttr("scaleway_iam_user.member_user", "type", "member"), ), }, + { + ResourceName: "scaleway_iam_user.member_user", + ImportState: true, + ImportStateVerify: true, + }, }, }) } diff --git a/provider/sdkv2_test.go b/provider/sdkv2_test.go index 41ebec3cb1..f8a717d34f 100644 --- a/provider/sdkv2_test.go +++ b/provider/sdkv2_test.go @@ -185,13 +185,6 @@ func TestSDKProvider_ResourceIdentityNotEmpty(t *testing.T) { "scaleway_function_namespace", "scaleway_function_token", "scaleway_function_trigger", - "scaleway_iam_api_key", - "scaleway_iam_application", - "scaleway_iam_group", - "scaleway_iam_group_membership", - "scaleway_iam_policy", - "scaleway_iam_ssh_key", - "scaleway_iam_user", "scaleway_inference_deployment", "scaleway_inference_model", "scaleway_instance_image",