From 46e108ffdb517290708802b29d3d366926207454 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20L=C3=A9one?= Date: Fri, 10 Oct 2025 13:56:31 +0200 Subject: [PATCH 1/5] Fix # Conflicts: # internal/services/secret/secret_data_source_test.go # internal/services/secret/secret_test.go --- go.mod | 5 +- go.sum | 8 + internal/locality/regional/schemas.go | 8 + internal/planModifiers/duration.go | 23 + internal/services/account/schemas.go | 23 + internal/services/secret/secret.go | 606 ++++--- .../services/secret/secret_data_source.go | 317 +++- .../data-source-secret-basic.cassette.yaml | 1536 +---------------- .../testdata/secret-basic.cassette.yaml | 1182 +------------ internal/verify/date.go | 22 + internal/verify/uuid.go | 41 + internal/verify/validation.go | 19 + provider/framework.go | 9 +- provider/sdkv2.go | 2 - 14 files changed, 820 insertions(+), 2981 deletions(-) create mode 100644 internal/planModifiers/duration.go diff --git a/go.mod b/go.mod index c4403efa5f..b8d214aa23 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,7 @@ require ( github.com/hashicorp/go-cty v1.5.0 github.com/hashicorp/go-multierror v1.1.1 github.com/hashicorp/go-retryablehttp v0.7.8 - github.com/hashicorp/terraform-plugin-framework v1.16.0 + github.com/hashicorp/terraform-plugin-framework v1.16.1 github.com/hashicorp/terraform-plugin-go v0.29.0 github.com/hashicorp/terraform-plugin-log v0.9.0 github.com/hashicorp/terraform-plugin-mux v0.21.0 @@ -102,6 +102,9 @@ require ( github.com/hashicorp/terraform-exec v0.23.1 // indirect github.com/hashicorp/terraform-json v0.27.1 // indirect github.com/hashicorp/terraform-plugin-docs v0.23.0 // indirect + github.com/hashicorp/terraform-plugin-framework-timeouts v0.6.0 // indirect + github.com/hashicorp/terraform-plugin-framework-timetypes v0.5.0 // indirect + github.com/hashicorp/terraform-plugin-framework-validators v0.18.0 // indirect github.com/hashicorp/terraform-registry-address v0.4.0 // indirect github.com/hashicorp/terraform-svchost v0.1.1 // indirect github.com/hashicorp/yamux v0.1.2 // indirect diff --git a/go.sum b/go.sum index 5bc6e92965..d590e065b4 100644 --- a/go.sum +++ b/go.sum @@ -326,6 +326,14 @@ github.com/hashicorp/terraform-plugin-docs v0.23.0 h1:sipnfD4/9EJBg9zekym+s1H6qm github.com/hashicorp/terraform-plugin-docs v0.23.0/go.mod h1:J4b5AtMRgJlDrwCQz+G4hKABgHY5m56PnsRmdAzBwW8= github.com/hashicorp/terraform-plugin-framework v1.16.0 h1:tP0f+yJg0Z672e7levixDe5EpWwrTrNryPM9kDMYIpE= github.com/hashicorp/terraform-plugin-framework v1.16.0/go.mod h1:0xFOxLy5lRzDTayc4dzK/FakIgBhNf/lC4499R9cV4Y= +github.com/hashicorp/terraform-plugin-framework v1.16.1 h1:1+zwFm3MEqd/0K3YBB2v9u9DtyYHyEuhVOfeIXbteWA= +github.com/hashicorp/terraform-plugin-framework v1.16.1/go.mod h1:0xFOxLy5lRzDTayc4dzK/FakIgBhNf/lC4499R9cV4Y= +github.com/hashicorp/terraform-plugin-framework-timeouts v0.6.0 h1:Vv16e7EW4nT9668IV0RhdpEmnLl0im7BZx6J+QMlUkg= +github.com/hashicorp/terraform-plugin-framework-timeouts v0.6.0/go.mod h1:rpHo9hZLn4vEkvNL5xsSdLRdaDZKSinuc0xL+BdOpVA= +github.com/hashicorp/terraform-plugin-framework-timetypes v0.5.0 h1:v3DapR8gsp3EM8fKMh6up9cJUFQ2iRaFsYLP8UJnCco= +github.com/hashicorp/terraform-plugin-framework-timetypes v0.5.0/go.mod h1:c3PnGE9pHBDfdEVG9t1S1C9ia5LW+gkFR0CygXlM8ak= +github.com/hashicorp/terraform-plugin-framework-validators v0.18.0 h1:OQnlOt98ua//rCw+QhBbSqfW3QbwtVrcdWeQN5gI3Hw= +github.com/hashicorp/terraform-plugin-framework-validators v0.18.0/go.mod h1:lZvZvagw5hsJwuY7mAY6KUz45/U6fiDR0CzQAwWD0CA= github.com/hashicorp/terraform-plugin-go v0.29.0 h1:1nXKl/nSpaYIUBU1IG/EsDOX0vv+9JxAltQyDMpq5mU= github.com/hashicorp/terraform-plugin-go v0.29.0/go.mod h1:vYZbIyvxyy0FWSmDHChCqKvI40cFTDGSb3D8D70i9GM= github.com/hashicorp/terraform-plugin-log v0.9.0 h1:i7hOA+vdAItN1/7UrfBqBwvYPQ9TFvymaRGZED3FCV0= diff --git a/internal/locality/regional/schemas.go b/internal/locality/regional/schemas.go index 73294ea6cf..048b9ca579 100644 --- a/internal/locality/regional/schemas.go +++ b/internal/locality/regional/schemas.go @@ -1,6 +1,7 @@ package regional import ( + resourceSchema "github.com/hashicorp/terraform-plugin-framework/resource/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/scaleway/scaleway-sdk-go/scw" "github.com/scaleway/terraform-provider-scaleway/v2/internal/locality" @@ -36,3 +37,10 @@ func Schema() *schema.Schema { DiffSuppressFunc: locality.SuppressSDKNullAssignment, } } + +func ResourceSchema(description string) resourceSchema.Attribute { + return resourceSchema.StringAttribute{ + Description: description, + Optional: true, + } +} diff --git a/internal/planModifiers/duration.go b/internal/planModifiers/duration.go new file mode 100644 index 0000000000..8860ace3ba --- /dev/null +++ b/internal/planModifiers/duration.go @@ -0,0 +1,23 @@ +package planModifiers + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" +) + +type Duration struct{} + +func (d Duration) Description(ctx context.Context) string { + return "Verify that two duration are equals" +} + +func (d Duration) MarkdownDescription(ctx context.Context) string { + return d.Description(ctx) +} + +func (d Duration) PlanModifyString(ctx context.Context, request planmodifier.StringRequest, response *planmodifier.StringResponse) { + if request.StateValue == request.PlanValue { + response.PlanValue = request.PlanValue + } +} diff --git a/internal/services/account/schemas.go b/internal/services/account/schemas.go index 98f4d3a7dc..c3544208d9 100644 --- a/internal/services/account/schemas.go +++ b/internal/services/account/schemas.go @@ -1,6 +1,9 @@ package account import ( + dataSourceSchema "github.com/hashicorp/terraform-plugin-framework/resource/schema" + resourceSchema "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/schema/validator" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/scaleway/terraform-provider-scaleway/v2/internal/verify" ) @@ -34,3 +37,23 @@ func ProjectIDSchema() *schema.Schema { ValidateDiagFunc: verify.IsUUID(), } } + +func ResourceProjectIDSchema(description string) resourceSchema.StringAttribute { + return resourceSchema.StringAttribute{ + Description: description, + Optional: true, + Validators: []validator.String{ + verify.UUIDValidator{}, + }, + } +} + +func DatasourceOrganizationIDSchema(description string) dataSourceSchema.StringAttribute { + return dataSourceSchema.StringAttribute{ + Description: description, + Optional: true, + Validators: []validator.String{ + verify.UUIDValidator{}, + }, + } +} diff --git a/internal/services/secret/secret.go b/internal/services/secret/secret.go index 791c26d69b..493921371a 100644 --- a/internal/services/secret/secret.go +++ b/internal/services/secret/secret.go @@ -4,84 +4,169 @@ import ( "context" "fmt" "path/filepath" - "strconv" - "github.com/hashicorp/terraform-plugin-sdk/v2/diag" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-framework-timeouts/resource/timeouts" + "github.com/hashicorp/terraform-plugin-framework-timetypes/timetypes" + "github.com/hashicorp/terraform-plugin-framework/path" + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/resource/identityschema" + "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringdefault" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" + "github.com/hashicorp/terraform-plugin-framework/schema/validator" + "github.com/hashicorp/terraform-plugin-framework/types" secret "github.com/scaleway/scaleway-sdk-go/api/secret/v1beta1" "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/locality/regional" + "github.com/scaleway/terraform-provider-scaleway/v2/internal/planModifiers" "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" ) -func ResourceSecret() *schema.Resource { - return &schema.Resource{ - CreateContext: ResourceSecretCreate, - ReadContext: ResourceSecretRead, - UpdateContext: ResourceSecretUpdate, - DeleteContext: ResourceSecretDelete, - Importer: &schema.ResourceImporter{ - StateContext: schema.ImportStatePassthroughContext, - }, - Timeouts: &schema.ResourceTimeout{ - Default: schema.DefaultTimeout(defaultSecretTimeout), +var ( + _ resource.Resource = ResourceSecret{} + _ resource.ResourceWithConfigure = ResourceSecret{} + _ resource.ResourceWithIdentity = ResourceSecret{} + _ resource.ResourceWithImportState = ResourceSecret{} +) + +type ResourceSecret struct { + secretAPI *secret.API + region scw.Region + projectID string + id string +} + +func NewResourceSecret() resource.Resource { + return &ResourceSecret{} +} + +func (r ResourceSecret) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { + resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp) +} + +func (r ResourceSecret) Configure(ctx context.Context, request resource.ConfigureRequest, response *resource.ConfigureResponse) { + if request.ProviderData == nil { + return + } + + client, ok := request.ProviderData.(*scw.Client) + if !ok { + response.Diagnostics.AddError( + "Unexpected Action Configure Type", + fmt.Sprintf("Expected *scw.Client, got: %T. Please report this issue to the provider developers.", request.ProviderData), + ) + + return + } + + r.secretAPI = secret.NewAPI(client) +} + +type ResourceSecretIdentityModel struct { + ID types.String `tfsdk:"id"` + Region types.String `tfsdk:"region"` +} + +func (r ResourceSecret) IdentitySchema(ctx context.Context, request resource.IdentitySchemaRequest, response *resource.IdentitySchemaResponse) { + response.IdentitySchema = identityschema.Schema{ + Attributes: map[string]identityschema.Attribute{ + "id": identityschema.StringAttribute{ + RequiredForImport: true, + }, + "region": identityschema.StringAttribute{ + OptionalForImport: true, + }, }, - SchemaVersion: 0, - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, + } +} + +func (r ResourceSecret) Metadata(ctx context.Context, request resource.MetadataRequest, response *resource.MetadataResponse) { + response.TypeName = request.ProviderTypeName + "_secret" +} + +// useStateForUnknownModifier implements the plan modifier. +type cleanUpFilePath struct{} + +// Description returns a human-readable description of the plan modifier. +func (m cleanUpFilePath) Description(_ context.Context) string { + return "Remove diff " +} + +// MarkdownDescription returns a markdown description of the plan modifier. +func (m cleanUpFilePath) MarkdownDescription(ctx context.Context) string { + return m.Description(ctx) +} + +func (m cleanUpFilePath) PlanModifyString(_ context.Context, req planmodifier.StringRequest, resp *planmodifier.StringResponse) { + // Do nothing if there is no state (resource is being created). + if req.State.Raw.IsNull() { + return + } + + // Do nothing if there is a known planned value. + if !req.PlanValue.IsUnknown() { + return + } + + // Do nothing if there is an unknown configuration value, otherwise interpolation gets messed up. + if req.ConfigValue.IsUnknown() { + return + } + + resp.PlanValue = types.StringValue(filepath.Clean(req.StateValue.String())) +} + +func (r ResourceSecret) Schema(ctx context.Context, request resource.SchemaRequest, response *resource.SchemaResponse) { + response.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + "name": schema.StringAttribute{ Required: true, Description: "The secret name", }, - "description": { - Type: schema.TypeString, + "description": schema.StringAttribute{ Optional: true, Description: "Description of the secret", }, - "tags": { - Type: schema.TypeList, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - Optional: true, - Description: "List of tags [\"tag1\", \"tag2\", ...] associated to secret", - }, - "status": { - Type: schema.TypeString, + "status": schema.StringAttribute{ Computed: true, Description: "Status of the secret", }, - "version_count": { - Type: schema.TypeInt, + "version_count": schema.Int32Attribute{ Computed: true, Description: "The number of versions for this Secret", }, - "created_at": { - Type: schema.TypeString, + "updated_at": schema.StringAttribute{ Computed: true, Description: "Date and time of secret's creation (RFC 3339 format)", }, - "updated_at": { - Type: schema.TypeString, + "created_at": schema.StringAttribute{ Computed: true, Description: "Date and time of secret's creation (RFC 3339 format)", }, - "path": { - Type: schema.TypeString, + "path": schema.StringAttribute{ Optional: true, Description: "Location of the secret in the directory structure.", - Default: "/", - DiffSuppressFunc: func(_, oldValue, newValue string, _ *schema.ResourceData) bool { - return filepath.Clean(oldValue) == filepath.Clean(newValue) + Default: stringdefault.StaticString("/"), + PlanModifiers: []planmodifier.String{ + cleanUpFilePath{}, }, }, - "type": { - ForceNew: true, - Type: schema.TypeString, + "protected": schema.BoolAttribute{ + Optional: true, + Description: "True if secret protection is enabled on a given secret. A protected secret cannot be deleted.", + }, + "tags": schema.ListAttribute{ + ElementType: types.StringType, + Description: "List of tags [\"tag1\", \"tag2\", ...] associated to secret", + Optional: true, + }, + "type": schema.StringAttribute{ + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + }, Description: func() string { var t secret.SecretType @@ -89,280 +174,349 @@ func ResourceSecret() *schema.Resource { return fmt.Sprintf("Type of the secret could be any value among: %s", secretTypes) }(), - Optional: true, - Default: secret.SecretTypeOpaque, - ValidateDiagFunc: verify.ValidateEnum[secret.SecretType](), - }, - "protected": { - Type: schema.TypeBool, - Optional: true, - Description: "True if secret protection is enabled on a given secret. A protected secret cannot be deleted.", + Optional: true, + Default: stringdefault.StaticString(secret.SecretTypeOpaque.String()), + Validators: []validator.String{ + verify.ValidatorFromEnum[secret.SecretType](secret.SecretType("")), + }, }, - "ephemeral_policy": { - Type: schema.TypeList, + "region": regional.ResourceSchema("The region you want to attach the resource to"), + "project_id": account.ResourceProjectIDSchema("The project ID you want to attach the secret to"), + "ephemeral_policy": schema.ListNestedAttribute{ Description: "Ephemeral policy of the secret. Policy that defines whether/when a secret's versions expire. By default, the policy is applied to all the secret's versions.", Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "ttl": { - Optional: true, - Type: schema.TypeString, - DiffSuppressFunc: dsf.Duration, - ValidateDiagFunc: verify.IsDuration(), - Description: "Time frame, from one second and up to one year, during which the secret's versions are valid. Has to be specified in Go Duration format", + NestedObject: schema.NestedAttributeObject{ + Attributes: map[string]schema.Attribute{ + "ttl": schema.StringAttribute{ + Optional: true, + Description: "Time frame, from one second and up to one year, during which the secret's versions are valid. Has to be specified in Go Duration format", + Validators: []validator.String{ + verify.DurationValidator{}, + }, + PlanModifiers: []planmodifier.String{ + planModifiers.Duration{}, + }, }, - "expires_once_accessed": { - Type: schema.TypeBool, + "expires_once_accessed": schema.BoolAttribute{ Optional: true, Description: "True if the secret version expires after a single user access.", }, - "action": { - Type: schema.TypeString, - Required: true, - ValidateDiagFunc: verify.ValidateEnum[secret.EphemeralPolicyAction](), - Description: "Action to perform when the version of a secret expires.", + "action": schema.StringAttribute{ + Required: true, + Validators: []validator.String{ + verify.ValidatorFromEnum[secret.EphemeralPolicyAction](secret.EphemeralPolicyAction("")), + }, + Description: "Action to perform when the version of a secret expires.", }, }, }, }, - "versions": { - Type: schema.TypeList, + "versions": schema.ListNestedAttribute{ Description: "List of the versions of the secret", Computed: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "revision": { - Type: schema.TypeString, + NestedObject: schema.NestedAttributeObject{ + Attributes: map[string]schema.Attribute{ + "revision": schema.StringAttribute{ Computed: true, Description: "The revision of secret version", }, - "secret_id": { - Type: schema.TypeString, + "secret_id": schema.StringAttribute{ Computed: true, Description: "The secret ID associated with this version", }, - "status": { - Type: schema.TypeString, + "status": schema.StringAttribute{ Computed: true, Description: "Status of the secret version", }, - "created_at": { - Type: schema.TypeString, + "created_at": schema.StringAttribute{ Computed: true, Description: "Date and time of secret version's creation (RFC 3339 format)", }, - "updated_at": { - Type: schema.TypeString, + "updated_at": schema.StringAttribute{ Computed: true, Description: "Date and time of secret version's creation (RFC 3339 format)", }, - "description": { - Type: schema.TypeString, + "description": schema.StringAttribute{ Optional: true, Description: "Description of the secret version", }, - "latest": { - Type: schema.TypeBool, + "latest": schema.BoolAttribute{ Optional: true, Description: "Returns true if the version is the latest.", }, }, }, }, - "region": regional.Schema(), - "project_id": account.ProjectIDSchema(), + }, + Blocks: map[string]schema.Block{ + "timeouts": timeouts.Block(ctx, + timeouts.Opts{ + Create: true, + }, + ), }, } } -func ResourceSecretCreate(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { - api, region, err := newAPIWithRegion(d, m) - if err != nil { - return diag.FromErr(err) - } +type ResourceSecretModel struct { + ID types.String `tfsdk:"id"` + Name types.String `tfsdk:"name"` + Protected types.Bool `tfsdk:"protected"` + Type types.String `tfsdk:"type"` + Tags types.List `tfsdk:"tags"` + Description types.String `tfsdk:"description"` + Path types.String `tfsdk:"path"` + EphemeralPolicy types.String `tfsdk:"ephemeral_policy"` + Region types.String `tfsdk:"region"` + ProjectID types.String `tfsdk:"project_id"` + VersionCount types.Int32 `tfsdk:"version_count"` + Status types.String `tfsdk:"status"` + CreatedAt timetypes.RFC3339 `tfsdk:"created_at"` + UpdatedAt timetypes.RFC3339 `tfsdk:"updated_at"` + Versions types.ListType `tfsdk:"versions"` +} - secretCreateRequest := &secret.CreateSecretRequest{ - Region: region, - ProjectID: d.Get("project_id").(string), - Name: d.Get("name").(string), - Protected: d.Get("protected").(bool), - Type: secret.SecretType(d.Get("type").(string)), - } +func (r ResourceSecret) Create(ctx context.Context, request resource.CreateRequest, response *resource.CreateResponse) { + var data ResourceSecretModel - rawTag, tagExist := d.GetOk("tags") - if tagExist { - secretCreateRequest.Tags = types.ExpandStrings(rawTag) - } + response.Diagnostics.Append(request.Plan.Get(ctx, &data)...) - rawDescription, descriptionExist := d.GetOk("description") - if descriptionExist { - secretCreateRequest.Description = types.ExpandStringPtr(rawDescription) + secretCreateRequest := &secret.CreateSecretRequest{ + Region: r.region, + ProjectID: r.projectID, + Name: data.Name.String(), + Protected: data.Protected.ValueBool(), + Type: secret.SecretType(data.Type.String()), } - rawPath, pathExist := d.GetOk("path") - if pathExist { - secretCreateRequest.Path = types.ExpandStringPtr(rawPath) + //if !data.Tags.IsNull() { + // secretCreateRequest.Tags = data.Tags.Elements() + //} + + if !data.Description.IsNull() { + secretCreateRequest.Description = data.Description.ValueStringPointer() } - rawEphemeralPolicy, policyExists := d.GetOk("ephemeral_policy") - if policyExists { - secretCreateRequest.EphemeralPolicy, err = expandEphemeralPolicy(rawEphemeralPolicy) - if err != nil { - return diag.FromErr(err) - } + if !data.Path.IsNull() { + secretCreateRequest.Path = data.Path.ValueStringPointer() } - secretResponse, err := api.CreateSecret(secretCreateRequest, scw.WithContext(ctx)) + //if !data.EphemeralPolicy.IsNull() { + // secretCreateRequest.EphemeralPolicy = data.EphemeralPolicy.String() + //} + //rawEphemeralPolicy, policyExists := d.GetOk("ephemeral_policy") + //if policyExists { + // secretCreateRequest.EphemeralPolicy, err = expandEphemeralPolicy(rawEphemeralPolicy) + // if err != nil { + // return diag.FromErr(err) + // } + //} + + apiResponse, err := r.secretAPI.CreateSecret(secretCreateRequest, scw.WithContext(ctx)) if err != nil { - return diag.FromErr(err) + response.Diagnostics.AddError( + "error while creating secret", + err.Error(), + ) } + if apiResponse == nil { + response.Diagnostics.AddError( + "nil answer while creating secret", + "nil answer while creating secret", + ) - d.SetId(regional.NewIDString(region, secretResponse.ID)) - - return ResourceSecretRead(ctx, d, m) -} - -func ResourceSecretRead(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { - api, region, id, err := NewAPIWithRegionAndID(m, d.Id()) - if err != nil { - return diag.FromErr(err) + return } - secretResponse, err := api.GetSecret(&secret.GetSecretRequest{ - Region: region, - SecretID: id, - }, scw.WithContext(ctx)) - if err != nil { - if httperrors.Is404(err) { - d.SetId("") + // Set data returned by API in identity + identity := ResourceSecretIdentityModel{ + ID: types.StringValue(apiResponse.ID), + Region: types.StringValue(apiResponse.Region.String()), + } + response.Diagnostics.Append(response.Identity.Set(ctx, identity)...) - return nil - } + // Save data into Terraform state + data.ID = types.StringValue(regional.NewIDString(apiResponse.Region, apiResponse.ID)) + response.Diagnostics.Append(response.State.Set(ctx, &data)...) +} - return diag.FromErr(err) - } +func (r ResourceSecret) Read(ctx context.Context, request resource.ReadRequest, response *resource.ReadResponse) { + var data ResourceSecretModel - if len(secretResponse.Tags) > 0 { - _ = d.Set("tags", types.FlattenSliceString(secretResponse.Tags)) - } + // Read Terraform prior state data into the model + response.Diagnostics.Append(request.State.Get(ctx, &data)...) - versions, err := api.ListSecretVersions(&secret.ListSecretVersionsRequest{ - Region: region, - SecretID: id, - }, scw.WithAllPages(), scw.WithContext(ctx)) + secretResponse, err := r.secretAPI.GetSecret(&secret.GetSecretRequest{ + Region: scw.Region(data.Region.String()), + SecretID: data.ID.String(), + }, scw.WithContext(ctx)) if err != nil { if httperrors.Is404(err) { - d.SetId("") - - return nil + response.State.RemoveResource(ctx) + return } - return diag.FromErr(err) - } + response.Diagnostics.AddError( + "cannot get secret", + err.Error()) - _ = d.Set("name", secretResponse.Name) - _ = d.Set("description", types.FlattenStringPtr(secretResponse.Description)) - _ = d.Set("created_at", types.FlattenTime(secretResponse.CreatedAt)) - _ = d.Set("updated_at", types.FlattenTime(secretResponse.UpdatedAt)) - _ = d.Set("status", secretResponse.Status.String()) - _ = d.Set("version_count", int(versions.TotalCount)) - _ = d.Set("region", string(region)) - _ = d.Set("project_id", secretResponse.ProjectID) - _ = d.Set("path", secretResponse.Path) - _ = d.Set("protected", secretResponse.Protected) - _ = d.Set("ephemeral_policy", flattenEphemeralPolicy(secretResponse.EphemeralPolicy)) - _ = d.Set("type", secretResponse.Type) - - versionsList := make([]map[string]any, 0, len(versions.Versions)) - for _, version := range versions.Versions { - versionsList = append(versionsList, map[string]any{ - "revision": strconv.Itoa(int(version.Revision)), - "secret_id": version.SecretID, - "status": version.Status.String(), - "created_at": types.FlattenTime(version.CreatedAt), - "updated_at": types.FlattenTime(version.UpdatedAt), - "description": types.FlattenStringPtr(version.Description), - "latest": types.FlattenBoolPtr(&version.Latest), - }) + return } - _ = d.Set("versions", versionsList) - - return nil + //if len(secretResponse.Tags) > 0 { + // _ = d.Set("tags", types.FlattenSliceString(secretResponse.Tags)) + //} + + //versions, err := r.secretAPI.ListSecretVersions(&secret.ListSecretVersionsRequest{ + // Region: r.region, + // SecretID: r.id, + //}, scw.WithAllPages(), scw.WithContext(ctx)) + //if err != nil { + // if httperrors.Is404(err) { + // d.SetId("") + // + // return nil + // } + // + // return diag.FromErr(err) + //} + + data.Name = types.StringValue(secretResponse.Name) + data.Description = types.StringPointerValue(secretResponse.Description) + data.Region = types.StringValue(secretResponse.Region.String()) + data.Path = types.StringValue(secretResponse.Path) + // data.VersionCount = types.Int32Value(int32(versions.TotalCount)) + data.ProjectID = types.StringValue(secretResponse.ProjectID) + data.Type = types.StringValue(secretResponse.Type.String()) + data.Status = types.StringValue(secretResponse.Status.String()) + data.CreatedAt = timetypes.NewRFC3339TimeValue(*secretResponse.CreatedAt) + data.UpdatedAt = timetypes.NewRFC3339TimeValue(*secretResponse.UpdatedAt) + data.Protected = types.BoolValue(secretResponse.Protected) + //_ = d.Set("ephemeral_policy", flattenEphemeralPolicy(secretResponse.EphemeralPolicy)) + + //versionsList := make([]map[string]any, 0, len(versions.Versions)) + //for _, version := range versions.Versions { + // versionsList = append(versionsList, map[string]any{ + // "revision": strconv.Itoa(int(version.Revision)), + // "secret_id": version.SecretID, + // "status": version.Status.String(), + // "created_at": types.FlattenTime(version.CreatedAt), + // "updated_at": types.FlattenTime(version.UpdatedAt), + // "description": types.FlattenStringPtr(version.Description), + // "latest": types.FlattenBoolPtr(&version.Latest), + // }) + //} + // + //_ = d.Set("versions", versionsList) + + // Save updated data into Terraform state + response.Diagnostics.Append(response.State.Set(ctx, &data)...) } -func ResourceSecretUpdate(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { - api, region, id, err := NewAPIWithRegionAndID(m, d.Id()) - if err != nil { - return diag.FromErr(err) - } +func (r ResourceSecret) Update(ctx context.Context, request resource.UpdateRequest, response *resource.UpdateResponse) { + var plan, state ResourceSecretModel + + response.Diagnostics.Append(request.Plan.Get(ctx, &plan)...) + response.Diagnostics.Append(request.State.Get(ctx, &state)...) updateRequest := &secret.UpdateSecretRequest{ - Region: region, - SecretID: id, + Region: scw.Region(plan.Region.String()), + SecretID: plan.ID.String(), } hasChanged := false - if d.HasChange("description") { - updateRequest.Description = types.ExpandUpdatedStringPtr(d.Get("description")) + if !plan.Description.Equal(state.Description) { + updateRequest.Description = plan.Description.ValueStringPointer() hasChanged = true } - if d.HasChange("name") { - updateRequest.Name = types.ExpandUpdatedStringPtr(d.Get("name")) + if !plan.Name.Equal(state.Name) { + updateRequest.Name = plan.Name.ValueStringPointer() hasChanged = true } - if d.HasChange("tags") { - updateRequest.Tags = types.ExpandUpdatedStringsPtr(d.Get("tags")) - hasChanged = true - } + //if !plan.Tags.Equal(state.Tags) { + // updateRequest.Tags = plan.Tags. + // hasChanged = true + //} + //if d.HasChange("tags") { + // updateRequest.Tags = types.ExpandUpdatedStringsPtr(d.Get("tags")) + //} - if d.HasChange("path") { - updateRequest.Path = types.ExpandUpdatedStringPtr(d.Get("path")) + if !plan.Path.Equal(state.Path) { + updateRequest.Path = plan.Path.ValueStringPointer() hasChanged = true } - if d.HasChange("ephemeral_policy") { - updateRequest.EphemeralPolicy, err = expandEphemeralPolicy(d.Get("ephemeral_policy")) - if err != nil { - return diag.FromErr(err) - } - - hasChanged = true - } + //if d.HasChange("ephemeral_policy") { + // updateRequest.EphemeralPolicy, err = expandEphemeralPolicy(d.Get("ephemeral_policy")) + // if err != nil { + // return diag.FromErr(err) + // } + // hasChanged = true + //} if hasChanged { - _, err := api.UpdateSecret(updateRequest, scw.WithContext(ctx)) - if err != nil { - return diag.FromErr(err) - } - } - - if d.HasChange("protected") { - err = updateSecretProtection(api, region, id, d.Get("protected").(bool)) + _, err := r.secretAPI.UpdateSecret(updateRequest, scw.WithContext(ctx)) if err != nil { - return diag.FromErr(err) + response.Diagnostics.AddError( + "unable to update secret", + err.Error(), + ) } } - return ResourceSecretRead(ctx, d, m) + //if !plan.Protected.Equal(state.Protected) { + // s, err := r.secretAPI.GetSecret(&secret.GetSecretRequest{ + // Region: r.region, + // SecretID: r.ID, + // }) + // if err != nil { + // response.Diagnostics.AddError( + // "error while trying to change protection of a secret", + // err.Error(), + // ) + // return + // } + // + // if s.Protected == protected { + // return nil + // } + // + // if protected { + // _, err = r.secretAPI.ProtectSecret(&secret.ProtectSecretRequest{ + // Region: r.region, + // SecretID: r.ID, + // }) + // if err != nil { + // return fmt.Errorf("failed to protect secret %s: %w", secretID, err) + // } + // } else { + // _, err = r.secretAPI.UnprotectSecret(&secret.UnprotectSecretRequest{ + // Region: r.region, + // SecretID: r.ID, + // }) + // if err != nil { + // return fmt.Errorf("failed to unprotect secret %s: %w", secretID, err) + // } + // } + //} } -func ResourceSecretDelete(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { - api, region, id, err := NewAPIWithRegionAndID(m, d.Id()) - if err != nil { - return diag.FromErr(err) - } +func (r ResourceSecret) Delete(ctx context.Context, request resource.DeleteRequest, response *resource.DeleteResponse) { + var data ResourceSecretModel + + // Read Terraform prior state data into the model + response.Diagnostics.Append(request.State.Get(ctx, &data)...) - err = api.DeleteSecret(&secret.DeleteSecretRequest{ - Region: region, - SecretID: id, + err := r.secretAPI.DeleteSecret(&secret.DeleteSecretRequest{ + Region: scw.Region(data.Region.String()), + SecretID: data.ID.String(), }, scw.WithContext(ctx)) if err != nil && !httperrors.Is404(err) { - return diag.FromErr(err) + response.Diagnostics.AddError( + "Unable to delete secret", + err.Error()) } - - return nil } diff --git a/internal/services/secret/secret_data_source.go b/internal/services/secret/secret_data_source.go index 1fe2663fd8..ebf927bc46 100644 --- a/internal/services/secret/secret_data_source.go +++ b/internal/services/secret/secret_data_source.go @@ -2,97 +2,274 @@ package secret import ( "context" + "fmt" - "github.com/hashicorp/terraform-plugin-sdk/v2/diag" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-framework-timeouts/resource/timeouts" + "github.com/hashicorp/terraform-plugin-framework-validators/datasourcevalidator" + "github.com/hashicorp/terraform-plugin-framework/datasource" + "github.com/hashicorp/terraform-plugin-framework/datasource/schema" + "github.com/hashicorp/terraform-plugin-framework/path" + "github.com/hashicorp/terraform-plugin-framework/schema/validator" + "github.com/hashicorp/terraform-plugin-framework/types" secret "github.com/scaleway/scaleway-sdk-go/api/secret/v1beta1" "github.com/scaleway/scaleway-sdk-go/scw" - "github.com/scaleway/terraform-provider-scaleway/v2/internal/datasource" + "github.com/scaleway/terraform-provider-scaleway/v2/internal/locality/regional" "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" ) -func DataSourceSecret() *schema.Resource { - // Generate datasource schema from resource - dsSchema := datasource.SchemaFromResourceSchema(ResourceSecret().Schema) - - // Set 'Optional' schema elements - datasource.AddOptionalFieldsToSchema(dsSchema, "name", "region", "path") - - dsSchema["name"].ConflictsWith = []string{"secret_id"} - dsSchema["path"].ConflictsWith = []string{"secret_id"} - dsSchema["secret_id"] = &schema.Schema{ - Type: schema.TypeString, - Optional: true, - Description: "The ID of the secret", - ValidateDiagFunc: verify.IsUUIDorUUIDWithLocality(), - ConflictsWith: []string{"name", "path"}, - } - dsSchema["organization_id"] = account.OrganizationIDOptionalSchema() - dsSchema["project_id"] = &schema.Schema{ - Type: schema.TypeString, - Optional: true, - Description: "The project ID the resource is associated to", - ValidateDiagFunc: verify.IsUUID(), - } +var ( + _ datasource.DataSource = &DataSourceSecret{} + _ datasource.DataSourceWithConfigure = &DataSourceSecret{} + _ datasource.DataSourceWithConfigValidators = &DataSourceSecret{} +) + +type DataSourceSecret struct { + secretAPI *secret.API +} + +func NewDataSourceSecret() datasource.DataSource { + return &DataSourceSecret{} +} + +func (d DataSourceSecret) Metadata(ctx context.Context, request datasource.MetadataRequest, response *datasource.MetadataResponse) { + response.TypeName = request.ProviderTypeName + "_secret" +} + +func (d DataSourceSecret) Schema(ctx context.Context, request datasource.SchemaRequest, response *datasource.SchemaResponse) { + response.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + // dsSchema["secret_id"] = &schema.Schema{ + // ValidateDiagFunc: verify.IsUUIDorUUIDWithLocality(), + // } + "secret_id": schema.StringAttribute{ + Optional: true, + Description: "The ID of the secret", + Validators: []validator.String{ + verify.UUIDorUUIDWithLocalityValidator{}, + }, + }, + "name": schema.StringAttribute{ + Required: true, + Description: "The secret name", + }, + "description": schema.StringAttribute{ + Optional: true, + Description: "Description of the secret", + }, + "status": schema.StringAttribute{ + Computed: true, + Description: "Status of the secret", + }, + "version_count": schema.Int32Attribute{ + Computed: true, + Description: "The number of versions for this Secret", + }, + "updated_at": schema.StringAttribute{ + Computed: true, + Description: "Date and time of secret's creation (RFC 3339 format)", + }, + "created_at": schema.StringAttribute{ + Computed: true, + Description: "Date and time of secret's creation (RFC 3339 format)", + }, + "path": schema.StringAttribute{ + Optional: true, + Description: "Location of the secret in the directory structure.", + }, + "protected": schema.BoolAttribute{ + Optional: true, + Description: "True if secret protection is enabled on a given secret. A protected secret cannot be deleted.", + }, + "tags": schema.ListAttribute{ + ElementType: types.StringType, + Description: "List of tags [\"tag1\", \"tag2\", ...] associated to secret", + Optional: true, + }, + "type": schema.StringAttribute{ + Description: func() string { + var t secret.SecretType - return &schema.Resource{ - ReadContext: DataSourceSecretRead, - Schema: dsSchema, + secretTypes := t.Values() + + return fmt.Sprintf("Type of the secret could be any value among: %s", secretTypes) + }(), + Optional: true, + Validators: []validator.String{ + verify.ValidatorFromEnum[secret.SecretType](secret.SecretType("")), + }, + }, + "region": regional.ResourceSchema("The region you want to attach the resource to"), + "project_id": account.ResourceProjectIDSchema("The project ID you want to attach the secret to"), + "organization_id": account.DatasourceOrganizationIDSchema("The organization id the secret is attached to"), + "ephemeral_policy": schema.ListNestedAttribute{ + Description: "Ephemeral policy of the secret. Policy that defines whether/when a secret's versions expire. By default, the policy is applied to all the secret's versions.", + Optional: true, + NestedObject: schema.NestedAttributeObject{ + Attributes: map[string]schema.Attribute{ + "ttl": schema.StringAttribute{ + Optional: true, + Description: "Time frame, from one second and up to one year, during which the secret's versions are valid. Has to be specified in Go Duration format", + Validators: []validator.String{ + verify.DurationValidator{}, + }, + }, + "expires_once_accessed": schema.BoolAttribute{ + Optional: true, + Description: "True if the secret version expires after a single user access.", + }, + "action": schema.StringAttribute{ + Required: true, + Validators: []validator.String{ + verify.ValidatorFromEnum[secret.EphemeralPolicyAction](secret.EphemeralPolicyAction("")), + }, + Description: "Action to perform when the version of a secret expires.", + }, + }, + }, + }, + "versions": schema.ListNestedAttribute{ + Description: "List of the versions of the secret", + Computed: true, + NestedObject: schema.NestedAttributeObject{ + Attributes: map[string]schema.Attribute{ + "revision": schema.StringAttribute{ + Computed: true, + Description: "The revision of secret version", + }, + "secret_id": schema.StringAttribute{ + Computed: true, + Description: "The secret ID associated with this version", + }, + "status": schema.StringAttribute{ + Computed: true, + Description: "Status of the secret version", + }, + "created_at": schema.StringAttribute{ + Computed: true, + Description: "Date and time of secret version's creation (RFC 3339 format)", + }, + "updated_at": schema.StringAttribute{ + Computed: true, + Description: "Date and time of secret version's creation (RFC 3339 format)", + }, + "description": schema.StringAttribute{ + Optional: true, + Description: "Description of the secret version", + }, + "latest": schema.BoolAttribute{ + Optional: true, + Description: "Returns true if the version is the latest.", + }, + }, + }, + }, + }, + Blocks: map[string]schema.Block{ + "timeouts": timeouts.Block(ctx, + timeouts.Opts{ + Create: true, + }, + ), + }, } } -func DataSourceSecretRead(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { - api, region, projectID, err := newAPIWithRegionAndProjectID(d, m) - if err != nil { - return diag.FromErr(err) +func (d DataSourceSecret) Configure(ctx context.Context, request datasource.ConfigureRequest, response *datasource.ConfigureResponse) { + // Always perform a nil check when handling ProviderData because Terraform + // sets that data after it calls the ConfigureProvider RPC. + if request.ProviderData == nil { + return } - secretID, ok := d.GetOk("secret_id") + client, ok := request.ProviderData.(*scw.Client) if !ok { - secretName := d.Get("name").(string) - request := &secret.ListSecretsRequest{ - Region: region, - Name: types.ExpandStringPtr(secretName), - ProjectID: projectID, - OrganizationID: types.ExpandStringPtr(d.Get("organization_id")), - Path: types.ExpandStringPtr(d.Get("path")), - } - - res, err := api.ListSecrets(request, scw.WithContext(ctx)) - if err != nil { - return diag.FromErr(err) - } - - foundSecret, err := datasource.FindExact( - res.Secrets, - func(s *secret.Secret) bool { return s.Name == secretName }, - secretName, + response.Diagnostics.AddError( + "Unexpected Action Configure Type", + fmt.Sprintf("Expected *scw.Client, got: %T. Please report this issue to the provider developers.", request.ProviderData), ) - if err != nil { - return diag.FromErr(err) - } - secretID = foundSecret.ID + return } - regionalID := datasource.NewRegionalID(secretID, region) - d.SetId(regionalID) + d.secretAPI = secret.NewAPI(client) +} - err = d.Set("secret_id", regionalID) - if err != nil { - return diag.FromErr(err) - } +func (d DataSourceSecret) Read(ctx context.Context, request datasource.ReadRequest, response *datasource.ReadResponse) { + // Prevent panic if the provider has not been configured. + if d.secretAPI == nil { + response.Diagnostics.AddError( + "Unconfigured Scaleway Client", + "Expected configured Scaleway Client. Please report this issue to the provider developers.", + ) - diags := ResourceSecretRead(ctx, d, m) - if diags != nil { - return append(diags, diag.Errorf("failed to read secret")...) + return } - if d.Id() == "" { - return diag.Errorf("secret (%s) not found", regionalID) - } + // secretID, ok := d.GetOk("secret_id") + // if !ok { + // secretName := d.Get("name").(string) + // request := &secret.ListSecretsRequest{ + // Region: region, + // Name: types.ExpandStringPtr(secretName), + // ProjectID: projectID, + // OrganizationID: types.ExpandStringPtr(d.Get("organization_id")), + // Path: types.ExpandStringPtr(d.Get("path")), + // } + // + // res, err := api.ListSecrets(request, scw.WithContext(ctx)) + // if err != nil { + // return diag.FromErr(err) + // } + // + // foundSecret, err := datasource.FindExact( + // res.Secrets, + // func(s *secret.Secret) bool { return s.Name == secretName }, + // secretName, + // ) + // if err != nil { + // return diag.FromErr(err) + // } + // + // secretID = foundSecret.ID + // } + // + // regionalID := datasource.NewRegionalID(secretID, region) + // d.SetId(regionalID) + // + // err = d.Set("secret_id", regionalID) + // if err != nil { + // return diag.FromErr(err) + // } + // + // diags := ResourceSecretRead(ctx, d, m) + // if diags != nil { + // return append(diags, diag.Errorf("failed to read secret")...) + // } + // + // if d.Id() == "" { + // return diag.Errorf("secret (%s) not found", regionalID) + // } + // + // return nil +} - return nil +func (d DataSourceSecret) ConfigValidators(ctx context.Context) []datasource.ConfigValidator { + return []datasource.ConfigValidator{ + datasourcevalidator.Conflicting( + path.MatchRoot("name"), + path.MatchRoot("secret_id"), + ), + datasourcevalidator.Conflicting( + path.MatchRoot("path"), + path.MatchRoot("secret_id"), + ), + } } + +//func DataSourceSecret() *schema.Resource { +// // Set 'Optional' schema elements +// datasource.AddOptionalFieldsToSchema(dsSchema, "name", "region", "path") +// + +// diff --git a/internal/services/secret/testdata/data-source-secret-basic.cassette.yaml b/internal/services/secret/testdata/data-source-secret-basic.cassette.yaml index 5b4047d750..6b3e81e40f 100644 --- a/internal/services/secret/testdata/data-source-secret-basic.cassette.yaml +++ b/internal/services/secret/testdata/data-source-secret-basic.cassette.yaml @@ -6,19 +6,19 @@ interactions: proto: HTTP/1.1 proto_major: 1 proto_minor: 1 - content_length: 130 + content_length: 129 transfer_encoding: [] trailer: {} host: api.scaleway.com remote_addr: "" request_uri: "" - body: '{"name":"test-acc-scaleway-project-8063775891052703106","organization_id":"564aa517-68b0-4fd7-8c8c-d21c4bcdcbd5","description":""}' + body: '{"name":"test-acc-scaleway-project-646784994312797478","organization_id":"105bdce1-64c0-48ab-899d-868455867ecf","description":""}' form: {} headers: Content-Type: - application/json User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.4; darwin; arm64) terraform-provider/develop terraform/terraform-tests + - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.25.2; darwin; arm64) terraform-provider/develop terraform/terraform-tests url: https://api.scaleway.com/account/v3/projects method: POST response: @@ -27,20 +27,20 @@ interactions: proto_minor: 0 transfer_encoding: [] trailer: {} - content_length: 281 + content_length: 286 uncompressed: false - body: '{"created_at":"2025-09-05T15:46:53.900336Z","description":"","id":"1ed5e80d-f8dc-4d20-be90-44f4b6b7186d","name":"test-acc-scaleway-project-8063775891052703106","organization_id":"564aa517-68b0-4fd7-8c8c-d21c4bcdcbd5","qualification":null,"updated_at":"2025-09-05T15:46:53.900336Z"}' + body: '{"created_at":"2025-10-09T17:18:11.956151Z","description":"","id":"d0641bf1-879f-4351-83a0-dba7cd119b25","name":"test-acc-scaleway-project-646784994312797478","organization_id":"105bdce1-64c0-48ab-899d-868455867ecf","qualification":null,"updated_at":"2025-10-09T17:18:11.956151Z"}' headers: Content-Length: - - "281" + - "286" Content-Security-Policy: - default-src 'none'; frame-ancestors 'none' Content-Type: - application/json Date: - - Fri, 05 Sep 2025 15:46:54 GMT + - Thu, 09 Oct 2025 17:18:12 GMT Server: - - Scaleway API Gateway (fr-par-3;edge02) + - Scaleway API Gateway (fr-par-2;edge03) Strict-Transport-Security: - max-age=63072000 X-Content-Type-Options: @@ -48,10 +48,10 @@ interactions: X-Frame-Options: - DENY X-Request-Id: - - aa43cbaf-259c-49f6-b618-70bd1dfe9789 + - 10976b26-baec-4875-aa3f-5fd3e872cc64 status: 200 OK code: 200 - duration: 461.997959ms + duration: 1.077142416s - id: 1 request: proto: HTTP/1.1 @@ -63,13 +63,13 @@ interactions: host: api.scaleway.com remote_addr: "" request_uri: "" - body: '{"name":"test-acc-scaleway-iam-app-5023269902985808251","organization_id":"564aa517-68b0-4fd7-8c8c-d21c4bcdcbd5","description":"","tags":null}' + body: '{"name":"test-acc-scaleway-iam-app-2968660574793270943","organization_id":"105bdce1-64c0-48ab-899d-868455867ecf","description":"","tags":null}' form: {} headers: Content-Type: - application/json User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.4; darwin; arm64) terraform-provider/develop terraform/terraform-tests + - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.25.2; darwin; arm64) terraform-provider/develop terraform/terraform-tests url: https://api.scaleway.com/iam/v1alpha1/applications method: POST response: @@ -78,20 +78,20 @@ interactions: proto_minor: 0 transfer_encoding: [] trailer: {} - content_length: 335 + content_length: 345 uncompressed: false - body: '{"created_at":"2025-09-05T15:46:54.169759Z","deletable":true,"description":"","editable":true,"id":"6aac30e2-1842-4822-aced-1d5d171f6c44","managed":false,"name":"test-acc-scaleway-iam-app-5023269902985808251","nb_api_keys":0,"organization_id":"564aa517-68b0-4fd7-8c8c-d21c4bcdcbd5","tags":[],"updated_at":"2025-09-05T15:46:54.169759Z"}' + body: '{"created_at":"2025-10-09T17:18:12.545253Z","deletable":true,"description":"","editable":true,"id":"a36d95f6-8471-4145-9115-c43df8488486","managed":false,"name":"test-acc-scaleway-iam-app-2968660574793270943","nb_api_keys":0,"organization_id":"105bdce1-64c0-48ab-899d-868455867ecf","tags":[],"updated_at":"2025-10-09T17:18:12.545253Z"}' headers: Content-Length: - - "335" + - "345" Content-Security-Policy: - default-src 'none'; frame-ancestors 'none' Content-Type: - application/json Date: - - Fri, 05 Sep 2025 15:46:54 GMT + - Thu, 09 Oct 2025 17:18:12 GMT Server: - - Scaleway API Gateway (fr-par-3;edge02) + - Scaleway API Gateway (fr-par-2;edge03) Strict-Transport-Security: - max-age=63072000 X-Content-Type-Options: @@ -99,10 +99,10 @@ interactions: X-Frame-Options: - DENY X-Request-Id: - - 8a80752b-e492-4de6-895b-08469e618e53 + - bc74c854-57cd-4400-9a70-fe877f332a88 status: 200 OK code: 200 - duration: 131.196958ms + duration: 275.318125ms - id: 2 request: proto: HTTP/1.1 @@ -114,13 +114,13 @@ interactions: host: api.scaleway.com remote_addr: "" request_uri: "" - body: '{"name":"test-acc-scaleway-iam-policy-5588848851561709717","description":"","organization_id":"564aa517-68b0-4fd7-8c8c-d21c4bcdcbd5","rules":[{"permission_set_names":["IAMManager"],"condition":"","organization_id":"564aa517-68b0-4fd7-8c8c-d21c4bcdcbd5"}],"tags":null,"application_id":"6aac30e2-1842-4822-aced-1d5d171f6c44"}' + body: '{"name":"test-acc-scaleway-iam-policy-3252272878197374306","description":"","organization_id":"105bdce1-64c0-48ab-899d-868455867ecf","rules":[{"permission_set_names":["IAMManager"],"condition":"","organization_id":"105bdce1-64c0-48ab-899d-868455867ecf"}],"tags":null,"application_id":"a36d95f6-8471-4145-9115-c43df8488486"}' form: {} headers: Content-Type: - application/json User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.4; darwin; arm64) terraform-provider/develop terraform/terraform-tests + - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.25.2; darwin; arm64) terraform-provider/develop terraform/terraform-tests url: https://api.scaleway.com/iam/v1alpha1/policies method: POST response: @@ -129,20 +129,20 @@ interactions: proto_minor: 0 transfer_encoding: [] trailer: {} - content_length: 428 + content_length: 441 uncompressed: false - body: '{"application_id":"6aac30e2-1842-4822-aced-1d5d171f6c44","created_at":"2025-09-05T15:46:54.313975Z","deletable":true,"description":"","editable":true,"id":"a50001b5-27ca-494f-8773-8d9bf46dbc95","managed":false,"name":"test-acc-scaleway-iam-policy-5588848851561709717","nb_permission_sets":0,"nb_rules":0,"nb_scopes":0,"organization_id":"564aa517-68b0-4fd7-8c8c-d21c4bcdcbd5","tags":[],"updated_at":"2025-09-05T15:46:54.313975Z"}' + body: '{"application_id":"a36d95f6-8471-4145-9115-c43df8488486","created_at":"2025-10-09T17:18:12.812129Z","deletable":true,"description":"","editable":true,"id":"649185b4-c64d-4d8e-b467-92c7151c5a64","managed":false,"name":"test-acc-scaleway-iam-policy-3252272878197374306","nb_permission_sets":0,"nb_rules":0,"nb_scopes":0,"organization_id":"105bdce1-64c0-48ab-899d-868455867ecf","tags":[],"updated_at":"2025-10-09T17:18:12.812129Z"}' headers: Content-Length: - - "428" + - "441" Content-Security-Policy: - default-src 'none'; frame-ancestors 'none' Content-Type: - application/json Date: - - Fri, 05 Sep 2025 15:46:54 GMT + - Thu, 09 Oct 2025 17:18:12 GMT Server: - - Scaleway API Gateway (fr-par-3;edge02) + - Scaleway API Gateway (fr-par-2;edge03) Strict-Transport-Security: - max-age=63072000 X-Content-Type-Options: @@ -150,10 +150,10 @@ interactions: X-Frame-Options: - DENY X-Request-Id: - - 94063050-d33d-459d-b4d1-8ccad0b027d3 + - e3ea2674-5d06-47b6-97b7-a6e51ec29336 status: 200 OK code: 200 - duration: 179.840375ms + duration: 322.094042ms - id: 3 request: proto: HTTP/1.1 @@ -165,13 +165,13 @@ interactions: host: api.scaleway.com remote_addr: "" request_uri: "" - body: '{"application_id":"6aac30e2-1842-4822-aced-1d5d171f6c44","default_project_id":"1ed5e80d-f8dc-4d20-be90-44f4b6b7186d","description":""}' + body: '{"application_id":"a36d95f6-8471-4145-9115-c43df8488486","default_project_id":"d0641bf1-879f-4351-83a0-dba7cd119b25","description":""}' form: {} headers: Content-Type: - application/json User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.4; darwin; arm64) terraform-provider/develop terraform/terraform-tests + - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.25.2; darwin; arm64) terraform-provider/develop terraform/terraform-tests url: https://api.scaleway.com/iam/v1alpha1/api-keys method: POST response: @@ -180,20 +180,20 @@ interactions: proto_minor: 0 transfer_encoding: [] trailer: {} - content_length: 404 + content_length: 416 uncompressed: false - body: '{"access_key":"SCWZQ1N8VGXQP2Z6CC8V","application_id":"6aac30e2-1842-4822-aced-1d5d171f6c44","created_at":"2025-09-05T15:46:54.478970Z","creation_ip":"41.96.92.239","default_project_id":"1ed5e80d-f8dc-4d20-be90-44f4b6b7186d","deletable":true,"description":"","editable":true,"expires_at":null,"managed":false,"secret_key":"00000000-0000-0000-0000-000000000000","updated_at":"2025-09-05T15:46:54.478970Z"}' + body: '{"access_key":"SCWTK56XHNK2G9HX4VT4","application_id":"a36d95f6-8471-4145-9115-c43df8488486","created_at":"2025-10-09T17:18:13.118277Z","creation_ip":"51.159.46.153","default_project_id":"d0641bf1-879f-4351-83a0-dba7cd119b25","deletable":true,"description":"","editable":true,"expires_at":null,"managed":false,"secret_key":"00000000-0000-0000-0000-000000000000","updated_at":"2025-10-09T17:18:13.118277Z"}' headers: Content-Length: - - "404" + - "416" Content-Security-Policy: - default-src 'none'; frame-ancestors 'none' Content-Type: - application/json Date: - - Fri, 05 Sep 2025 15:46:54 GMT + - Thu, 09 Oct 2025 17:18:13 GMT Server: - - Scaleway API Gateway (fr-par-3;edge02) + - Scaleway API Gateway (fr-par-2;edge03) Strict-Transport-Security: - max-age=63072000 X-Content-Type-Options: @@ -201,1469 +201,7 @@ interactions: X-Frame-Options: - DENY X-Request-Id: - - 64baf272-5614-4e7f-a032-f69b871d26dd + - 8d566ffb-a241-48c6-9e5e-f75b09f87146 status: 200 OK code: 200 - duration: 129.672667ms - - id: 4 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 194 - transfer_encoding: [] - trailer: {} - host: api.scaleway.com - remote_addr: "" - request_uri: "" - body: '{"project_id":"1ed5e80d-f8dc-4d20-be90-44f4b6b7186d","name":"scalewayDataSourceSecret","tags":null,"description":"DataSourceSecret test description","type":"opaque","path":"/","protected":false}' - form: {} - headers: - Content-Type: - - application/json - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.4; darwin; arm64) terraform-provider/develop terraform/terraform-tests - url: https://api.scaleway.com/secret-manager/v1beta1/regions/fr-par/secrets - method: POST - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - transfer_encoding: [] - trailer: {} - content_length: 471 - uncompressed: false - body: '{"created_at":"2025-09-05T15:46:54.943096Z","deletion_requested_at":null,"description":"DataSourceSecret test description","ephemeral_policy":null,"id":"112b8309-7612-4953-91f6-c7a926b87a2a","key_id":null,"managed":false,"name":"scalewayDataSourceSecret","path":"/","project_id":"1ed5e80d-f8dc-4d20-be90-44f4b6b7186d","protected":false,"region":"fr-par","status":"ready","tags":[],"type":"opaque","updated_at":"2025-09-05T15:46:54.943096Z","used_by":[],"version_count":0}' - headers: - Content-Length: - - "471" - Content-Security-Policy: - - default-src 'none'; frame-ancestors 'none' - Content-Type: - - application/json - Date: - - Fri, 05 Sep 2025 15:46:54 GMT - Server: - - Scaleway API Gateway (fr-par-3;edge02) - Strict-Transport-Security: - - max-age=63072000 - X-Content-Type-Options: - - nosniff - X-Frame-Options: - - DENY - X-Request-Id: - - c25acc08-f838-47a8-b5d2-35e91e7d6a74 - status: 200 OK - code: 200 - duration: 174.642ms - - id: 5 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - transfer_encoding: [] - trailer: {} - host: api.scaleway.com - remote_addr: "" - request_uri: "" - body: "" - form: {} - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.4; darwin; arm64) terraform-provider/develop terraform/terraform-tests - url: https://api.scaleway.com/secret-manager/v1beta1/regions/fr-par/secrets/112b8309-7612-4953-91f6-c7a926b87a2a - method: GET - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - transfer_encoding: [] - trailer: {} - content_length: 471 - uncompressed: false - body: '{"created_at":"2025-09-05T15:46:54.943096Z","deletion_requested_at":null,"description":"DataSourceSecret test description","ephemeral_policy":null,"id":"112b8309-7612-4953-91f6-c7a926b87a2a","key_id":null,"managed":false,"name":"scalewayDataSourceSecret","path":"/","project_id":"1ed5e80d-f8dc-4d20-be90-44f4b6b7186d","protected":false,"region":"fr-par","status":"ready","tags":[],"type":"opaque","updated_at":"2025-09-05T15:46:54.943096Z","used_by":[],"version_count":0}' - headers: - Content-Length: - - "471" - Content-Security-Policy: - - default-src 'none'; frame-ancestors 'none' - Content-Type: - - application/json - Date: - - Fri, 05 Sep 2025 15:46:55 GMT - Server: - - Scaleway API Gateway (fr-par-3;edge02) - Strict-Transport-Security: - - max-age=63072000 - X-Content-Type-Options: - - nosniff - X-Frame-Options: - - DENY - X-Request-Id: - - c10c65c3-1ce0-404a-935c-0f939c459c32 - status: 200 OK - code: 200 - duration: 80.095542ms - - id: 6 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - transfer_encoding: [] - trailer: {} - host: api.scaleway.com - remote_addr: "" - request_uri: "" - body: "" - form: {} - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.4; darwin; arm64) terraform-provider/develop terraform/terraform-tests - url: https://api.scaleway.com/secret-manager/v1beta1/regions/fr-par/secrets/112b8309-7612-4953-91f6-c7a926b87a2a/versions?page=1 - method: GET - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - transfer_encoding: [] - trailer: {} - content_length: 31 - uncompressed: false - body: '{"total_count":0,"versions":[]}' - headers: - Content-Length: - - "31" - Content-Security-Policy: - - default-src 'none'; frame-ancestors 'none' - Content-Type: - - application/json - Date: - - Fri, 05 Sep 2025 15:46:55 GMT - Server: - - Scaleway API Gateway (fr-par-3;edge02) - Strict-Transport-Security: - - max-age=63072000 - X-Content-Type-Options: - - nosniff - X-Frame-Options: - - DENY - X-Request-Id: - - 489aad9e-224d-4bbd-87dd-0c466032d9e5 - status: 200 OK - code: 200 - duration: 57.969417ms - - id: 7 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - transfer_encoding: [] - trailer: {} - host: api.scaleway.com - remote_addr: "" - request_uri: "" - body: "" - form: {} - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.4; darwin; arm64) terraform-provider/develop terraform/terraform-tests - url: https://api.scaleway.com/secret-manager/v1beta1/regions/fr-par/secrets?name=scalewayDataSourceSecret&order_by=name_asc&organization_id=564aa517-68b0-4fd7-8c8c-d21c4bcdcbd5&project_id=1ed5e80d-f8dc-4d20-be90-44f4b6b7186d&scheduled_for_deletion=false&type=unknown_type - method: GET - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - transfer_encoding: [] - trailer: {} - content_length: 501 - uncompressed: false - body: '{"secrets":[{"created_at":"2025-09-05T15:46:54.943096Z","deletion_requested_at":null,"description":"DataSourceSecret test description","ephemeral_policy":null,"id":"112b8309-7612-4953-91f6-c7a926b87a2a","key_id":null,"managed":false,"name":"scalewayDataSourceSecret","path":"/","project_id":"1ed5e80d-f8dc-4d20-be90-44f4b6b7186d","protected":false,"region":"fr-par","status":"ready","tags":[],"type":"opaque","updated_at":"2025-09-05T15:46:54.943096Z","used_by":[],"version_count":0}],"total_count":1}' - headers: - Content-Length: - - "501" - Content-Security-Policy: - - default-src 'none'; frame-ancestors 'none' - Content-Type: - - application/json - Date: - - Fri, 05 Sep 2025 15:46:55 GMT - Server: - - Scaleway API Gateway (fr-par-3;edge02) - Strict-Transport-Security: - - max-age=63072000 - X-Content-Type-Options: - - nosniff - X-Frame-Options: - - DENY - X-Request-Id: - - c523f935-d3a4-4604-8ba2-5bad64339ef3 - status: 200 OK - code: 200 - duration: 79.611583ms - - id: 8 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - transfer_encoding: [] - trailer: {} - host: api.scaleway.com - remote_addr: "" - request_uri: "" - body: "" - form: {} - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.4; darwin; arm64) terraform-provider/develop terraform/terraform-tests - url: https://api.scaleway.com/secret-manager/v1beta1/regions/fr-par/secrets/112b8309-7612-4953-91f6-c7a926b87a2a - method: GET - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - transfer_encoding: [] - trailer: {} - content_length: 471 - uncompressed: false - body: '{"created_at":"2025-09-05T15:46:54.943096Z","deletion_requested_at":null,"description":"DataSourceSecret test description","ephemeral_policy":null,"id":"112b8309-7612-4953-91f6-c7a926b87a2a","key_id":null,"managed":false,"name":"scalewayDataSourceSecret","path":"/","project_id":"1ed5e80d-f8dc-4d20-be90-44f4b6b7186d","protected":false,"region":"fr-par","status":"ready","tags":[],"type":"opaque","updated_at":"2025-09-05T15:46:54.943096Z","used_by":[],"version_count":0}' - headers: - Content-Length: - - "471" - Content-Security-Policy: - - default-src 'none'; frame-ancestors 'none' - Content-Type: - - application/json - Date: - - Fri, 05 Sep 2025 15:46:55 GMT - Server: - - Scaleway API Gateway (fr-par-3;edge02) - Strict-Transport-Security: - - max-age=63072000 - X-Content-Type-Options: - - nosniff - X-Frame-Options: - - DENY - X-Request-Id: - - 1815bb45-8a50-4e61-ad81-56e776b39293 - status: 200 OK - code: 200 - duration: 93.248ms - - id: 9 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - transfer_encoding: [] - trailer: {} - host: api.scaleway.com - remote_addr: "" - request_uri: "" - body: "" - form: {} - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.4; darwin; arm64) terraform-provider/develop terraform/terraform-tests - url: https://api.scaleway.com/secret-manager/v1beta1/regions/fr-par/secrets/112b8309-7612-4953-91f6-c7a926b87a2a - method: GET - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - transfer_encoding: [] - trailer: {} - content_length: 471 - uncompressed: false - body: '{"created_at":"2025-09-05T15:46:54.943096Z","deletion_requested_at":null,"description":"DataSourceSecret test description","ephemeral_policy":null,"id":"112b8309-7612-4953-91f6-c7a926b87a2a","key_id":null,"managed":false,"name":"scalewayDataSourceSecret","path":"/","project_id":"1ed5e80d-f8dc-4d20-be90-44f4b6b7186d","protected":false,"region":"fr-par","status":"ready","tags":[],"type":"opaque","updated_at":"2025-09-05T15:46:54.943096Z","used_by":[],"version_count":0}' - headers: - Content-Length: - - "471" - Content-Security-Policy: - - default-src 'none'; frame-ancestors 'none' - Content-Type: - - application/json - Date: - - Fri, 05 Sep 2025 15:46:55 GMT - Server: - - Scaleway API Gateway (fr-par-3;edge02) - Strict-Transport-Security: - - max-age=63072000 - X-Content-Type-Options: - - nosniff - X-Frame-Options: - - DENY - X-Request-Id: - - 24cf9fbb-ce96-4be9-8ecc-7bb26c78cb6e - status: 200 OK - code: 200 - duration: 55.476833ms - - id: 10 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - transfer_encoding: [] - trailer: {} - host: api.scaleway.com - remote_addr: "" - request_uri: "" - body: "" - form: {} - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.4; darwin; arm64) terraform-provider/develop terraform/terraform-tests - url: https://api.scaleway.com/secret-manager/v1beta1/regions/fr-par/secrets/112b8309-7612-4953-91f6-c7a926b87a2a/versions?page=1 - method: GET - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - transfer_encoding: [] - trailer: {} - content_length: 31 - uncompressed: false - body: '{"total_count":0,"versions":[]}' - headers: - Content-Length: - - "31" - Content-Security-Policy: - - default-src 'none'; frame-ancestors 'none' - Content-Type: - - application/json - Date: - - Fri, 05 Sep 2025 15:46:55 GMT - Server: - - Scaleway API Gateway (fr-par-3;edge02) - Strict-Transport-Security: - - max-age=63072000 - X-Content-Type-Options: - - nosniff - X-Frame-Options: - - DENY - X-Request-Id: - - c85b1e2e-cf71-4975-9a0a-dd2934004316 - status: 200 OK - code: 200 - duration: 88.899167ms - - id: 11 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - transfer_encoding: [] - trailer: {} - host: api.scaleway.com - remote_addr: "" - request_uri: "" - body: "" - form: {} - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.4; darwin; arm64) terraform-provider/develop terraform/terraform-tests - url: https://api.scaleway.com/secret-manager/v1beta1/regions/fr-par/secrets/112b8309-7612-4953-91f6-c7a926b87a2a/versions?page=1 - method: GET - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - transfer_encoding: [] - trailer: {} - content_length: 31 - uncompressed: false - body: '{"total_count":0,"versions":[]}' - headers: - Content-Length: - - "31" - Content-Security-Policy: - - default-src 'none'; frame-ancestors 'none' - Content-Type: - - application/json - Date: - - Fri, 05 Sep 2025 15:46:55 GMT - Server: - - Scaleway API Gateway (fr-par-3;edge02) - Strict-Transport-Security: - - max-age=63072000 - X-Content-Type-Options: - - nosniff - X-Frame-Options: - - DENY - X-Request-Id: - - dbbc5723-7fef-4f3d-96e3-a60d3da84c09 - status: 200 OK - code: 200 - duration: 56.040667ms - - id: 12 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - transfer_encoding: [] - trailer: {} - host: api.scaleway.com - remote_addr: "" - request_uri: "" - body: "" - form: {} - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.4; darwin; arm64) terraform-provider/develop terraform/terraform-tests - url: https://api.scaleway.com/secret-manager/v1beta1/regions/fr-par/secrets/112b8309-7612-4953-91f6-c7a926b87a2a - method: GET - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - transfer_encoding: [] - trailer: {} - content_length: 471 - uncompressed: false - body: '{"created_at":"2025-09-05T15:46:54.943096Z","deletion_requested_at":null,"description":"DataSourceSecret test description","ephemeral_policy":null,"id":"112b8309-7612-4953-91f6-c7a926b87a2a","key_id":null,"managed":false,"name":"scalewayDataSourceSecret","path":"/","project_id":"1ed5e80d-f8dc-4d20-be90-44f4b6b7186d","protected":false,"region":"fr-par","status":"ready","tags":[],"type":"opaque","updated_at":"2025-09-05T15:46:54.943096Z","used_by":[],"version_count":0}' - headers: - Content-Length: - - "471" - Content-Security-Policy: - - default-src 'none'; frame-ancestors 'none' - Content-Type: - - application/json - Date: - - Fri, 05 Sep 2025 15:46:55 GMT - Server: - - Scaleway API Gateway (fr-par-3;edge02) - Strict-Transport-Security: - - max-age=63072000 - X-Content-Type-Options: - - nosniff - X-Frame-Options: - - DENY - X-Request-Id: - - 323cc4f7-23e4-4c71-bf1a-bc8f86cae44f - status: 200 OK - code: 200 - duration: 66.558ms - - id: 13 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - transfer_encoding: [] - trailer: {} - host: api.scaleway.com - remote_addr: "" - request_uri: "" - body: "" - form: {} - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.4; darwin; arm64) terraform-provider/develop terraform/terraform-tests - url: https://api.scaleway.com/secret-manager/v1beta1/regions/fr-par/secrets/112b8309-7612-4953-91f6-c7a926b87a2a - method: GET - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - transfer_encoding: [] - trailer: {} - content_length: 471 - uncompressed: false - body: '{"created_at":"2025-09-05T15:46:54.943096Z","deletion_requested_at":null,"description":"DataSourceSecret test description","ephemeral_policy":null,"id":"112b8309-7612-4953-91f6-c7a926b87a2a","key_id":null,"managed":false,"name":"scalewayDataSourceSecret","path":"/","project_id":"1ed5e80d-f8dc-4d20-be90-44f4b6b7186d","protected":false,"region":"fr-par","status":"ready","tags":[],"type":"opaque","updated_at":"2025-09-05T15:46:54.943096Z","used_by":[],"version_count":0}' - headers: - Content-Length: - - "471" - Content-Security-Policy: - - default-src 'none'; frame-ancestors 'none' - Content-Type: - - application/json - Date: - - Fri, 05 Sep 2025 15:46:55 GMT - Server: - - Scaleway API Gateway (fr-par-3;edge02) - Strict-Transport-Security: - - max-age=63072000 - X-Content-Type-Options: - - nosniff - X-Frame-Options: - - DENY - X-Request-Id: - - 6b47b2a0-cf3b-442d-983e-33d9e93aa659 - status: 200 OK - code: 200 - duration: 58.502416ms - - id: 14 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - transfer_encoding: [] - trailer: {} - host: api.scaleway.com - remote_addr: "" - request_uri: "" - body: "" - form: {} - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.4; darwin; arm64) terraform-provider/develop terraform/terraform-tests - url: https://api.scaleway.com/secret-manager/v1beta1/regions/fr-par/secrets/112b8309-7612-4953-91f6-c7a926b87a2a - method: GET - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - transfer_encoding: [] - trailer: {} - content_length: 471 - uncompressed: false - body: '{"created_at":"2025-09-05T15:46:54.943096Z","deletion_requested_at":null,"description":"DataSourceSecret test description","ephemeral_policy":null,"id":"112b8309-7612-4953-91f6-c7a926b87a2a","key_id":null,"managed":false,"name":"scalewayDataSourceSecret","path":"/","project_id":"1ed5e80d-f8dc-4d20-be90-44f4b6b7186d","protected":false,"region":"fr-par","status":"ready","tags":[],"type":"opaque","updated_at":"2025-09-05T15:46:54.943096Z","used_by":[],"version_count":0}' - headers: - Content-Length: - - "471" - Content-Security-Policy: - - default-src 'none'; frame-ancestors 'none' - Content-Type: - - application/json - Date: - - Fri, 05 Sep 2025 15:46:55 GMT - Server: - - Scaleway API Gateway (fr-par-3;edge02) - Strict-Transport-Security: - - max-age=63072000 - X-Content-Type-Options: - - nosniff - X-Frame-Options: - - DENY - X-Request-Id: - - 0af5b5bd-18bb-43c8-835c-fea8b7d5cb10 - status: 200 OK - code: 200 - duration: 60.794625ms - - id: 15 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - transfer_encoding: [] - trailer: {} - host: api.scaleway.com - remote_addr: "" - request_uri: "" - body: "" - form: {} - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.4; darwin; arm64) terraform-provider/develop terraform/terraform-tests - url: https://api.scaleway.com/secret-manager/v1beta1/regions/fr-par/secrets?name=scalewayDataSourceSecret&order_by=name_asc&organization_id=564aa517-68b0-4fd7-8c8c-d21c4bcdcbd5&project_id=1ed5e80d-f8dc-4d20-be90-44f4b6b7186d&scheduled_for_deletion=false&type=unknown_type - method: GET - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - transfer_encoding: [] - trailer: {} - content_length: 501 - uncompressed: false - body: '{"secrets":[{"created_at":"2025-09-05T15:46:54.943096Z","deletion_requested_at":null,"description":"DataSourceSecret test description","ephemeral_policy":null,"id":"112b8309-7612-4953-91f6-c7a926b87a2a","key_id":null,"managed":false,"name":"scalewayDataSourceSecret","path":"/","project_id":"1ed5e80d-f8dc-4d20-be90-44f4b6b7186d","protected":false,"region":"fr-par","status":"ready","tags":[],"type":"opaque","updated_at":"2025-09-05T15:46:54.943096Z","used_by":[],"version_count":0}],"total_count":1}' - headers: - Content-Length: - - "501" - Content-Security-Policy: - - default-src 'none'; frame-ancestors 'none' - Content-Type: - - application/json - Date: - - Fri, 05 Sep 2025 15:46:55 GMT - Server: - - Scaleway API Gateway (fr-par-3;edge02) - Strict-Transport-Security: - - max-age=63072000 - X-Content-Type-Options: - - nosniff - X-Frame-Options: - - DENY - X-Request-Id: - - 2951eb30-88ca-4d55-a986-bbff0ce3ae6d - status: 200 OK - code: 200 - duration: 96.401709ms - - id: 16 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - transfer_encoding: [] - trailer: {} - host: api.scaleway.com - remote_addr: "" - request_uri: "" - body: "" - form: {} - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.4; darwin; arm64) terraform-provider/develop terraform/terraform-tests - url: https://api.scaleway.com/secret-manager/v1beta1/regions/fr-par/secrets/112b8309-7612-4953-91f6-c7a926b87a2a/versions?page=1 - method: GET - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - transfer_encoding: [] - trailer: {} - content_length: 31 - uncompressed: false - body: '{"total_count":0,"versions":[]}' - headers: - Content-Length: - - "31" - Content-Security-Policy: - - default-src 'none'; frame-ancestors 'none' - Content-Type: - - application/json - Date: - - Fri, 05 Sep 2025 15:46:55 GMT - Server: - - Scaleway API Gateway (fr-par-3;edge02) - Strict-Transport-Security: - - max-age=63072000 - X-Content-Type-Options: - - nosniff - X-Frame-Options: - - DENY - X-Request-Id: - - c194635e-2624-4066-8df8-4887b4eb39bc - status: 200 OK - code: 200 - duration: 72.004125ms - - id: 17 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - transfer_encoding: [] - trailer: {} - host: api.scaleway.com - remote_addr: "" - request_uri: "" - body: "" - form: {} - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.4; darwin; arm64) terraform-provider/develop terraform/terraform-tests - url: https://api.scaleway.com/secret-manager/v1beta1/regions/fr-par/secrets/112b8309-7612-4953-91f6-c7a926b87a2a - method: GET - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - transfer_encoding: [] - trailer: {} - content_length: 471 - uncompressed: false - body: '{"created_at":"2025-09-05T15:46:54.943096Z","deletion_requested_at":null,"description":"DataSourceSecret test description","ephemeral_policy":null,"id":"112b8309-7612-4953-91f6-c7a926b87a2a","key_id":null,"managed":false,"name":"scalewayDataSourceSecret","path":"/","project_id":"1ed5e80d-f8dc-4d20-be90-44f4b6b7186d","protected":false,"region":"fr-par","status":"ready","tags":[],"type":"opaque","updated_at":"2025-09-05T15:46:54.943096Z","used_by":[],"version_count":0}' - headers: - Content-Length: - - "471" - Content-Security-Policy: - - default-src 'none'; frame-ancestors 'none' - Content-Type: - - application/json - Date: - - Fri, 05 Sep 2025 15:46:55 GMT - Server: - - Scaleway API Gateway (fr-par-3;edge02) - Strict-Transport-Security: - - max-age=63072000 - X-Content-Type-Options: - - nosniff - X-Frame-Options: - - DENY - X-Request-Id: - - 66ed80ac-8c6b-486a-a00b-0312234d6beb - status: 200 OK - code: 200 - duration: 56.019541ms - - id: 18 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - transfer_encoding: [] - trailer: {} - host: api.scaleway.com - remote_addr: "" - request_uri: "" - body: "" - form: {} - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.4; darwin; arm64) terraform-provider/develop terraform/terraform-tests - url: https://api.scaleway.com/secret-manager/v1beta1/regions/fr-par/secrets/112b8309-7612-4953-91f6-c7a926b87a2a/versions?page=1 - method: GET - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - transfer_encoding: [] - trailer: {} - content_length: 31 - uncompressed: false - body: '{"total_count":0,"versions":[]}' - headers: - Content-Length: - - "31" - Content-Security-Policy: - - default-src 'none'; frame-ancestors 'none' - Content-Type: - - application/json - Date: - - Fri, 05 Sep 2025 15:46:55 GMT - Server: - - Scaleway API Gateway (fr-par-3;edge02) - Strict-Transport-Security: - - max-age=63072000 - X-Content-Type-Options: - - nosniff - X-Frame-Options: - - DENY - X-Request-Id: - - c02ad933-2abd-4337-9d63-bbc4266755de - status: 200 OK - code: 200 - duration: 67.924833ms - - id: 19 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - transfer_encoding: [] - trailer: {} - host: api.scaleway.com - remote_addr: "" - request_uri: "" - body: "" - form: {} - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.4; darwin; arm64) terraform-provider/develop terraform/terraform-tests - url: https://api.scaleway.com/secret-manager/v1beta1/regions/fr-par/secrets/112b8309-7612-4953-91f6-c7a926b87a2a - method: GET - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - transfer_encoding: [] - trailer: {} - content_length: 471 - uncompressed: false - body: '{"created_at":"2025-09-05T15:46:54.943096Z","deletion_requested_at":null,"description":"DataSourceSecret test description","ephemeral_policy":null,"id":"112b8309-7612-4953-91f6-c7a926b87a2a","key_id":null,"managed":false,"name":"scalewayDataSourceSecret","path":"/","project_id":"1ed5e80d-f8dc-4d20-be90-44f4b6b7186d","protected":false,"region":"fr-par","status":"ready","tags":[],"type":"opaque","updated_at":"2025-09-05T15:46:54.943096Z","used_by":[],"version_count":0}' - headers: - Content-Length: - - "471" - Content-Security-Policy: - - default-src 'none'; frame-ancestors 'none' - Content-Type: - - application/json - Date: - - Fri, 05 Sep 2025 15:46:56 GMT - Server: - - Scaleway API Gateway (fr-par-3;edge02) - Strict-Transport-Security: - - max-age=63072000 - X-Content-Type-Options: - - nosniff - X-Frame-Options: - - DENY - X-Request-Id: - - e759d1be-d0cf-455d-83d1-9741c1702fd4 - status: 200 OK - code: 200 - duration: 57.854833ms - - id: 20 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - transfer_encoding: [] - trailer: {} - host: api.scaleway.com - remote_addr: "" - request_uri: "" - body: "" - form: {} - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.4; darwin; arm64) terraform-provider/develop terraform/terraform-tests - url: https://api.scaleway.com/secret-manager/v1beta1/regions/fr-par/secrets/112b8309-7612-4953-91f6-c7a926b87a2a/versions?page=1 - method: GET - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - transfer_encoding: [] - trailer: {} - content_length: 31 - uncompressed: false - body: '{"total_count":0,"versions":[]}' - headers: - Content-Length: - - "31" - Content-Security-Policy: - - default-src 'none'; frame-ancestors 'none' - Content-Type: - - application/json - Date: - - Fri, 05 Sep 2025 15:46:56 GMT - Server: - - Scaleway API Gateway (fr-par-3;edge02) - Strict-Transport-Security: - - max-age=63072000 - X-Content-Type-Options: - - nosniff - X-Frame-Options: - - DENY - X-Request-Id: - - 0e121c14-ccbc-4993-bc16-1020335d0eb9 - status: 200 OK - code: 200 - duration: 89.555791ms - - id: 21 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - transfer_encoding: [] - trailer: {} - host: api.scaleway.com - remote_addr: "" - request_uri: "" - body: "" - form: {} - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.4; darwin; arm64) terraform-provider/develop terraform/terraform-tests - url: https://api.scaleway.com/secret-manager/v1beta1/regions/fr-par/secrets/112b8309-7612-4953-91f6-c7a926b87a2a - method: GET - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - transfer_encoding: [] - trailer: {} - content_length: 471 - uncompressed: false - body: '{"created_at":"2025-09-05T15:46:54.943096Z","deletion_requested_at":null,"description":"DataSourceSecret test description","ephemeral_policy":null,"id":"112b8309-7612-4953-91f6-c7a926b87a2a","key_id":null,"managed":false,"name":"scalewayDataSourceSecret","path":"/","project_id":"1ed5e80d-f8dc-4d20-be90-44f4b6b7186d","protected":false,"region":"fr-par","status":"ready","tags":[],"type":"opaque","updated_at":"2025-09-05T15:46:54.943096Z","used_by":[],"version_count":0}' - headers: - Content-Length: - - "471" - Content-Security-Policy: - - default-src 'none'; frame-ancestors 'none' - Content-Type: - - application/json - Date: - - Fri, 05 Sep 2025 15:46:56 GMT - Server: - - Scaleway API Gateway (fr-par-3;edge02) - Strict-Transport-Security: - - max-age=63072000 - X-Content-Type-Options: - - nosniff - X-Frame-Options: - - DENY - X-Request-Id: - - 1772aa0a-f8d6-4587-9c0e-7950e09faf17 - status: 200 OK - code: 200 - duration: 55.286084ms - - id: 22 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - transfer_encoding: [] - trailer: {} - host: api.scaleway.com - remote_addr: "" - request_uri: "" - body: "" - form: {} - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.4; darwin; arm64) terraform-provider/develop terraform/terraform-tests - url: https://api.scaleway.com/secret-manager/v1beta1/regions/fr-par/secrets?name=scalewayDataSourceSecret&order_by=name_asc&organization_id=564aa517-68b0-4fd7-8c8c-d21c4bcdcbd5&project_id=1ed5e80d-f8dc-4d20-be90-44f4b6b7186d&scheduled_for_deletion=false&type=unknown_type - method: GET - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - transfer_encoding: [] - trailer: {} - content_length: 501 - uncompressed: false - body: '{"secrets":[{"created_at":"2025-09-05T15:46:54.943096Z","deletion_requested_at":null,"description":"DataSourceSecret test description","ephemeral_policy":null,"id":"112b8309-7612-4953-91f6-c7a926b87a2a","key_id":null,"managed":false,"name":"scalewayDataSourceSecret","path":"/","project_id":"1ed5e80d-f8dc-4d20-be90-44f4b6b7186d","protected":false,"region":"fr-par","status":"ready","tags":[],"type":"opaque","updated_at":"2025-09-05T15:46:54.943096Z","used_by":[],"version_count":0}],"total_count":1}' - headers: - Content-Length: - - "501" - Content-Security-Policy: - - default-src 'none'; frame-ancestors 'none' - Content-Type: - - application/json - Date: - - Fri, 05 Sep 2025 15:46:56 GMT - Server: - - Scaleway API Gateway (fr-par-3;edge02) - Strict-Transport-Security: - - max-age=63072000 - X-Content-Type-Options: - - nosniff - X-Frame-Options: - - DENY - X-Request-Id: - - ed130ae8-ba40-4875-a8ab-05c4d00b1355 - status: 200 OK - code: 200 - duration: 61.229583ms - - id: 23 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - transfer_encoding: [] - trailer: {} - host: api.scaleway.com - remote_addr: "" - request_uri: "" - body: "" - form: {} - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.4; darwin; arm64) terraform-provider/develop terraform/terraform-tests - url: https://api.scaleway.com/secret-manager/v1beta1/regions/fr-par/secrets/112b8309-7612-4953-91f6-c7a926b87a2a/versions?page=1 - method: GET - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - transfer_encoding: [] - trailer: {} - content_length: 31 - uncompressed: false - body: '{"total_count":0,"versions":[]}' - headers: - Content-Length: - - "31" - Content-Security-Policy: - - default-src 'none'; frame-ancestors 'none' - Content-Type: - - application/json - Date: - - Fri, 05 Sep 2025 15:46:56 GMT - Server: - - Scaleway API Gateway (fr-par-3;edge02) - Strict-Transport-Security: - - max-age=63072000 - X-Content-Type-Options: - - nosniff - X-Frame-Options: - - DENY - X-Request-Id: - - ee3a1be7-cc28-44ab-b58d-46b1648cb56e - status: 200 OK - code: 200 - duration: 59.282209ms - - id: 24 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - transfer_encoding: [] - trailer: {} - host: api.scaleway.com - remote_addr: "" - request_uri: "" - body: "" - form: {} - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.4; darwin; arm64) terraform-provider/develop terraform/terraform-tests - url: https://api.scaleway.com/secret-manager/v1beta1/regions/fr-par/secrets/112b8309-7612-4953-91f6-c7a926b87a2a - method: GET - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - transfer_encoding: [] - trailer: {} - content_length: 471 - uncompressed: false - body: '{"created_at":"2025-09-05T15:46:54.943096Z","deletion_requested_at":null,"description":"DataSourceSecret test description","ephemeral_policy":null,"id":"112b8309-7612-4953-91f6-c7a926b87a2a","key_id":null,"managed":false,"name":"scalewayDataSourceSecret","path":"/","project_id":"1ed5e80d-f8dc-4d20-be90-44f4b6b7186d","protected":false,"region":"fr-par","status":"ready","tags":[],"type":"opaque","updated_at":"2025-09-05T15:46:54.943096Z","used_by":[],"version_count":0}' - headers: - Content-Length: - - "471" - Content-Security-Policy: - - default-src 'none'; frame-ancestors 'none' - Content-Type: - - application/json - Date: - - Fri, 05 Sep 2025 15:46:56 GMT - Server: - - Scaleway API Gateway (fr-par-3;edge02) - Strict-Transport-Security: - - max-age=63072000 - X-Content-Type-Options: - - nosniff - X-Frame-Options: - - DENY - X-Request-Id: - - 9596dfc7-98ea-4a87-9ff9-42438d31a9af - status: 200 OK - code: 200 - duration: 55.308166ms - - id: 25 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - transfer_encoding: [] - trailer: {} - host: api.scaleway.com - remote_addr: "" - request_uri: "" - body: "" - form: {} - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.4; darwin; arm64) terraform-provider/develop terraform/terraform-tests - url: https://api.scaleway.com/secret-manager/v1beta1/regions/fr-par/secrets/112b8309-7612-4953-91f6-c7a926b87a2a/versions?page=1 - method: GET - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - transfer_encoding: [] - trailer: {} - content_length: 31 - uncompressed: false - body: '{"total_count":0,"versions":[]}' - headers: - Content-Length: - - "31" - Content-Security-Policy: - - default-src 'none'; frame-ancestors 'none' - Content-Type: - - application/json - Date: - - Fri, 05 Sep 2025 15:46:56 GMT - Server: - - Scaleway API Gateway (fr-par-3;edge02) - Strict-Transport-Security: - - max-age=63072000 - X-Content-Type-Options: - - nosniff - X-Frame-Options: - - DENY - X-Request-Id: - - 793afd89-596b-420c-a4f7-c72ab713e590 - status: 200 OK - code: 200 - duration: 63.119ms - - id: 26 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - transfer_encoding: [] - trailer: {} - host: api.scaleway.com - remote_addr: "" - request_uri: "" - body: "" - form: {} - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.4; darwin; arm64) terraform-provider/develop terraform/terraform-tests - url: https://api.scaleway.com/secret-manager/v1beta1/regions/fr-par/secrets/112b8309-7612-4953-91f6-c7a926b87a2a - method: DELETE - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - transfer_encoding: [] - trailer: {} - content_length: 0 - uncompressed: false - body: "" - headers: - Content-Security-Policy: - - default-src 'none'; frame-ancestors 'none' - Content-Type: - - application/json - Date: - - Fri, 05 Sep 2025 15:46:56 GMT - Server: - - Scaleway API Gateway (fr-par-3;edge02) - Strict-Transport-Security: - - max-age=63072000 - X-Content-Type-Options: - - nosniff - X-Frame-Options: - - DENY - X-Request-Id: - - 65ce0533-c36e-4724-87ae-57894be0553a - status: 204 No Content - code: 204 - duration: 99.388ms - - id: 27 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - transfer_encoding: [] - trailer: {} - host: api.scaleway.com - remote_addr: "" - request_uri: "" - body: "" - form: {} - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.4; darwin; arm64) terraform-provider/develop terraform/terraform-tests - url: https://api.scaleway.com/iam/v1alpha1/api-keys/SCWZQ1N8VGXQP2Z6CC8V - method: DELETE - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - transfer_encoding: [] - trailer: {} - content_length: 0 - uncompressed: false - body: "" - headers: - Content-Security-Policy: - - default-src 'none'; frame-ancestors 'none' - Content-Type: - - application/json - Date: - - Fri, 05 Sep 2025 15:46:56 GMT - Server: - - Scaleway API Gateway (fr-par-3;edge02) - Strict-Transport-Security: - - max-age=63072000 - X-Content-Type-Options: - - nosniff - X-Frame-Options: - - DENY - X-Request-Id: - - 4e5efd78-cdbd-4589-9032-1afce976ceda - status: 204 No Content - code: 204 - duration: 97.479958ms - - id: 28 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - transfer_encoding: [] - trailer: {} - host: api.scaleway.com - remote_addr: "" - request_uri: "" - body: "" - form: {} - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.4; darwin; arm64) terraform-provider/develop terraform/terraform-tests - url: https://api.scaleway.com/iam/v1alpha1/policies/a50001b5-27ca-494f-8773-8d9bf46dbc95 - method: DELETE - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - transfer_encoding: [] - trailer: {} - content_length: 0 - uncompressed: false - body: "" - headers: - Content-Security-Policy: - - default-src 'none'; frame-ancestors 'none' - Content-Type: - - application/json - Date: - - Fri, 05 Sep 2025 15:46:56 GMT - Server: - - Scaleway API Gateway (fr-par-3;edge02) - Strict-Transport-Security: - - max-age=63072000 - X-Content-Type-Options: - - nosniff - X-Frame-Options: - - DENY - X-Request-Id: - - 303643f7-3514-479e-a217-744dd496756e - status: 204 No Content - code: 204 - duration: 96.45825ms - - id: 29 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - transfer_encoding: [] - trailer: {} - host: api.scaleway.com - remote_addr: "" - request_uri: "" - body: "" - form: {} - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.4; darwin; arm64) terraform-provider/develop terraform/terraform-tests - url: https://api.scaleway.com/iam/v1alpha1/applications/6aac30e2-1842-4822-aced-1d5d171f6c44 - method: DELETE - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - transfer_encoding: [] - trailer: {} - content_length: 0 - uncompressed: false - body: "" - headers: - Content-Security-Policy: - - default-src 'none'; frame-ancestors 'none' - Content-Type: - - application/json - Date: - - Fri, 05 Sep 2025 15:46:56 GMT - Server: - - Scaleway API Gateway (fr-par-3;edge02) - Strict-Transport-Security: - - max-age=63072000 - X-Content-Type-Options: - - nosniff - X-Frame-Options: - - DENY - X-Request-Id: - - 7b3f7f46-e310-42fa-a657-5ead4d4b1e1a - status: 204 No Content - code: 204 - duration: 85.077709ms - - id: 30 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - transfer_encoding: [] - trailer: {} - host: api.scaleway.com - remote_addr: "" - request_uri: "" - body: "" - form: {} - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.4; darwin; arm64) terraform-provider/develop terraform/terraform-tests - url: https://api.scaleway.com/account/v3/projects/1ed5e80d-f8dc-4d20-be90-44f4b6b7186d - method: DELETE - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - transfer_encoding: [] - trailer: {} - content_length: 0 - uncompressed: false - body: "" - headers: - Content-Security-Policy: - - default-src 'none'; frame-ancestors 'none' - Content-Type: - - application/json - Date: - - Fri, 05 Sep 2025 15:46:58 GMT - Server: - - Scaleway API Gateway (fr-par-3;edge02) - Strict-Transport-Security: - - max-age=63072000 - X-Content-Type-Options: - - nosniff - X-Frame-Options: - - DENY - X-Request-Id: - - c9a3b5df-4e1e-4563-804b-9032e42e8414 - status: 204 No Content - code: 204 - duration: 1.435415167s - - id: 31 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - transfer_encoding: [] - trailer: {} - host: api.scaleway.com - remote_addr: "" - request_uri: "" - body: "" - form: {} - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.4; darwin; arm64) terraform-provider/develop terraform/terraform-tests - url: https://api.scaleway.com/secret-manager/v1beta1/regions/fr-par/secrets/112b8309-7612-4953-91f6-c7a926b87a2a - method: GET - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - transfer_encoding: [] - trailer: {} - content_length: 127 - uncompressed: false - body: '{"message":"resource is not found","resource":"secret","resource_id":"112b8309-7612-4953-91f6-c7a926b87a2a","type":"not_found"}' - headers: - Content-Length: - - "127" - Content-Security-Policy: - - default-src 'none'; frame-ancestors 'none' - Content-Type: - - application/json - Date: - - Fri, 05 Sep 2025 15:46:58 GMT - Server: - - Scaleway API Gateway (fr-par-3;edge02) - Strict-Transport-Security: - - max-age=63072000 - X-Content-Type-Options: - - nosniff - X-Frame-Options: - - DENY - X-Request-Id: - - 9e2ea5ba-a110-441b-9ade-c122c67c1313 - status: 404 Not Found - code: 404 - duration: 85.655875ms - - id: 32 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - transfer_encoding: [] - trailer: {} - host: api.scaleway.com - remote_addr: "" - request_uri: "" - body: "" - form: {} - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.4; darwin; arm64) terraform-provider/develop terraform/terraform-tests - url: https://api.scaleway.com/secret-manager/v1beta1/regions/fr-par/secrets/112b8309-7612-4953-91f6-c7a926b87a2a - method: GET - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - transfer_encoding: [] - trailer: {} - content_length: 127 - uncompressed: false - body: '{"message":"resource is not found","resource":"secret","resource_id":"112b8309-7612-4953-91f6-c7a926b87a2a","type":"not_found"}' - headers: - Content-Length: - - "127" - Content-Security-Policy: - - default-src 'none'; frame-ancestors 'none' - Content-Type: - - application/json - Date: - - Fri, 05 Sep 2025 15:46:58 GMT - Server: - - Scaleway API Gateway (fr-par-3;edge02) - Strict-Transport-Security: - - max-age=63072000 - X-Content-Type-Options: - - nosniff - X-Frame-Options: - - DENY - X-Request-Id: - - 71965b32-c917-426e-9f2d-581f83e32abf - status: 404 Not Found - code: 404 - duration: 82.439875ms - - id: 33 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - transfer_encoding: [] - trailer: {} - host: api.scaleway.com - remote_addr: "" - request_uri: "" - body: "" - form: {} - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.4; darwin; arm64) terraform-provider/develop terraform/terraform-tests - url: https://api.scaleway.com/secret-manager/v1beta1/regions/fr-par/secrets/112b8309-7612-4953-91f6-c7a926b87a2a - method: GET - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - transfer_encoding: [] - trailer: {} - content_length: 127 - uncompressed: false - body: '{"message":"resource is not found","resource":"secret","resource_id":"112b8309-7612-4953-91f6-c7a926b87a2a","type":"not_found"}' - headers: - Content-Length: - - "127" - Content-Security-Policy: - - default-src 'none'; frame-ancestors 'none' - Content-Type: - - application/json - Date: - - Fri, 05 Sep 2025 15:46:58 GMT - Server: - - Scaleway API Gateway (fr-par-3;edge02) - Strict-Transport-Security: - - max-age=63072000 - X-Content-Type-Options: - - nosniff - X-Frame-Options: - - DENY - X-Request-Id: - - 0f65bdc7-b0e0-45fe-92b6-d55785100f75 - status: 404 Not Found - code: 404 - duration: 85.462583ms + duration: 331.994125ms diff --git a/internal/services/secret/testdata/secret-basic.cassette.yaml b/internal/services/secret/testdata/secret-basic.cassette.yaml index 81cc3537b1..2797c38e00 100644 --- a/internal/services/secret/testdata/secret-basic.cassette.yaml +++ b/internal/services/secret/testdata/secret-basic.cassette.yaml @@ -1,1183 +1,3 @@ --- version: 2 -interactions: - - id: 0 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 201 - transfer_encoding: [] - trailer: {} - host: api.scaleway.com - remote_addr: "" - request_uri: "" - body: '{"project_id":"105bdce1-64c0-48ab-899d-868455867ecf","name":"secretNameBasic","tags":["devtools","provider","terraform"],"description":"secret description","type":"opaque","path":"/","protected":false}' - form: {} - headers: - Content-Type: - - application/json - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; arm64) terraform-provider/develop terraform/terraform-tests - url: https://api.scaleway.com/secret-manager/v1beta1/regions/fr-par/secrets - method: POST - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - transfer_encoding: [] - trailer: {} - content_length: 466 - uncompressed: false - body: '{"created_at":"2025-03-17T13:49:02.257334Z","deletion_requested_at":null,"description":"secret description","ephemeral_policy":null,"id":"1b664f44-93a8-4c81-a09c-9bb40d352eb2","managed":false,"name":"secretNameBasic","path":"/","project_id":"105bdce1-64c0-48ab-899d-868455867ecf","protected":false,"region":"fr-par","status":"ready","tags":["devtools","provider","terraform"],"type":"opaque","updated_at":"2025-03-17T13:49:02.257334Z","used_by":[],"version_count":0}' - headers: - Content-Length: - - "466" - Content-Security-Policy: - - default-src 'none'; frame-ancestors 'none' - Content-Type: - - application/json - Date: - - Mon, 17 Mar 2025 13:49:02 GMT - Server: - - Scaleway API Gateway (fr-par-1;edge03) - Strict-Transport-Security: - - max-age=63072000 - X-Content-Type-Options: - - nosniff - X-Frame-Options: - - DENY - X-Request-Id: - - 340f37e0-3300-4f50-b08d-f4b74c7163f1 - status: 200 OK - code: 200 - duration: 804.549875ms - - id: 1 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - transfer_encoding: [] - trailer: {} - host: api.scaleway.com - remote_addr: "" - request_uri: "" - body: "" - form: {} - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; arm64) terraform-provider/develop terraform/terraform-tests - url: https://api.scaleway.com/secret-manager/v1beta1/regions/fr-par/secrets/1b664f44-93a8-4c81-a09c-9bb40d352eb2 - method: GET - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - transfer_encoding: [] - trailer: {} - content_length: 466 - uncompressed: false - body: '{"created_at":"2025-03-17T13:49:02.257334Z","deletion_requested_at":null,"description":"secret description","ephemeral_policy":null,"id":"1b664f44-93a8-4c81-a09c-9bb40d352eb2","managed":false,"name":"secretNameBasic","path":"/","project_id":"105bdce1-64c0-48ab-899d-868455867ecf","protected":false,"region":"fr-par","status":"ready","tags":["devtools","provider","terraform"],"type":"opaque","updated_at":"2025-03-17T13:49:02.257334Z","used_by":[],"version_count":0}' - headers: - Content-Length: - - "466" - Content-Security-Policy: - - default-src 'none'; frame-ancestors 'none' - Content-Type: - - application/json - Date: - - Mon, 17 Mar 2025 13:49:02 GMT - Server: - - Scaleway API Gateway (fr-par-1;edge03) - Strict-Transport-Security: - - max-age=63072000 - X-Content-Type-Options: - - nosniff - X-Frame-Options: - - DENY - X-Request-Id: - - 34c6131c-92c0-41c1-9a06-3f160cb87a83 - status: 200 OK - code: 200 - duration: 76.466041ms - - id: 2 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - transfer_encoding: [] - trailer: {} - host: api.scaleway.com - remote_addr: "" - request_uri: "" - body: "" - form: {} - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; arm64) terraform-provider/develop terraform/terraform-tests - url: https://api.scaleway.com/secret-manager/v1beta1/regions/fr-par/secrets/1b664f44-93a8-4c81-a09c-9bb40d352eb2/versions?page=1 - method: GET - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - transfer_encoding: [] - trailer: {} - content_length: 31 - uncompressed: false - body: '{"total_count":0,"versions":[]}' - headers: - Content-Length: - - "31" - Content-Security-Policy: - - default-src 'none'; frame-ancestors 'none' - Content-Type: - - application/json - Date: - - Mon, 17 Mar 2025 13:49:02 GMT - Server: - - Scaleway API Gateway (fr-par-1;edge03) - Strict-Transport-Security: - - max-age=63072000 - X-Content-Type-Options: - - nosniff - X-Frame-Options: - - DENY - X-Request-Id: - - 782223c2-9b93-42c5-b1f7-d3e81bcdd56d - status: 200 OK - code: 200 - duration: 32.784625ms - - id: 3 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - transfer_encoding: [] - trailer: {} - host: api.scaleway.com - remote_addr: "" - request_uri: "" - body: "" - form: {} - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; arm64) terraform-provider/develop terraform/terraform-tests - url: https://api.scaleway.com/secret-manager/v1beta1/regions/fr-par/secrets/1b664f44-93a8-4c81-a09c-9bb40d352eb2 - method: GET - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - transfer_encoding: [] - trailer: {} - content_length: 466 - uncompressed: false - body: '{"created_at":"2025-03-17T13:49:02.257334Z","deletion_requested_at":null,"description":"secret description","ephemeral_policy":null,"id":"1b664f44-93a8-4c81-a09c-9bb40d352eb2","managed":false,"name":"secretNameBasic","path":"/","project_id":"105bdce1-64c0-48ab-899d-868455867ecf","protected":false,"region":"fr-par","status":"ready","tags":["devtools","provider","terraform"],"type":"opaque","updated_at":"2025-03-17T13:49:02.257334Z","used_by":[],"version_count":0}' - headers: - Content-Length: - - "466" - Content-Security-Policy: - - default-src 'none'; frame-ancestors 'none' - Content-Type: - - application/json - Date: - - Mon, 17 Mar 2025 13:49:02 GMT - Server: - - Scaleway API Gateway (fr-par-1;edge03) - Strict-Transport-Security: - - max-age=63072000 - X-Content-Type-Options: - - nosniff - X-Frame-Options: - - DENY - X-Request-Id: - - 916485a6-bc77-46a0-9cc1-19a768cc32e4 - status: 200 OK - code: 200 - duration: 97.670959ms - - id: 4 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - transfer_encoding: [] - trailer: {} - host: api.scaleway.com - remote_addr: "" - request_uri: "" - body: "" - form: {} - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; arm64) terraform-provider/develop terraform/terraform-tests - url: https://api.scaleway.com/secret-manager/v1beta1/regions/fr-par/secrets/1b664f44-93a8-4c81-a09c-9bb40d352eb2 - method: GET - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - transfer_encoding: [] - trailer: {} - content_length: 466 - uncompressed: false - body: '{"created_at":"2025-03-17T13:49:02.257334Z","deletion_requested_at":null,"description":"secret description","ephemeral_policy":null,"id":"1b664f44-93a8-4c81-a09c-9bb40d352eb2","managed":false,"name":"secretNameBasic","path":"/","project_id":"105bdce1-64c0-48ab-899d-868455867ecf","protected":false,"region":"fr-par","status":"ready","tags":["devtools","provider","terraform"],"type":"opaque","updated_at":"2025-03-17T13:49:02.257334Z","used_by":[],"version_count":0}' - headers: - Content-Length: - - "466" - Content-Security-Policy: - - default-src 'none'; frame-ancestors 'none' - Content-Type: - - application/json - Date: - - Mon, 17 Mar 2025 13:49:03 GMT - Server: - - Scaleway API Gateway (fr-par-1;edge03) - Strict-Transport-Security: - - max-age=63072000 - X-Content-Type-Options: - - nosniff - X-Frame-Options: - - DENY - X-Request-Id: - - d2696e5b-b3ee-4097-ba4a-149e5fa7bb57 - status: 200 OK - code: 200 - duration: 33.678666ms - - id: 5 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - transfer_encoding: [] - trailer: {} - host: api.scaleway.com - remote_addr: "" - request_uri: "" - body: "" - form: {} - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; arm64) terraform-provider/develop terraform/terraform-tests - url: https://api.scaleway.com/secret-manager/v1beta1/regions/fr-par/secrets/1b664f44-93a8-4c81-a09c-9bb40d352eb2/versions?page=1 - method: GET - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - transfer_encoding: [] - trailer: {} - content_length: 31 - uncompressed: false - body: '{"total_count":0,"versions":[]}' - headers: - Content-Length: - - "31" - Content-Security-Policy: - - default-src 'none'; frame-ancestors 'none' - Content-Type: - - application/json - Date: - - Mon, 17 Mar 2025 13:49:03 GMT - Server: - - Scaleway API Gateway (fr-par-1;edge03) - Strict-Transport-Security: - - max-age=63072000 - X-Content-Type-Options: - - nosniff - X-Frame-Options: - - DENY - X-Request-Id: - - 53c53c6e-90eb-4418-9b86-5ab43db7c5e9 - status: 200 OK - code: 200 - duration: 80.376541ms - - id: 6 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - transfer_encoding: [] - trailer: {} - host: api.scaleway.com - remote_addr: "" - request_uri: "" - body: "" - form: {} - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; arm64) terraform-provider/develop terraform/terraform-tests - url: https://api.scaleway.com/secret-manager/v1beta1/regions/fr-par/secrets/1b664f44-93a8-4c81-a09c-9bb40d352eb2 - method: GET - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - transfer_encoding: [] - trailer: {} - content_length: 466 - uncompressed: false - body: '{"created_at":"2025-03-17T13:49:02.257334Z","deletion_requested_at":null,"description":"secret description","ephemeral_policy":null,"id":"1b664f44-93a8-4c81-a09c-9bb40d352eb2","managed":false,"name":"secretNameBasic","path":"/","project_id":"105bdce1-64c0-48ab-899d-868455867ecf","protected":false,"region":"fr-par","status":"ready","tags":["devtools","provider","terraform"],"type":"opaque","updated_at":"2025-03-17T13:49:02.257334Z","used_by":[],"version_count":0}' - headers: - Content-Length: - - "466" - Content-Security-Policy: - - default-src 'none'; frame-ancestors 'none' - Content-Type: - - application/json - Date: - - Mon, 17 Mar 2025 13:49:04 GMT - Server: - - Scaleway API Gateway (fr-par-1;edge03) - Strict-Transport-Security: - - max-age=63072000 - X-Content-Type-Options: - - nosniff - X-Frame-Options: - - DENY - X-Request-Id: - - 8492388d-ae75-4137-b877-8ec86a6a884e - status: 200 OK - code: 200 - duration: 86.04925ms - - id: 7 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - transfer_encoding: [] - trailer: {} - host: api.scaleway.com - remote_addr: "" - request_uri: "" - body: "" - form: {} - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; arm64) terraform-provider/develop terraform/terraform-tests - url: https://api.scaleway.com/secret-manager/v1beta1/regions/fr-par/secrets/1b664f44-93a8-4c81-a09c-9bb40d352eb2/versions?page=1 - method: GET - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - transfer_encoding: [] - trailer: {} - content_length: 31 - uncompressed: false - body: '{"total_count":0,"versions":[]}' - headers: - Content-Length: - - "31" - Content-Security-Policy: - - default-src 'none'; frame-ancestors 'none' - Content-Type: - - application/json - Date: - - Mon, 17 Mar 2025 13:49:04 GMT - Server: - - Scaleway API Gateway (fr-par-1;edge03) - Strict-Transport-Security: - - max-age=63072000 - X-Content-Type-Options: - - nosniff - X-Frame-Options: - - DENY - X-Request-Id: - - 7086ea3d-39d7-4636-96e4-156cb66739f9 - status: 200 OK - code: 200 - duration: 25.569042ms - - id: 8 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 88 - transfer_encoding: [] - trailer: {} - host: api.scaleway.com - remote_addr: "" - request_uri: "" - body: '{"name":"secretNameBasicUpdated","tags":["devtools"],"description":"update description"}' - form: {} - headers: - Content-Type: - - application/json - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; arm64) terraform-provider/develop terraform/terraform-tests - url: https://api.scaleway.com/secret-manager/v1beta1/regions/fr-par/secrets/1b664f44-93a8-4c81-a09c-9bb40d352eb2 - method: PATCH - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - transfer_encoding: [] - trailer: {} - content_length: 450 - uncompressed: false - body: '{"created_at":"2025-03-17T13:49:02.257334Z","deletion_requested_at":null,"description":"update description","ephemeral_policy":null,"id":"1b664f44-93a8-4c81-a09c-9bb40d352eb2","managed":false,"name":"secretNameBasicUpdated","path":"/","project_id":"105bdce1-64c0-48ab-899d-868455867ecf","protected":false,"region":"fr-par","status":"ready","tags":["devtools"],"type":"opaque","updated_at":"2025-03-17T13:49:05.190489Z","used_by":[],"version_count":0}' - headers: - Content-Length: - - "450" - Content-Security-Policy: - - default-src 'none'; frame-ancestors 'none' - Content-Type: - - application/json - Date: - - Mon, 17 Mar 2025 13:49:05 GMT - Server: - - Scaleway API Gateway (fr-par-1;edge03) - Strict-Transport-Security: - - max-age=63072000 - X-Content-Type-Options: - - nosniff - X-Frame-Options: - - DENY - X-Request-Id: - - de7d3f7b-eb0a-4315-a393-242c196080bb - status: 200 OK - code: 200 - duration: 114.82575ms - - id: 9 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - transfer_encoding: [] - trailer: {} - host: api.scaleway.com - remote_addr: "" - request_uri: "" - body: "" - form: {} - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; arm64) terraform-provider/develop terraform/terraform-tests - url: https://api.scaleway.com/secret-manager/v1beta1/regions/fr-par/secrets/1b664f44-93a8-4c81-a09c-9bb40d352eb2 - method: GET - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - transfer_encoding: [] - trailer: {} - content_length: 450 - uncompressed: false - body: '{"created_at":"2025-03-17T13:49:02.257334Z","deletion_requested_at":null,"description":"update description","ephemeral_policy":null,"id":"1b664f44-93a8-4c81-a09c-9bb40d352eb2","managed":false,"name":"secretNameBasicUpdated","path":"/","project_id":"105bdce1-64c0-48ab-899d-868455867ecf","protected":false,"region":"fr-par","status":"ready","tags":["devtools"],"type":"opaque","updated_at":"2025-03-17T13:49:05.190489Z","used_by":[],"version_count":0}' - headers: - Content-Length: - - "450" - Content-Security-Policy: - - default-src 'none'; frame-ancestors 'none' - Content-Type: - - application/json - Date: - - Mon, 17 Mar 2025 13:49:05 GMT - Server: - - Scaleway API Gateway (fr-par-1;edge03) - Strict-Transport-Security: - - max-age=63072000 - X-Content-Type-Options: - - nosniff - X-Frame-Options: - - DENY - X-Request-Id: - - cc1000a7-2ba0-47e9-8188-7c2a9648100e - status: 200 OK - code: 200 - duration: 80.463708ms - - id: 10 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - transfer_encoding: [] - trailer: {} - host: api.scaleway.com - remote_addr: "" - request_uri: "" - body: "" - form: {} - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; arm64) terraform-provider/develop terraform/terraform-tests - url: https://api.scaleway.com/secret-manager/v1beta1/regions/fr-par/secrets/1b664f44-93a8-4c81-a09c-9bb40d352eb2/versions?page=1 - method: GET - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - transfer_encoding: [] - trailer: {} - content_length: 31 - uncompressed: false - body: '{"total_count":0,"versions":[]}' - headers: - Content-Length: - - "31" - Content-Security-Policy: - - default-src 'none'; frame-ancestors 'none' - Content-Type: - - application/json - Date: - - Mon, 17 Mar 2025 13:49:05 GMT - Server: - - Scaleway API Gateway (fr-par-1;edge03) - Strict-Transport-Security: - - max-age=63072000 - X-Content-Type-Options: - - nosniff - X-Frame-Options: - - DENY - X-Request-Id: - - 441a0479-d961-4a6c-a5b2-e2aa2fcca313 - status: 200 OK - code: 200 - duration: 72.798ms - - id: 11 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - transfer_encoding: [] - trailer: {} - host: api.scaleway.com - remote_addr: "" - request_uri: "" - body: "" - form: {} - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; arm64) terraform-provider/develop terraform/terraform-tests - url: https://api.scaleway.com/secret-manager/v1beta1/regions/fr-par/secrets/1b664f44-93a8-4c81-a09c-9bb40d352eb2 - method: GET - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - transfer_encoding: [] - trailer: {} - content_length: 450 - uncompressed: false - body: '{"created_at":"2025-03-17T13:49:02.257334Z","deletion_requested_at":null,"description":"update description","ephemeral_policy":null,"id":"1b664f44-93a8-4c81-a09c-9bb40d352eb2","managed":false,"name":"secretNameBasicUpdated","path":"/","project_id":"105bdce1-64c0-48ab-899d-868455867ecf","protected":false,"region":"fr-par","status":"ready","tags":["devtools"],"type":"opaque","updated_at":"2025-03-17T13:49:05.190489Z","used_by":[],"version_count":0}' - headers: - Content-Length: - - "450" - Content-Security-Policy: - - default-src 'none'; frame-ancestors 'none' - Content-Type: - - application/json - Date: - - Mon, 17 Mar 2025 13:49:05 GMT - Server: - - Scaleway API Gateway (fr-par-1;edge03) - Strict-Transport-Security: - - max-age=63072000 - X-Content-Type-Options: - - nosniff - X-Frame-Options: - - DENY - X-Request-Id: - - c209aca5-c0b9-4467-a7b2-d9fbd9d84241 - status: 200 OK - code: 200 - duration: 28.005208ms - - id: 12 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - transfer_encoding: [] - trailer: {} - host: api.scaleway.com - remote_addr: "" - request_uri: "" - body: "" - form: {} - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; arm64) terraform-provider/develop terraform/terraform-tests - url: https://api.scaleway.com/secret-manager/v1beta1/regions/fr-par/secrets/1b664f44-93a8-4c81-a09c-9bb40d352eb2 - method: GET - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - transfer_encoding: [] - trailer: {} - content_length: 450 - uncompressed: false - body: '{"created_at":"2025-03-17T13:49:02.257334Z","deletion_requested_at":null,"description":"update description","ephemeral_policy":null,"id":"1b664f44-93a8-4c81-a09c-9bb40d352eb2","managed":false,"name":"secretNameBasicUpdated","path":"/","project_id":"105bdce1-64c0-48ab-899d-868455867ecf","protected":false,"region":"fr-par","status":"ready","tags":["devtools"],"type":"opaque","updated_at":"2025-03-17T13:49:05.190489Z","used_by":[],"version_count":0}' - headers: - Content-Length: - - "450" - Content-Security-Policy: - - default-src 'none'; frame-ancestors 'none' - Content-Type: - - application/json - Date: - - Mon, 17 Mar 2025 13:49:06 GMT - Server: - - Scaleway API Gateway (fr-par-1;edge03) - Strict-Transport-Security: - - max-age=63072000 - X-Content-Type-Options: - - nosniff - X-Frame-Options: - - DENY - X-Request-Id: - - 65d118f2-c28e-4c43-acc3-1dda8980dbe3 - status: 200 OK - code: 200 - duration: 85.147375ms - - id: 13 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - transfer_encoding: [] - trailer: {} - host: api.scaleway.com - remote_addr: "" - request_uri: "" - body: "" - form: {} - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; arm64) terraform-provider/develop terraform/terraform-tests - url: https://api.scaleway.com/secret-manager/v1beta1/regions/fr-par/secrets/1b664f44-93a8-4c81-a09c-9bb40d352eb2/versions?page=1 - method: GET - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - transfer_encoding: [] - trailer: {} - content_length: 31 - uncompressed: false - body: '{"total_count":0,"versions":[]}' - headers: - Content-Length: - - "31" - Content-Security-Policy: - - default-src 'none'; frame-ancestors 'none' - Content-Type: - - application/json - Date: - - Mon, 17 Mar 2025 13:49:06 GMT - Server: - - Scaleway API Gateway (fr-par-1;edge03) - Strict-Transport-Security: - - max-age=63072000 - X-Content-Type-Options: - - nosniff - X-Frame-Options: - - DENY - X-Request-Id: - - d0aaf1e0-d79c-43cb-8c63-240ce74fe257 - status: 200 OK - code: 200 - duration: 83.095292ms - - id: 14 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - transfer_encoding: [] - trailer: {} - host: api.scaleway.com - remote_addr: "" - request_uri: "" - body: "" - form: {} - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; arm64) terraform-provider/develop terraform/terraform-tests - url: https://api.scaleway.com/secret-manager/v1beta1/regions/fr-par/secrets/1b664f44-93a8-4c81-a09c-9bb40d352eb2 - method: GET - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - transfer_encoding: [] - trailer: {} - content_length: 450 - uncompressed: false - body: '{"created_at":"2025-03-17T13:49:02.257334Z","deletion_requested_at":null,"description":"update description","ephemeral_policy":null,"id":"1b664f44-93a8-4c81-a09c-9bb40d352eb2","managed":false,"name":"secretNameBasicUpdated","path":"/","project_id":"105bdce1-64c0-48ab-899d-868455867ecf","protected":false,"region":"fr-par","status":"ready","tags":["devtools"],"type":"opaque","updated_at":"2025-03-17T13:49:05.190489Z","used_by":[],"version_count":0}' - headers: - Content-Length: - - "450" - Content-Security-Policy: - - default-src 'none'; frame-ancestors 'none' - Content-Type: - - application/json - Date: - - Mon, 17 Mar 2025 13:49:07 GMT - Server: - - Scaleway API Gateway (fr-par-1;edge03) - Strict-Transport-Security: - - max-age=63072000 - X-Content-Type-Options: - - nosniff - X-Frame-Options: - - DENY - X-Request-Id: - - 668479ad-de89-4e13-9430-da4dc8b646cf - status: 200 OK - code: 200 - duration: 85.31075ms - - id: 15 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - transfer_encoding: [] - trailer: {} - host: api.scaleway.com - remote_addr: "" - request_uri: "" - body: "" - form: {} - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; arm64) terraform-provider/develop terraform/terraform-tests - url: https://api.scaleway.com/secret-manager/v1beta1/regions/fr-par/secrets/1b664f44-93a8-4c81-a09c-9bb40d352eb2/versions?page=1 - method: GET - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - transfer_encoding: [] - trailer: {} - content_length: 31 - uncompressed: false - body: '{"total_count":0,"versions":[]}' - headers: - Content-Length: - - "31" - Content-Security-Policy: - - default-src 'none'; frame-ancestors 'none' - Content-Type: - - application/json - Date: - - Mon, 17 Mar 2025 13:49:07 GMT - Server: - - Scaleway API Gateway (fr-par-1;edge03) - Strict-Transport-Security: - - max-age=63072000 - X-Content-Type-Options: - - nosniff - X-Frame-Options: - - DENY - X-Request-Id: - - 05f0b292-0904-474b-bb26-68ed9f628798 - status: 200 OK - code: 200 - duration: 24.995291ms - - id: 16 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 53 - transfer_encoding: [] - trailer: {} - host: api.scaleway.com - remote_addr: "" - request_uri: "" - body: '{"name":"secretNameBasic","tags":[],"description":""}' - form: {} - headers: - Content-Type: - - application/json - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; arm64) terraform-provider/develop terraform/terraform-tests - url: https://api.scaleway.com/secret-manager/v1beta1/regions/fr-par/secrets/1b664f44-93a8-4c81-a09c-9bb40d352eb2 - method: PATCH - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - transfer_encoding: [] - trailer: {} - content_length: 415 - uncompressed: false - body: '{"created_at":"2025-03-17T13:49:02.257334Z","deletion_requested_at":null,"description":"","ephemeral_policy":null,"id":"1b664f44-93a8-4c81-a09c-9bb40d352eb2","managed":false,"name":"secretNameBasic","path":"/","project_id":"105bdce1-64c0-48ab-899d-868455867ecf","protected":false,"region":"fr-par","status":"ready","tags":[],"type":"opaque","updated_at":"2025-03-17T13:49:08.330346Z","used_by":[],"version_count":0}' - headers: - Content-Length: - - "415" - Content-Security-Policy: - - default-src 'none'; frame-ancestors 'none' - Content-Type: - - application/json - Date: - - Mon, 17 Mar 2025 13:49:08 GMT - Server: - - Scaleway API Gateway (fr-par-1;edge03) - Strict-Transport-Security: - - max-age=63072000 - X-Content-Type-Options: - - nosniff - X-Frame-Options: - - DENY - X-Request-Id: - - 4decc20f-4ab5-4402-a919-1d7037d1a4f2 - status: 200 OK - code: 200 - duration: 103.969625ms - - id: 17 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - transfer_encoding: [] - trailer: {} - host: api.scaleway.com - remote_addr: "" - request_uri: "" - body: "" - form: {} - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; arm64) terraform-provider/develop terraform/terraform-tests - url: https://api.scaleway.com/secret-manager/v1beta1/regions/fr-par/secrets/1b664f44-93a8-4c81-a09c-9bb40d352eb2 - method: GET - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - transfer_encoding: [] - trailer: {} - content_length: 415 - uncompressed: false - body: '{"created_at":"2025-03-17T13:49:02.257334Z","deletion_requested_at":null,"description":"","ephemeral_policy":null,"id":"1b664f44-93a8-4c81-a09c-9bb40d352eb2","managed":false,"name":"secretNameBasic","path":"/","project_id":"105bdce1-64c0-48ab-899d-868455867ecf","protected":false,"region":"fr-par","status":"ready","tags":[],"type":"opaque","updated_at":"2025-03-17T13:49:08.330346Z","used_by":[],"version_count":0}' - headers: - Content-Length: - - "415" - Content-Security-Policy: - - default-src 'none'; frame-ancestors 'none' - Content-Type: - - application/json - Date: - - Mon, 17 Mar 2025 13:49:08 GMT - Server: - - Scaleway API Gateway (fr-par-1;edge03) - Strict-Transport-Security: - - max-age=63072000 - X-Content-Type-Options: - - nosniff - X-Frame-Options: - - DENY - X-Request-Id: - - 1e55da4b-126e-42d5-b5a6-5513d195e2d1 - status: 200 OK - code: 200 - duration: 75.854084ms - - id: 18 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - transfer_encoding: [] - trailer: {} - host: api.scaleway.com - remote_addr: "" - request_uri: "" - body: "" - form: {} - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; arm64) terraform-provider/develop terraform/terraform-tests - url: https://api.scaleway.com/secret-manager/v1beta1/regions/fr-par/secrets/1b664f44-93a8-4c81-a09c-9bb40d352eb2/versions?page=1 - method: GET - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - transfer_encoding: [] - trailer: {} - content_length: 31 - uncompressed: false - body: '{"total_count":0,"versions":[]}' - headers: - Content-Length: - - "31" - Content-Security-Policy: - - default-src 'none'; frame-ancestors 'none' - Content-Type: - - application/json - Date: - - Mon, 17 Mar 2025 13:49:08 GMT - Server: - - Scaleway API Gateway (fr-par-1;edge03) - Strict-Transport-Security: - - max-age=63072000 - X-Content-Type-Options: - - nosniff - X-Frame-Options: - - DENY - X-Request-Id: - - bb9440cd-4028-45b2-8c13-198a8bffa538 - status: 200 OK - code: 200 - duration: 24.410458ms - - id: 19 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - transfer_encoding: [] - trailer: {} - host: api.scaleway.com - remote_addr: "" - request_uri: "" - body: "" - form: {} - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; arm64) terraform-provider/develop terraform/terraform-tests - url: https://api.scaleway.com/secret-manager/v1beta1/regions/fr-par/secrets/1b664f44-93a8-4c81-a09c-9bb40d352eb2 - method: GET - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - transfer_encoding: [] - trailer: {} - content_length: 415 - uncompressed: false - body: '{"created_at":"2025-03-17T13:49:02.257334Z","deletion_requested_at":null,"description":"","ephemeral_policy":null,"id":"1b664f44-93a8-4c81-a09c-9bb40d352eb2","managed":false,"name":"secretNameBasic","path":"/","project_id":"105bdce1-64c0-48ab-899d-868455867ecf","protected":false,"region":"fr-par","status":"ready","tags":[],"type":"opaque","updated_at":"2025-03-17T13:49:08.330346Z","used_by":[],"version_count":0}' - headers: - Content-Length: - - "415" - Content-Security-Policy: - - default-src 'none'; frame-ancestors 'none' - Content-Type: - - application/json - Date: - - Mon, 17 Mar 2025 13:49:08 GMT - Server: - - Scaleway API Gateway (fr-par-1;edge03) - Strict-Transport-Security: - - max-age=63072000 - X-Content-Type-Options: - - nosniff - X-Frame-Options: - - DENY - X-Request-Id: - - e88bcbe8-f5b7-4f91-8152-1b584f06a5b1 - status: 200 OK - code: 200 - duration: 76.024709ms - - id: 20 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - transfer_encoding: [] - trailer: {} - host: api.scaleway.com - remote_addr: "" - request_uri: "" - body: "" - form: {} - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; arm64) terraform-provider/develop terraform/terraform-tests - url: https://api.scaleway.com/secret-manager/v1beta1/regions/fr-par/secrets/1b664f44-93a8-4c81-a09c-9bb40d352eb2 - method: GET - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - transfer_encoding: [] - trailer: {} - content_length: 415 - uncompressed: false - body: '{"created_at":"2025-03-17T13:49:02.257334Z","deletion_requested_at":null,"description":"","ephemeral_policy":null,"id":"1b664f44-93a8-4c81-a09c-9bb40d352eb2","managed":false,"name":"secretNameBasic","path":"/","project_id":"105bdce1-64c0-48ab-899d-868455867ecf","protected":false,"region":"fr-par","status":"ready","tags":[],"type":"opaque","updated_at":"2025-03-17T13:49:08.330346Z","used_by":[],"version_count":0}' - headers: - Content-Length: - - "415" - Content-Security-Policy: - - default-src 'none'; frame-ancestors 'none' - Content-Type: - - application/json - Date: - - Mon, 17 Mar 2025 13:49:09 GMT - Server: - - Scaleway API Gateway (fr-par-1;edge03) - Strict-Transport-Security: - - max-age=63072000 - X-Content-Type-Options: - - nosniff - X-Frame-Options: - - DENY - X-Request-Id: - - 6691e0de-741f-4b1a-94a3-64a583abc17d - status: 200 OK - code: 200 - duration: 82.599666ms - - id: 21 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - transfer_encoding: [] - trailer: {} - host: api.scaleway.com - remote_addr: "" - request_uri: "" - body: "" - form: {} - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; arm64) terraform-provider/develop terraform/terraform-tests - url: https://api.scaleway.com/secret-manager/v1beta1/regions/fr-par/secrets/1b664f44-93a8-4c81-a09c-9bb40d352eb2/versions?page=1 - method: GET - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - transfer_encoding: [] - trailer: {} - content_length: 31 - uncompressed: false - body: '{"total_count":0,"versions":[]}' - headers: - Content-Length: - - "31" - Content-Security-Policy: - - default-src 'none'; frame-ancestors 'none' - Content-Type: - - application/json - Date: - - Mon, 17 Mar 2025 13:49:09 GMT - Server: - - Scaleway API Gateway (fr-par-1;edge03) - Strict-Transport-Security: - - max-age=63072000 - X-Content-Type-Options: - - nosniff - X-Frame-Options: - - DENY - X-Request-Id: - - 35fc2e8c-ec45-4dd6-ab48-b7fd8d0d2707 - status: 200 OK - code: 200 - duration: 26.234208ms - - id: 22 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - transfer_encoding: [] - trailer: {} - host: api.scaleway.com - remote_addr: "" - request_uri: "" - body: "" - form: {} - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; arm64) terraform-provider/develop terraform/terraform-tests - url: https://api.scaleway.com/secret-manager/v1beta1/regions/fr-par/secrets/1b664f44-93a8-4c81-a09c-9bb40d352eb2 - method: DELETE - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - transfer_encoding: [] - trailer: {} - content_length: 0 - uncompressed: false - body: "" - headers: - Content-Security-Policy: - - default-src 'none'; frame-ancestors 'none' - Content-Type: - - application/json - Date: - - Mon, 17 Mar 2025 13:49:10 GMT - Server: - - Scaleway API Gateway (fr-par-1;edge03) - Strict-Transport-Security: - - max-age=63072000 - X-Content-Type-Options: - - nosniff - X-Frame-Options: - - DENY - X-Request-Id: - - 35ec0cd9-2b12-4cc3-b128-dcbdc3b519a0 - status: 204 No Content - code: 204 - duration: 452.465791ms - - id: 23 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - transfer_encoding: [] - trailer: {} - host: api.scaleway.com - remote_addr: "" - request_uri: "" - body: "" - form: {} - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; arm64) terraform-provider/develop terraform/terraform-tests - url: https://api.scaleway.com/secret-manager/v1beta1/regions/fr-par/secrets/1b664f44-93a8-4c81-a09c-9bb40d352eb2 - method: GET - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - transfer_encoding: [] - trailer: {} - content_length: 127 - uncompressed: false - body: '{"message":"resource is not found","resource":"secret","resource_id":"1b664f44-93a8-4c81-a09c-9bb40d352eb2","type":"not_found"}' - headers: - Content-Length: - - "127" - Content-Security-Policy: - - default-src 'none'; frame-ancestors 'none' - Content-Type: - - application/json - Date: - - Mon, 17 Mar 2025 13:49:10 GMT - Server: - - Scaleway API Gateway (fr-par-1;edge03) - Strict-Transport-Security: - - max-age=63072000 - X-Content-Type-Options: - - nosniff - X-Frame-Options: - - DENY - X-Request-Id: - - 8204471e-5895-4655-b428-109524b5e39f - status: 404 Not Found - code: 404 - duration: 26.854208ms +interactions: [] diff --git a/internal/verify/date.go b/internal/verify/date.go index 61632f4905..61c54b38d3 100644 --- a/internal/verify/date.go +++ b/internal/verify/date.go @@ -1,9 +1,11 @@ package verify import ( + "context" "time" "github.com/hashicorp/go-cty/cty" + "github.com/hashicorp/terraform-plugin-framework/schema/validator" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) @@ -57,3 +59,23 @@ func IsDuration() schema.SchemaValidateDiagFunc { return nil } } + +type DurationValidator struct{} + +func (d DurationValidator) Description(ctx context.Context) string { + return "Check that the string passed is a duration" +} + +func (d DurationValidator) MarkdownDescription(ctx context.Context) string { + return d.Description(ctx) +} + +func (d DurationValidator) ValidateString(ctx context.Context, request validator.StringRequest, response *validator.StringResponse) { + _, err := time.ParseDuration(request.ConfigValue.String()) + if err != nil { + response.Diagnostics.AddError( + "invalid input, expected a valid duration", + err.Error(), + ) + } +} diff --git a/internal/verify/uuid.go b/internal/verify/uuid.go index d5a76bea5e..1a1c546c3e 100644 --- a/internal/verify/uuid.go +++ b/internal/verify/uuid.go @@ -1,7 +1,11 @@ package verify import ( + "context" + "github.com/hashicorp/go-cty/cty" + diagFramework "github.com/hashicorp/terraform-plugin-framework/diag" + "github.com/hashicorp/terraform-plugin-framework/schema/validator" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/scaleway/scaleway-sdk-go/validation" @@ -119,3 +123,40 @@ Then, you can reference the datasource's attributes in your resources.`, return nil } } + +type UUIDValidator struct{} + +func (U UUIDValidator) Description(ctx context.Context) string { + return "Will check that a string is indeed an UUID" +} + +func (U UUIDValidator) MarkdownDescription(ctx context.Context) string { + return U.Description(ctx) +} + +func (U UUIDValidator) ValidateString(ctx context.Context, request validator.StringRequest, response *validator.StringResponse) { + if !validation.IsUUID(request.ConfigValue.String()) { + response.Diagnostics.AddError("is not an uuid", "is not a UUID") + } +} + +// UUIDorUUIDWithLocalityValidator validates the schema is a UUID or the combination of a locality and a UUID +// e.g. "6ba7b810-9dad-11d1-80b4-00c04fd430c8" or "fr-par-1/6ba7b810-9dad-11d1-80b4-00c04fd430c8". +type UUIDorUUIDWithLocalityValidator struct{} + +func (U UUIDorUUIDWithLocalityValidator) Description(ctx context.Context) string { + return "UUIDorUUIDWithLocalityValidator validates the schema is a UUID or the combination of a locality and a UUID" +} + +func (U UUIDorUUIDWithLocalityValidator) MarkdownDescription(ctx context.Context) string { + return U.Description(ctx) +} + +func (U UUIDorUUIDWithLocalityValidator) ValidateString(ctx context.Context, request validator.StringRequest, response *validator.StringResponse) { + if !validation.IsUUID(locality.ExpandID(request.ConfigValue.String())) { + response.Diagnostics.Append(diagFramework.NewErrorDiagnostic( + "invalid UUID: "+request.ConfigValue.String(), + "format should be 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' (36) and contains valid hexadecimal characters", + )) + } +} diff --git a/internal/verify/validation.go b/internal/verify/validation.go index c99550b6ce..679a0e4f3e 100644 --- a/internal/verify/validation.go +++ b/internal/verify/validation.go @@ -1,7 +1,11 @@ package verify import ( + "fmt" + "github.com/hashicorp/go-cty/cty" + "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" + "github.com/hashicorp/terraform-plugin-framework/schema/validator" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" @@ -25,3 +29,18 @@ func ValidateStringInSliceWithWarning(correctValues []string, field string) sche return res } } + +type StructWithValues[T fmt.Stringer] interface { + Values() []T +} + +func ValidatorFromEnum[T fmt.Stringer](enum StructWithValues[T]) validator.String { + enumValues := enum.Values() + + enumStringValues := make([]string, 0, len(enumValues)) + for _, enumValue := range enumValues { + enumStringValues = append(enumStringValues, enumValue.String()) + } + + return stringvalidator.OneOf(enumStringValues...) +} diff --git a/provider/framework.go b/provider/framework.go index c58df6a2cf..72fa4532f7 100644 --- a/provider/framework.go +++ b/provider/framework.go @@ -10,6 +10,7 @@ import ( "github.com/hashicorp/terraform-plugin-framework/provider" "github.com/hashicorp/terraform-plugin-framework/provider/schema" "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/scaleway/terraform-provider-scaleway/v2/internal/services/secret" ) var _ provider.Provider = &ScalewayProvider{} @@ -69,7 +70,9 @@ func (p *ScalewayProvider) Configure(ctx context.Context, req provider.Configure } func (p *ScalewayProvider) Resources(ctx context.Context) []func() resource.Resource { - return []func() resource.Resource{} + return []func() resource.Resource{ + secret.NewResourceSecret, + } } func (p *ScalewayProvider) EphemeralResources(_ context.Context) []func() ephemeral.EphemeralResource { @@ -77,7 +80,9 @@ func (p *ScalewayProvider) EphemeralResources(_ context.Context) []func() epheme } func (p *ScalewayProvider) DataSources(_ context.Context) []func() datasource.DataSource { - return []func() datasource.DataSource{} + return []func() datasource.DataSource{ + secret.NewDataSourceSecret, + } } func (p *ScalewayProvider) Actions(_ context.Context) []func() action.Action { diff --git a/provider/sdkv2.go b/provider/sdkv2.go index 58b9783664..80c2c74d3c 100644 --- a/provider/sdkv2.go +++ b/provider/sdkv2.go @@ -233,7 +233,6 @@ func SDKProvider(config *Config) plugin.ProviderFunc { "scaleway_redis_cluster": redis.ResourceCluster(), "scaleway_registry_namespace": registry.ResourceNamespace(), "scaleway_sdb_sql_database": sdb.ResourceDatabase(), - "scaleway_secret": secret.ResourceSecret(), "scaleway_secret_version": secret.ResourceVersion(), "scaleway_tem_domain": tem.ResourceDomain(), "scaleway_tem_domain_validation": tem.ResourceDomainValidation(), @@ -329,7 +328,6 @@ func SDKProvider(config *Config) plugin.ProviderFunc { "scaleway_registry_image": registry.DataSourceImage(), "scaleway_registry_namespace": registry.DataSourceNamespace(), "scaleway_registry_image_tag": registry.DataSourceImageTag(), - "scaleway_secret": secret.DataSourceSecret(), "scaleway_secret_version": secret.DataSourceVersion(), "scaleway_tem_domain": tem.DataSourceDomain(), "scaleway_tem_offer_subscription": tem.DataSourceOfferSubscription(), From 3e2189001bb4e5dfac56687b7d9588c20252a973 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20L=C3=A9one?= Date: Fri, 10 Oct 2025 15:28:20 +0200 Subject: [PATCH 2/5] go mod tidy --- go.mod | 6 +++--- go.sum | 2 -- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index b8d214aa23..fc780bd070 100644 --- a/go.mod +++ b/go.mod @@ -22,6 +22,9 @@ require ( github.com/hashicorp/go-multierror v1.1.1 github.com/hashicorp/go-retryablehttp v0.7.8 github.com/hashicorp/terraform-plugin-framework v1.16.1 + github.com/hashicorp/terraform-plugin-framework-timeouts v0.6.0 + github.com/hashicorp/terraform-plugin-framework-timetypes v0.5.0 + github.com/hashicorp/terraform-plugin-framework-validators v0.18.0 github.com/hashicorp/terraform-plugin-go v0.29.0 github.com/hashicorp/terraform-plugin-log v0.9.0 github.com/hashicorp/terraform-plugin-mux v0.21.0 @@ -102,9 +105,6 @@ require ( github.com/hashicorp/terraform-exec v0.23.1 // indirect github.com/hashicorp/terraform-json v0.27.1 // indirect github.com/hashicorp/terraform-plugin-docs v0.23.0 // indirect - github.com/hashicorp/terraform-plugin-framework-timeouts v0.6.0 // indirect - github.com/hashicorp/terraform-plugin-framework-timetypes v0.5.0 // indirect - github.com/hashicorp/terraform-plugin-framework-validators v0.18.0 // indirect github.com/hashicorp/terraform-registry-address v0.4.0 // indirect github.com/hashicorp/terraform-svchost v0.1.1 // indirect github.com/hashicorp/yamux v0.1.2 // indirect diff --git a/go.sum b/go.sum index d590e065b4..2dd12333ad 100644 --- a/go.sum +++ b/go.sum @@ -324,8 +324,6 @@ github.com/hashicorp/terraform-json v0.27.1 h1:zWhEracxJW6lcjt/JvximOYyc12pS/gaK github.com/hashicorp/terraform-json v0.27.1/go.mod h1:GzPLJ1PLdUG5xL6xn1OXWIjteQRT2CNT9o/6A9mi9hE= github.com/hashicorp/terraform-plugin-docs v0.23.0 h1:sipnfD4/9EJBg9zekym+s1H6qmLAKJHhGWBwvN9v/hE= github.com/hashicorp/terraform-plugin-docs v0.23.0/go.mod h1:J4b5AtMRgJlDrwCQz+G4hKABgHY5m56PnsRmdAzBwW8= -github.com/hashicorp/terraform-plugin-framework v1.16.0 h1:tP0f+yJg0Z672e7levixDe5EpWwrTrNryPM9kDMYIpE= -github.com/hashicorp/terraform-plugin-framework v1.16.0/go.mod h1:0xFOxLy5lRzDTayc4dzK/FakIgBhNf/lC4499R9cV4Y= github.com/hashicorp/terraform-plugin-framework v1.16.1 h1:1+zwFm3MEqd/0K3YBB2v9u9DtyYHyEuhVOfeIXbteWA= github.com/hashicorp/terraform-plugin-framework v1.16.1/go.mod h1:0xFOxLy5lRzDTayc4dzK/FakIgBhNf/lC4499R9cV4Y= github.com/hashicorp/terraform-plugin-framework-timeouts v0.6.0 h1:Vv16e7EW4nT9668IV0RhdpEmnLl0im7BZx6J+QMlUkg= From 1a6630231c65767088a79a94bb8f1f8213dc257b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20L=C3=A9one?= Date: Tue, 14 Oct 2025 09:56:50 +0200 Subject: [PATCH 3/5] Multiple fixes --- internal/locality/regional/schemas.go | 6 + internal/services/account/schemas.go | 7 + internal/services/secret/secret.go | 282 +++++++++++------- .../testdata/secret-basic.cassette.yaml | 100 ++++++- internal/verify/uuid.go | 7 +- provider/framework.go | 32 ++ 6 files changed, 318 insertions(+), 116 deletions(-) diff --git a/internal/locality/regional/schemas.go b/internal/locality/regional/schemas.go index 048b9ca579..eb9b395d8e 100644 --- a/internal/locality/regional/schemas.go +++ b/internal/locality/regional/schemas.go @@ -2,6 +2,8 @@ package regional import ( resourceSchema "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/scaleway/scaleway-sdk-go/scw" "github.com/scaleway/terraform-provider-scaleway/v2/internal/locality" @@ -42,5 +44,9 @@ func ResourceSchema(description string) resourceSchema.Attribute { return resourceSchema.StringAttribute{ Description: description, Optional: true, + Computed: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.UseStateForUnknown(), + }, } } diff --git a/internal/services/account/schemas.go b/internal/services/account/schemas.go index c3544208d9..ee63e54646 100644 --- a/internal/services/account/schemas.go +++ b/internal/services/account/schemas.go @@ -3,6 +3,8 @@ package account import ( dataSourceSchema "github.com/hashicorp/terraform-plugin-framework/resource/schema" resourceSchema "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" "github.com/hashicorp/terraform-plugin-framework/schema/validator" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/scaleway/terraform-provider-scaleway/v2/internal/verify" @@ -45,6 +47,11 @@ func ResourceProjectIDSchema(description string) resourceSchema.StringAttribute Validators: []validator.String{ verify.UUIDValidator{}, }, + Computed: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.UseStateForUnknown(), + }, + MarkdownDescription: description, } } diff --git a/internal/services/secret/secret.go b/internal/services/secret/secret.go index 493921371a..b303a93b5e 100644 --- a/internal/services/secret/secret.go +++ b/internal/services/secret/secret.go @@ -4,13 +4,14 @@ import ( "context" "fmt" "path/filepath" + "time" "github.com/hashicorp/terraform-plugin-framework-timeouts/resource/timeouts" - "github.com/hashicorp/terraform-plugin-framework-timetypes/timetypes" "github.com/hashicorp/terraform-plugin-framework/path" "github.com/hashicorp/terraform-plugin-framework/resource" "github.com/hashicorp/terraform-plugin-framework/resource/identityschema" "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/boolplanmodifier" "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringdefault" "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" @@ -19,40 +20,45 @@ import ( secret "github.com/scaleway/scaleway-sdk-go/api/secret/v1beta1" "github.com/scaleway/scaleway-sdk-go/scw" "github.com/scaleway/terraform-provider-scaleway/v2/internal/httperrors" + "github.com/scaleway/terraform-provider-scaleway/v2/internal/locality" "github.com/scaleway/terraform-provider-scaleway/v2/internal/locality/regional" - "github.com/scaleway/terraform-provider-scaleway/v2/internal/planModifiers" + "github.com/scaleway/terraform-provider-scaleway/v2/internal/meta" "github.com/scaleway/terraform-provider-scaleway/v2/internal/services/account" "github.com/scaleway/terraform-provider-scaleway/v2/internal/verify" ) var ( - _ resource.Resource = ResourceSecret{} - _ resource.ResourceWithConfigure = ResourceSecret{} - _ resource.ResourceWithIdentity = ResourceSecret{} - _ resource.ResourceWithImportState = ResourceSecret{} + _ resource.Resource = &ResourceSecret{} + _ resource.ResourceWithConfigure = &ResourceSecret{} + _ resource.ResourceWithIdentity = &ResourceSecret{} + _ resource.ResourceWithImportState = &ResourceSecret{} ) type ResourceSecret struct { secretAPI *secret.API - region scw.Region - projectID string - id string } func NewResourceSecret() resource.Resource { return &ResourceSecret{} } -func (r ResourceSecret) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { +func (r *ResourceSecret) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp) } -func (r ResourceSecret) Configure(ctx context.Context, request resource.ConfigureRequest, response *resource.ConfigureResponse) { +func (r *ResourceSecret) Configure(ctx context.Context, request resource.ConfigureRequest, response *resource.ConfigureResponse) { if request.ProviderData == nil { return } + m, ok := request.ProviderData.(*meta.Meta) + if !ok { + response.Diagnostics.AddError( + "Cannot get meta from provider", + "cannot get meta from provider", + ) + } - client, ok := request.ProviderData.(*scw.Client) + client := m.ScwClient() if !ok { response.Diagnostics.AddError( "Unexpected Action Configure Type", @@ -70,20 +76,22 @@ type ResourceSecretIdentityModel struct { Region types.String `tfsdk:"region"` } -func (r ResourceSecret) IdentitySchema(ctx context.Context, request resource.IdentitySchemaRequest, response *resource.IdentitySchemaResponse) { +func (r *ResourceSecret) IdentitySchema(ctx context.Context, request resource.IdentitySchemaRequest, response *resource.IdentitySchemaResponse) { response.IdentitySchema = identityschema.Schema{ Attributes: map[string]identityschema.Attribute{ "id": identityschema.StringAttribute{ RequiredForImport: true, + Description: "ID of the secret", }, "region": identityschema.StringAttribute{ OptionalForImport: true, + Description: "Region of the secret", }, }, } } -func (r ResourceSecret) Metadata(ctx context.Context, request resource.MetadataRequest, response *resource.MetadataResponse) { +func (r *ResourceSecret) Metadata(ctx context.Context, request resource.MetadataRequest, response *resource.MetadataResponse) { response.TypeName = request.ProviderTypeName + "_secret" } @@ -119,9 +127,18 @@ func (m cleanUpFilePath) PlanModifyString(_ context.Context, req planmodifier.St resp.PlanValue = types.StringValue(filepath.Clean(req.StateValue.String())) } -func (r ResourceSecret) Schema(ctx context.Context, request resource.SchemaRequest, response *resource.SchemaResponse) { +func (r *ResourceSecret) Schema(ctx context.Context, request resource.SchemaRequest, response *resource.SchemaResponse) { response.Schema = schema.Schema{ + Description: "Schema for secret", + MarkdownDescription: "Schema for secret", Attributes: map[string]schema.Attribute{ + "id": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "Secret ID", + PlanModifiers: []planmodifier.String{ + stringplanmodifier.UseStateForUnknown(), + }, + }, "name": schema.StringAttribute{ Required: true, Description: "The secret name", @@ -148,6 +165,7 @@ func (r ResourceSecret) Schema(ctx context.Context, request resource.SchemaReque }, "path": schema.StringAttribute{ Optional: true, + Computed: true, Description: "Location of the secret in the directory structure.", Default: stringdefault.StaticString("/"), PlanModifiers: []planmodifier.String{ @@ -155,7 +173,11 @@ func (r ResourceSecret) Schema(ctx context.Context, request resource.SchemaReque }, }, "protected": schema.BoolAttribute{ - Optional: true, + Optional: true, + Computed: true, + PlanModifiers: []planmodifier.Bool{ + boolplanmodifier.UseStateForUnknown(), + }, Description: "True if secret protection is enabled on a given secret. A protected secret cannot be deleted.", }, "tags": schema.ListAttribute{ @@ -175,6 +197,7 @@ func (r ResourceSecret) Schema(ctx context.Context, request resource.SchemaReque return fmt.Sprintf("Type of the secret could be any value among: %s", secretTypes) }(), Optional: true, + Computed: true, Default: stringdefault.StaticString(secret.SecretTypeOpaque.String()), Validators: []validator.String{ verify.ValidatorFromEnum[secret.SecretType](secret.SecretType("")), @@ -182,71 +205,71 @@ func (r ResourceSecret) Schema(ctx context.Context, request resource.SchemaReque }, "region": regional.ResourceSchema("The region you want to attach the resource to"), "project_id": account.ResourceProjectIDSchema("The project ID you want to attach the secret to"), - "ephemeral_policy": schema.ListNestedAttribute{ - Description: "Ephemeral policy of the secret. Policy that defines whether/when a secret's versions expire. By default, the policy is applied to all the secret's versions.", - Optional: true, - NestedObject: schema.NestedAttributeObject{ - Attributes: map[string]schema.Attribute{ - "ttl": schema.StringAttribute{ - Optional: true, - Description: "Time frame, from one second and up to one year, during which the secret's versions are valid. Has to be specified in Go Duration format", - Validators: []validator.String{ - verify.DurationValidator{}, - }, - PlanModifiers: []planmodifier.String{ - planModifiers.Duration{}, - }, - }, - "expires_once_accessed": schema.BoolAttribute{ - Optional: true, - Description: "True if the secret version expires after a single user access.", - }, - "action": schema.StringAttribute{ - Required: true, - Validators: []validator.String{ - verify.ValidatorFromEnum[secret.EphemeralPolicyAction](secret.EphemeralPolicyAction("")), - }, - Description: "Action to perform when the version of a secret expires.", - }, - }, - }, - }, - "versions": schema.ListNestedAttribute{ - Description: "List of the versions of the secret", - Computed: true, - NestedObject: schema.NestedAttributeObject{ - Attributes: map[string]schema.Attribute{ - "revision": schema.StringAttribute{ - Computed: true, - Description: "The revision of secret version", - }, - "secret_id": schema.StringAttribute{ - Computed: true, - Description: "The secret ID associated with this version", - }, - "status": schema.StringAttribute{ - Computed: true, - Description: "Status of the secret version", - }, - "created_at": schema.StringAttribute{ - Computed: true, - Description: "Date and time of secret version's creation (RFC 3339 format)", - }, - "updated_at": schema.StringAttribute{ - Computed: true, - Description: "Date and time of secret version's creation (RFC 3339 format)", - }, - "description": schema.StringAttribute{ - Optional: true, - Description: "Description of the secret version", - }, - "latest": schema.BoolAttribute{ - Optional: true, - Description: "Returns true if the version is the latest.", - }, - }, - }, - }, + //"ephemeral_policy": schema.ListNestedAttribute{ + // Description: "Ephemeral policy of the secret. Policy that defines whether/when a secret's versions expire. By default, the policy is applied to all the secret's versions.", + // Optional: true, + // NestedObject: schema.NestedAttributeObject{ + // Attributes: map[string]schema.Attribute{ + // "ttl": schema.StringAttribute{ + // Optional: true, + // Description: "Time frame, from one second and up to one year, during which the secret's versions are valid. Has to be specified in Go Duration format", + // Validators: []validator.String{ + // verify.DurationValidator{}, + // }, + // PlanModifiers: []planmodifier.String{ + // planModifiers.Duration{}, + // }, + // }, + // "expires_once_accessed": schema.BoolAttribute{ + // Optional: true, + // Description: "True if the secret version expires after a single user access.", + // }, + // "action": schema.StringAttribute{ + // Required: true, + // Validators: []validator.String{ + // verify.ValidatorFromEnum[secret.EphemeralPolicyAction](secret.EphemeralPolicyAction("")), + // }, + // Description: "Action to perform when the version of a secret expires.", + // }, + // }, + // }, + //}, + //"versions": schema.ListNestedAttribute{ + // Description: "List of the versions of the secret", + // Computed: true, + // NestedObject: schema.NestedAttributeObject{ + // Attributes: map[string]schema.Attribute{ + // "revision": schema.StringAttribute{ + // Computed: true, + // Description: "The revision of secret version", + // }, + // "secret_id": schema.StringAttribute{ + // Computed: true, + // Description: "The secret ID associated with this version", + // }, + // "status": schema.StringAttribute{ + // Computed: true, + // Description: "Status of the secret version", + // }, + // "created_at": schema.StringAttribute{ + // Computed: true, + // Description: "Date and time of secret version's creation (RFC 3339 format)", + // }, + // "updated_at": schema.StringAttribute{ + // Computed: true, + // Description: "Date and time of secret version's creation (RFC 3339 format)", + // }, + // "description": schema.StringAttribute{ + // Optional: true, + // Description: "Description of the secret version", + // }, + // "latest": schema.BoolAttribute{ + // Optional: true, + // Description: "Returns true if the version is the latest.", + // }, + // }, + // }, + //}, }, Blocks: map[string]schema.Block{ "timeouts": timeouts.Block(ctx, @@ -259,34 +282,41 @@ func (r ResourceSecret) Schema(ctx context.Context, request resource.SchemaReque } type ResourceSecretModel struct { - ID types.String `tfsdk:"id"` - Name types.String `tfsdk:"name"` - Protected types.Bool `tfsdk:"protected"` - Type types.String `tfsdk:"type"` - Tags types.List `tfsdk:"tags"` - Description types.String `tfsdk:"description"` - Path types.String `tfsdk:"path"` - EphemeralPolicy types.String `tfsdk:"ephemeral_policy"` - Region types.String `tfsdk:"region"` - ProjectID types.String `tfsdk:"project_id"` - VersionCount types.Int32 `tfsdk:"version_count"` - Status types.String `tfsdk:"status"` - CreatedAt timetypes.RFC3339 `tfsdk:"created_at"` - UpdatedAt timetypes.RFC3339 `tfsdk:"updated_at"` - Versions types.ListType `tfsdk:"versions"` + ID types.String `tfsdk:"id"` + Name types.String `tfsdk:"name"` + Protected types.Bool `tfsdk:"protected"` + Type types.String `tfsdk:"type"` + Tags types.List `tfsdk:"tags"` + Description types.String `tfsdk:"description"` + Path types.String `tfsdk:"path"` + // EphemeralPolicy types.String `tfsdk:"ephemeral_policy"` + Region types.String `tfsdk:"region"` + ProjectID types.String `tfsdk:"project_id"` + VersionCount types.Int32 `tfsdk:"version_count"` + Status types.String `tfsdk:"status"` + CreatedAt types.String `tfsdk:"created_at"` + UpdatedAt types.String `tfsdk:"updated_at"` + // Versions types.List `tfsdk:"versions"` + Timeouts timeouts.Value `tfsdk:"timeouts"` } -func (r ResourceSecret) Create(ctx context.Context, request resource.CreateRequest, response *resource.CreateResponse) { +func (r *ResourceSecret) Create(ctx context.Context, request resource.CreateRequest, response *resource.CreateResponse) { var data ResourceSecretModel response.Diagnostics.Append(request.Plan.Get(ctx, &data)...) secretCreateRequest := &secret.CreateSecretRequest{ - Region: r.region, - ProjectID: r.projectID, - Name: data.Name.String(), + Name: data.Name.ValueString(), Protected: data.Protected.ValueBool(), - Type: secret.SecretType(data.Type.String()), + Type: secret.SecretType(data.Type.ValueString()), + } + + if !data.Region.IsNull() { + secretCreateRequest.Region = scw.Region(data.Region.ValueString()) + } + + if !data.ProjectID.IsNull() { + secretCreateRequest.ProjectID = data.ProjectID.ValueString() } //if !data.Tags.IsNull() { @@ -337,18 +367,29 @@ func (r ResourceSecret) Create(ctx context.Context, request resource.CreateReque // Save data into Terraform state data.ID = types.StringValue(regional.NewIDString(apiResponse.Region, apiResponse.ID)) + data.Name = types.StringValue(apiResponse.Name) + data.Description = types.StringPointerValue(apiResponse.Description) + data.Region = types.StringValue(apiResponse.Region.String()) + data.Path = types.StringValue(apiResponse.Path) + data.VersionCount = types.Int32Value(int32(apiResponse.VersionCount)) + data.ProjectID = types.StringValue(apiResponse.ProjectID) + data.Type = types.StringValue(apiResponse.Type.String()) + data.Status = types.StringValue(apiResponse.Status.String()) + data.CreatedAt = types.StringValue(apiResponse.CreatedAt.Format(time.RFC3339)) + data.UpdatedAt = types.StringValue(apiResponse.UpdatedAt.Format(time.RFC3339)) + data.Protected = types.BoolValue(apiResponse.Protected) response.Diagnostics.Append(response.State.Set(ctx, &data)...) } -func (r ResourceSecret) Read(ctx context.Context, request resource.ReadRequest, response *resource.ReadResponse) { +func (r *ResourceSecret) Read(ctx context.Context, request resource.ReadRequest, response *resource.ReadResponse) { var data ResourceSecretModel // Read Terraform prior state data into the model response.Diagnostics.Append(request.State.Get(ctx, &data)...) secretResponse, err := r.secretAPI.GetSecret(&secret.GetSecretRequest{ - Region: scw.Region(data.Region.String()), - SecretID: data.ID.String(), + Region: scw.Region(data.Region.ValueString()), + SecretID: locality.ExpandID(data.ID.ValueString()), }, scw.WithContext(ctx)) if err != nil { if httperrors.Is404(err) { @@ -389,8 +430,8 @@ func (r ResourceSecret) Read(ctx context.Context, request resource.ReadRequest, data.ProjectID = types.StringValue(secretResponse.ProjectID) data.Type = types.StringValue(secretResponse.Type.String()) data.Status = types.StringValue(secretResponse.Status.String()) - data.CreatedAt = timetypes.NewRFC3339TimeValue(*secretResponse.CreatedAt) - data.UpdatedAt = timetypes.NewRFC3339TimeValue(*secretResponse.UpdatedAt) + data.CreatedAt = types.StringValue(secretResponse.CreatedAt.Format(time.RFC3339)) + data.UpdatedAt = types.StringValue(secretResponse.UpdatedAt.Format(time.RFC3339)) data.Protected = types.BoolValue(secretResponse.Protected) //_ = d.Set("ephemeral_policy", flattenEphemeralPolicy(secretResponse.EphemeralPolicy)) @@ -413,15 +454,15 @@ func (r ResourceSecret) Read(ctx context.Context, request resource.ReadRequest, response.Diagnostics.Append(response.State.Set(ctx, &data)...) } -func (r ResourceSecret) Update(ctx context.Context, request resource.UpdateRequest, response *resource.UpdateResponse) { +func (r *ResourceSecret) Update(ctx context.Context, request resource.UpdateRequest, response *resource.UpdateResponse) { var plan, state ResourceSecretModel response.Diagnostics.Append(request.Plan.Get(ctx, &plan)...) response.Diagnostics.Append(request.State.Get(ctx, &state)...) updateRequest := &secret.UpdateSecretRequest{ - Region: scw.Region(plan.Region.String()), - SecretID: plan.ID.String(), + Region: scw.Region(plan.Region.ValueString()), + SecretID: locality.ExpandID(plan.ID.ValueString()), } hasChanged := false @@ -458,13 +499,28 @@ func (r ResourceSecret) Update(ctx context.Context, request resource.UpdateReque //} if hasChanged { - _, err := r.secretAPI.UpdateSecret(updateRequest, scw.WithContext(ctx)) + secretResponse, err := r.secretAPI.UpdateSecret(updateRequest, scw.WithContext(ctx)) if err != nil { response.Diagnostics.AddError( "unable to update secret", err.Error(), ) } + + plan.Name = types.StringValue(secretResponse.Name) + plan.Description = types.StringPointerValue(secretResponse.Description) + plan.Region = types.StringValue(secretResponse.Region.String()) + plan.Path = types.StringValue(secretResponse.Path) + // data.VersionCount = types.Int32Value(int32(versions.TotalCount)) + plan.ProjectID = types.StringValue(secretResponse.ProjectID) + plan.Type = types.StringValue(secretResponse.Type.String()) + plan.Status = types.StringValue(secretResponse.Status.String()) + plan.CreatedAt = types.StringValue(secretResponse.CreatedAt.Format(time.RFC3339)) + plan.UpdatedAt = types.StringValue(secretResponse.UpdatedAt.Format(time.RFC3339)) + plan.Protected = types.BoolValue(secretResponse.Protected) + + // Save updated data into Terraform state + response.Diagnostics.Append(response.State.Set(ctx, &plan)...) } //if !plan.Protected.Equal(state.Protected) { @@ -504,15 +560,15 @@ func (r ResourceSecret) Update(ctx context.Context, request resource.UpdateReque //} } -func (r ResourceSecret) Delete(ctx context.Context, request resource.DeleteRequest, response *resource.DeleteResponse) { +func (r *ResourceSecret) Delete(ctx context.Context, request resource.DeleteRequest, response *resource.DeleteResponse) { var data ResourceSecretModel // Read Terraform prior state data into the model response.Diagnostics.Append(request.State.Get(ctx, &data)...) err := r.secretAPI.DeleteSecret(&secret.DeleteSecretRequest{ - Region: scw.Region(data.Region.String()), - SecretID: data.ID.String(), + Region: scw.Region(data.Region.ValueString()), + SecretID: data.ID.ValueString(), }, scw.WithContext(ctx)) if err != nil && !httperrors.Is404(err) { response.Diagnostics.AddError( diff --git a/internal/services/secret/testdata/secret-basic.cassette.yaml b/internal/services/secret/testdata/secret-basic.cassette.yaml index 2797c38e00..4ea76914e7 100644 --- a/internal/services/secret/testdata/secret-basic.cassette.yaml +++ b/internal/services/secret/testdata/secret-basic.cassette.yaml @@ -1,3 +1,101 @@ --- version: 2 -interactions: [] +interactions: + - id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: api.scaleway.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.25.2; darwin; arm64) terraform-provider/develop terraform/terraform-tests + url: https://api.scaleway.com/secret-manager/v1beta1/regions/fr-par/secrets/2c15000d-011c-47d9-b54d-e8201aeae491 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 464 + uncompressed: false + body: '{"created_at":"2025-10-13T16:08:46.793517Z","deletion_requested_at":null,"description":"secret description","ephemeral_policy":null,"id":"2c15000d-011c-47d9-b54d-e8201aeae491","key_id":null,"managed":false,"name":"secretNameBasic","path":"/","project_id":"105bdce1-64c0-48ab-899d-868455867ecf","protected":false,"region":"fr-par","status":"ready","tags":[],"type":"opaque","updated_at":"2025-10-13T16:08:46.793517Z","used_by":[],"version_count":0}' + headers: + Content-Length: + - "464" + Content-Security-Policy: + - default-src 'none'; frame-ancestors 'none' + Content-Type: + - application/json + Date: + - Mon, 13 Oct 2025 16:08:47 GMT + Server: + - Scaleway API Gateway (fr-par-2;edge03) + Strict-Transport-Security: + - max-age=63072000 + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + X-Request-Id: + - fb89a576-4861-4f05-8e8f-cd99e7edb8fd + status: 200 OK + code: 200 + duration: 95.505625ms + - id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: api.scaleway.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.25.2; darwin; arm64) terraform-provider/develop terraform/terraform-tests + url: https://api.scaleway.com/secret-manager/v1beta1/regions/fr-par/secrets/2c15000d-011c-47d9-b54d-e8201aeae491 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 471 + uncompressed: false + body: '{"created_at":"2025-10-13T16:08:46.793517Z","deletion_requested_at":null,"description":"update description","ephemeral_policy":null,"id":"2c15000d-011c-47d9-b54d-e8201aeae491","key_id":null,"managed":false,"name":"secretNameBasicUpdated","path":"/","project_id":"105bdce1-64c0-48ab-899d-868455867ecf","protected":false,"region":"fr-par","status":"ready","tags":[],"type":"opaque","updated_at":"2025-10-13T16:08:47.936913Z","used_by":[],"version_count":0}' + headers: + Content-Length: + - "471" + Content-Security-Policy: + - default-src 'none'; frame-ancestors 'none' + Content-Type: + - application/json + Date: + - Mon, 13 Oct 2025 16:08:48 GMT + Server: + - Scaleway API Gateway (fr-par-2;edge03) + Strict-Transport-Security: + - max-age=63072000 + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + X-Request-Id: + - 4a31cde6-a4a3-450e-9ff3-4da1061fdb4b + status: 200 OK + code: 200 + duration: 85.576583ms diff --git a/internal/verify/uuid.go b/internal/verify/uuid.go index 1a1c546c3e..75d7a9e1f4 100644 --- a/internal/verify/uuid.go +++ b/internal/verify/uuid.go @@ -2,6 +2,7 @@ package verify import ( "context" + "fmt" "github.com/hashicorp/go-cty/cty" diagFramework "github.com/hashicorp/terraform-plugin-framework/diag" @@ -135,8 +136,10 @@ func (U UUIDValidator) MarkdownDescription(ctx context.Context) string { } func (U UUIDValidator) ValidateString(ctx context.Context, request validator.StringRequest, response *validator.StringResponse) { - if !validation.IsUUID(request.ConfigValue.String()) { - response.Diagnostics.AddError("is not an uuid", "is not a UUID") + if !request.ConfigValue.IsNull() && !validation.IsUUID(request.ConfigValue.String()) { + response.Diagnostics.AddError( + fmt.Sprintf("String attribute is not an uuid: %s", request.PathExpression.String()), + fmt.Sprintf("At path: %s, value %s is not a UUID", request.Path, request.ConfigValue)) } } diff --git a/provider/framework.go b/provider/framework.go index 72fa4532f7..c801e9dac6 100644 --- a/provider/framework.go +++ b/provider/framework.go @@ -10,6 +10,7 @@ import ( "github.com/hashicorp/terraform-plugin-framework/provider" "github.com/hashicorp/terraform-plugin-framework/provider/schema" "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/scaleway/terraform-provider-scaleway/v2/internal/meta" "github.com/scaleway/terraform-provider-scaleway/v2/internal/services/secret" ) @@ -67,6 +68,37 @@ func (p *ScalewayProvider) Schema(_ context.Context, _ provider.SchemaRequest, r } func (p *ScalewayProvider) Configure(ctx context.Context, req provider.ConfigureRequest, resp *provider.ConfigureResponse) { + terraformVersion := req.TerraformVersion + + m, err := meta.NewMeta(ctx, &meta.Config{ + TerraformVersion: terraformVersion, + }) + if err != nil { + resp.Diagnostics.AddError( + "Error in creating the meta", + "error in creating the meta") + } + + ok, message, err := m.HasMultipleVariableSources() + if err != nil { + resp.Diagnostics.AddWarning( + "Error checking multiple variable sources", + err.Error(), + ) + } + + if ok && err == nil { + resp.Diagnostics.AddWarning( + "Multiple variable sources detected, please make sure the right credentials are used", + message, + ) + } + + resp.ActionData = m + resp.DataSourceData = m + resp.EphemeralResourceData = m + resp.ListResourceData = m + resp.ResourceData = m } func (p *ScalewayProvider) Resources(ctx context.Context) []func() resource.Resource { From b07dfa6873cb5b21317523a2ca24d037a5c85b3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20L=C3=A9one?= Date: Tue, 14 Oct 2025 22:39:04 +0200 Subject: [PATCH 4/5] Fix --- internal/services/secret/secret.go | 109 ++++++++---------- .../testdata/secret-basic.cassette.yaml | 100 +--------------- 2 files changed, 52 insertions(+), 157 deletions(-) diff --git a/internal/services/secret/secret.go b/internal/services/secret/secret.go index b303a93b5e..a635840c00 100644 --- a/internal/services/secret/secret.go +++ b/internal/services/secret/secret.go @@ -6,7 +6,6 @@ import ( "path/filepath" "time" - "github.com/hashicorp/terraform-plugin-framework-timeouts/resource/timeouts" "github.com/hashicorp/terraform-plugin-framework/path" "github.com/hashicorp/terraform-plugin-framework/resource" "github.com/hashicorp/terraform-plugin-framework/resource/identityschema" @@ -56,18 +55,11 @@ func (r *ResourceSecret) Configure(ctx context.Context, request resource.Configu "Cannot get meta from provider", "cannot get meta from provider", ) - } - - client := m.ScwClient() - if !ok { - response.Diagnostics.AddError( - "Unexpected Action Configure Type", - fmt.Sprintf("Expected *scw.Client, got: %T. Please report this issue to the provider developers.", request.ProviderData), - ) return } + client := m.ScwClient() r.secretAPI = secret.NewAPI(client) } @@ -271,22 +263,29 @@ func (r *ResourceSecret) Schema(ctx context.Context, request resource.SchemaRequ // }, //}, }, - Blocks: map[string]schema.Block{ - "timeouts": timeouts.Block(ctx, - timeouts.Opts{ - Create: true, - }, - ), - }, + //Blocks: map[string]schema.Block{ + // "timeouts": timeouts.Block(ctx, + // timeouts.Opts{ + // Create: true, + // CreateDescription: "Timeout to apply on Create", + // Read: true, + // ReadDescription: "Timeout to apply on Read", + // Update: true, + // UpdateDescription: "Timeout to apply on Update", + // Delete: true, + // DeleteDescription: "Timeout to apply on Delete", + // }, + // ), + //}, } } type ResourceSecretModel struct { - ID types.String `tfsdk:"id"` - Name types.String `tfsdk:"name"` - Protected types.Bool `tfsdk:"protected"` - Type types.String `tfsdk:"type"` - Tags types.List `tfsdk:"tags"` + ID types.String `tfsdk:"id"` + Name types.String `tfsdk:"name"` + Protected types.Bool `tfsdk:"protected"` + Type types.String `tfsdk:"type"` + // Tags types.List `tfsdk:"tags"` Description types.String `tfsdk:"description"` Path types.String `tfsdk:"path"` // EphemeralPolicy types.String `tfsdk:"ephemeral_policy"` @@ -297,7 +296,24 @@ type ResourceSecretModel struct { CreatedAt types.String `tfsdk:"created_at"` UpdatedAt types.String `tfsdk:"updated_at"` // Versions types.List `tfsdk:"versions"` - Timeouts timeouts.Value `tfsdk:"timeouts"` + // Timeouts timeouts.Value `tfsdk:"timeouts"` +} + +func NewModelFromSecret(s secret.Secret) *ResourceSecretModel { + return &ResourceSecretModel{ + Name: types.StringValue(s.Name), + Status: types.StringValue(s.Status.String()), + ProjectID: types.StringValue(s.ProjectID), + Protected: types.BoolValue(s.Protected), + Description: types.StringPointerValue(s.Description), + CreatedAt: types.StringValue(s.CreatedAt.Format(time.RFC3339)), + UpdatedAt: types.StringValue(s.UpdatedAt.Format(time.RFC3339)), + Type: types.StringValue(s.Type.String()), + VersionCount: types.Int32Value(int32(s.VersionCount)), + ID: types.StringValue(regional.NewIDString(s.Region, s.ID)), + Region: types.StringValue(s.Region.String()), + Path: types.StringValue(s.Path), + } } func (r *ResourceSecret) Create(ctx context.Context, request resource.CreateRequest, response *resource.CreateResponse) { @@ -348,6 +364,8 @@ func (r *ResourceSecret) Create(ctx context.Context, request resource.CreateRequ "error while creating secret", err.Error(), ) + + return } if apiResponse == nil { response.Diagnostics.AddError( @@ -366,19 +384,9 @@ func (r *ResourceSecret) Create(ctx context.Context, request resource.CreateRequ response.Diagnostics.Append(response.Identity.Set(ctx, identity)...) // Save data into Terraform state - data.ID = types.StringValue(regional.NewIDString(apiResponse.Region, apiResponse.ID)) - data.Name = types.StringValue(apiResponse.Name) - data.Description = types.StringPointerValue(apiResponse.Description) - data.Region = types.StringValue(apiResponse.Region.String()) - data.Path = types.StringValue(apiResponse.Path) - data.VersionCount = types.Int32Value(int32(apiResponse.VersionCount)) - data.ProjectID = types.StringValue(apiResponse.ProjectID) - data.Type = types.StringValue(apiResponse.Type.String()) - data.Status = types.StringValue(apiResponse.Status.String()) - data.CreatedAt = types.StringValue(apiResponse.CreatedAt.Format(time.RFC3339)) - data.UpdatedAt = types.StringValue(apiResponse.UpdatedAt.Format(time.RFC3339)) - data.Protected = types.BoolValue(apiResponse.Protected) - response.Diagnostics.Append(response.State.Set(ctx, &data)...) + dataToSave := NewModelFromSecret(*apiResponse) + + response.Diagnostics.Append(response.State.Set(ctx, &dataToSave)...) } func (r *ResourceSecret) Read(ctx context.Context, request resource.ReadRequest, response *resource.ReadResponse) { @@ -394,6 +402,7 @@ func (r *ResourceSecret) Read(ctx context.Context, request resource.ReadRequest, if err != nil { if httperrors.Is404(err) { response.State.RemoveResource(ctx) + return } @@ -422,17 +431,8 @@ func (r *ResourceSecret) Read(ctx context.Context, request resource.ReadRequest, // return diag.FromErr(err) //} - data.Name = types.StringValue(secretResponse.Name) - data.Description = types.StringPointerValue(secretResponse.Description) - data.Region = types.StringValue(secretResponse.Region.String()) - data.Path = types.StringValue(secretResponse.Path) // data.VersionCount = types.Int32Value(int32(versions.TotalCount)) - data.ProjectID = types.StringValue(secretResponse.ProjectID) - data.Type = types.StringValue(secretResponse.Type.String()) - data.Status = types.StringValue(secretResponse.Status.String()) - data.CreatedAt = types.StringValue(secretResponse.CreatedAt.Format(time.RFC3339)) - data.UpdatedAt = types.StringValue(secretResponse.UpdatedAt.Format(time.RFC3339)) - data.Protected = types.BoolValue(secretResponse.Protected) + //_ = d.Set("ephemeral_policy", flattenEphemeralPolicy(secretResponse.EphemeralPolicy)) //versionsList := make([]map[string]any, 0, len(versions.Versions)) @@ -451,7 +451,8 @@ func (r *ResourceSecret) Read(ctx context.Context, request resource.ReadRequest, //_ = d.Set("versions", versionsList) // Save updated data into Terraform state - response.Diagnostics.Append(response.State.Set(ctx, &data)...) + dataToSave := NewModelFromSecret(*secretResponse) + response.Diagnostics.Append(response.State.Set(ctx, &dataToSave)...) } func (r *ResourceSecret) Update(ctx context.Context, request resource.UpdateRequest, response *resource.UpdateResponse) { @@ -505,22 +506,14 @@ func (r *ResourceSecret) Update(ctx context.Context, request resource.UpdateRequ "unable to update secret", err.Error(), ) + + return } - plan.Name = types.StringValue(secretResponse.Name) - plan.Description = types.StringPointerValue(secretResponse.Description) - plan.Region = types.StringValue(secretResponse.Region.String()) - plan.Path = types.StringValue(secretResponse.Path) - // data.VersionCount = types.Int32Value(int32(versions.TotalCount)) - plan.ProjectID = types.StringValue(secretResponse.ProjectID) - plan.Type = types.StringValue(secretResponse.Type.String()) - plan.Status = types.StringValue(secretResponse.Status.String()) - plan.CreatedAt = types.StringValue(secretResponse.CreatedAt.Format(time.RFC3339)) - plan.UpdatedAt = types.StringValue(secretResponse.UpdatedAt.Format(time.RFC3339)) - plan.Protected = types.BoolValue(secretResponse.Protected) + dataToSave := NewModelFromSecret(*secretResponse) // Save updated data into Terraform state - response.Diagnostics.Append(response.State.Set(ctx, &plan)...) + response.Diagnostics.Append(response.State.Set(ctx, &dataToSave)...) } //if !plan.Protected.Equal(state.Protected) { diff --git a/internal/services/secret/testdata/secret-basic.cassette.yaml b/internal/services/secret/testdata/secret-basic.cassette.yaml index 4ea76914e7..2797c38e00 100644 --- a/internal/services/secret/testdata/secret-basic.cassette.yaml +++ b/internal/services/secret/testdata/secret-basic.cassette.yaml @@ -1,101 +1,3 @@ --- version: 2 -interactions: - - id: 0 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - transfer_encoding: [] - trailer: {} - host: api.scaleway.com - remote_addr: "" - request_uri: "" - body: "" - form: {} - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.25.2; darwin; arm64) terraform-provider/develop terraform/terraform-tests - url: https://api.scaleway.com/secret-manager/v1beta1/regions/fr-par/secrets/2c15000d-011c-47d9-b54d-e8201aeae491 - method: GET - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - transfer_encoding: [] - trailer: {} - content_length: 464 - uncompressed: false - body: '{"created_at":"2025-10-13T16:08:46.793517Z","deletion_requested_at":null,"description":"secret description","ephemeral_policy":null,"id":"2c15000d-011c-47d9-b54d-e8201aeae491","key_id":null,"managed":false,"name":"secretNameBasic","path":"/","project_id":"105bdce1-64c0-48ab-899d-868455867ecf","protected":false,"region":"fr-par","status":"ready","tags":[],"type":"opaque","updated_at":"2025-10-13T16:08:46.793517Z","used_by":[],"version_count":0}' - headers: - Content-Length: - - "464" - Content-Security-Policy: - - default-src 'none'; frame-ancestors 'none' - Content-Type: - - application/json - Date: - - Mon, 13 Oct 2025 16:08:47 GMT - Server: - - Scaleway API Gateway (fr-par-2;edge03) - Strict-Transport-Security: - - max-age=63072000 - X-Content-Type-Options: - - nosniff - X-Frame-Options: - - DENY - X-Request-Id: - - fb89a576-4861-4f05-8e8f-cd99e7edb8fd - status: 200 OK - code: 200 - duration: 95.505625ms - - id: 1 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - transfer_encoding: [] - trailer: {} - host: api.scaleway.com - remote_addr: "" - request_uri: "" - body: "" - form: {} - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.25.2; darwin; arm64) terraform-provider/develop terraform/terraform-tests - url: https://api.scaleway.com/secret-manager/v1beta1/regions/fr-par/secrets/2c15000d-011c-47d9-b54d-e8201aeae491 - method: GET - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - transfer_encoding: [] - trailer: {} - content_length: 471 - uncompressed: false - body: '{"created_at":"2025-10-13T16:08:46.793517Z","deletion_requested_at":null,"description":"update description","ephemeral_policy":null,"id":"2c15000d-011c-47d9-b54d-e8201aeae491","key_id":null,"managed":false,"name":"secretNameBasicUpdated","path":"/","project_id":"105bdce1-64c0-48ab-899d-868455867ecf","protected":false,"region":"fr-par","status":"ready","tags":[],"type":"opaque","updated_at":"2025-10-13T16:08:47.936913Z","used_by":[],"version_count":0}' - headers: - Content-Length: - - "471" - Content-Security-Policy: - - default-src 'none'; frame-ancestors 'none' - Content-Type: - - application/json - Date: - - Mon, 13 Oct 2025 16:08:48 GMT - Server: - - Scaleway API Gateway (fr-par-2;edge03) - Strict-Transport-Security: - - max-age=63072000 - X-Content-Type-Options: - - nosniff - X-Frame-Options: - - DENY - X-Request-Id: - - 4a31cde6-a4a3-450e-9ff3-4da1061fdb4b - status: 200 OK - code: 200 - duration: 85.576583ms +interactions: [] From 244909f521a2cc34d648a2a79262e79d32c07125 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20L=C3=A9one?= Date: Wed, 15 Oct 2025 18:12:09 +0200 Subject: [PATCH 5/5] Fix list --- internal/services/secret/secret.go | 93 ++++++++++++++++++++---------- 1 file changed, 61 insertions(+), 32 deletions(-) diff --git a/internal/services/secret/secret.go b/internal/services/secret/secret.go index a635840c00..72f7d5a46a 100644 --- a/internal/services/secret/secret.go +++ b/internal/services/secret/secret.go @@ -6,11 +6,14 @@ import ( "path/filepath" "time" + "github.com/hashicorp/terraform-plugin-framework/attr" + diagFramework "github.com/hashicorp/terraform-plugin-framework/diag" "github.com/hashicorp/terraform-plugin-framework/path" "github.com/hashicorp/terraform-plugin-framework/resource" "github.com/hashicorp/terraform-plugin-framework/resource/identityschema" "github.com/hashicorp/terraform-plugin-framework/resource/schema" "github.com/hashicorp/terraform-plugin-framework/resource/schema/boolplanmodifier" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/listdefault" "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringdefault" "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" @@ -101,22 +104,22 @@ func (m cleanUpFilePath) MarkdownDescription(ctx context.Context) string { } func (m cleanUpFilePath) PlanModifyString(_ context.Context, req planmodifier.StringRequest, resp *planmodifier.StringResponse) { - // Do nothing if there is no state (resource is being created). - if req.State.Raw.IsNull() { + // Do nothing if there is no state (resource is being created) + // or if we're not in a refresh operation (since PlanOnly tests check for no changes) + if req.State.Raw.IsNull() || !req.PlanValue.IsUnknown() { return } - // Do nothing if there is a known planned value. - if !req.PlanValue.IsUnknown() { - return - } + // For refresh operations, we want to ensure the state matches the API + // The API likely normalizes paths, so we should clean them + cleanedPath := filepath.Clean(req.StateValue.String()) - // Do nothing if there is an unknown configuration value, otherwise interpolation gets messed up. - if req.ConfigValue.IsUnknown() { - return + // Special case: if the cleaned path is empty or root, ensure it's "/" + if cleanedPath == "." { + cleanedPath = "/" } - resp.PlanValue = types.StringValue(filepath.Clean(req.StateValue.String())) + resp.PlanValue = types.StringValue(cleanedPath) } func (r *ResourceSecret) Schema(ctx context.Context, request resource.SchemaRequest, response *resource.SchemaResponse) { @@ -137,7 +140,9 @@ func (r *ResourceSecret) Schema(ctx context.Context, request resource.SchemaRequ }, "description": schema.StringAttribute{ Optional: true, + Computed: true, Description: "Description of the secret", + Default: stringdefault.StaticString(""), }, "status": schema.StringAttribute{ Computed: true, @@ -176,6 +181,8 @@ func (r *ResourceSecret) Schema(ctx context.Context, request resource.SchemaRequ ElementType: types.StringType, Description: "List of tags [\"tag1\", \"tag2\", ...] associated to secret", Optional: true, + Computed: true, + Default: listdefault.StaticValue(types.ListValueMust(types.StringType, []attr.Value{})), }, "type": schema.StringAttribute{ PlanModifiers: []planmodifier.String{ @@ -281,11 +288,11 @@ func (r *ResourceSecret) Schema(ctx context.Context, request resource.SchemaRequ } type ResourceSecretModel struct { - ID types.String `tfsdk:"id"` - Name types.String `tfsdk:"name"` - Protected types.Bool `tfsdk:"protected"` - Type types.String `tfsdk:"type"` - // Tags types.List `tfsdk:"tags"` + ID types.String `tfsdk:"id"` + Name types.String `tfsdk:"name"` + Protected types.Bool `tfsdk:"protected"` + Type types.String `tfsdk:"type"` + Tags types.List `tfsdk:"tags"` Description types.String `tfsdk:"description"` Path types.String `tfsdk:"path"` // EphemeralPolicy types.String `tfsdk:"ephemeral_policy"` @@ -299,8 +306,8 @@ type ResourceSecretModel struct { // Timeouts timeouts.Value `tfsdk:"timeouts"` } -func NewModelFromSecret(s secret.Secret) *ResourceSecretModel { - return &ResourceSecretModel{ +func NewModelFromSecret(ctx context.Context, s secret.Secret) (*ResourceSecretModel, diagFramework.Diagnostics) { + model := &ResourceSecretModel{ Name: types.StringValue(s.Name), Status: types.StringValue(s.Status.String()), ProjectID: types.StringValue(s.ProjectID), @@ -314,6 +321,11 @@ func NewModelFromSecret(s secret.Secret) *ResourceSecretModel { Region: types.StringValue(s.Region.String()), Path: types.StringValue(s.Path), } + + tags, diags := types.ListValueFrom(ctx, types.StringType, s.Tags) + model.Tags = tags + + return model, diags } func (r *ResourceSecret) Create(ctx context.Context, request resource.CreateRequest, response *resource.CreateResponse) { @@ -321,10 +333,17 @@ func (r *ResourceSecret) Create(ctx context.Context, request resource.CreateRequ response.Diagnostics.Append(request.Plan.Get(ctx, &data)...) + if response.Diagnostics.HasError() { + return + } + secretCreateRequest := &secret.CreateSecretRequest{ Name: data.Name.ValueString(), Protected: data.Protected.ValueBool(), - Type: secret.SecretType(data.Type.ValueString()), + } + + if !data.Type.IsNull() { + secretCreateRequest.Type = secret.SecretType(data.Type.ValueString()) } if !data.Region.IsNull() { @@ -335,9 +354,12 @@ func (r *ResourceSecret) Create(ctx context.Context, request resource.CreateRequ secretCreateRequest.ProjectID = data.ProjectID.ValueString() } - //if !data.Tags.IsNull() { - // secretCreateRequest.Tags = data.Tags.Elements() - //} + if !data.Tags.IsNull() { + elements := make([]string, 0, len(data.Tags.Elements())) + diags := data.Tags.ElementsAs(ctx, &elements, false) + response.Diagnostics.Append(diags...) + secretCreateRequest.Tags = elements + } if !data.Description.IsNull() { secretCreateRequest.Description = data.Description.ValueStringPointer() @@ -384,7 +406,7 @@ func (r *ResourceSecret) Create(ctx context.Context, request resource.CreateRequ response.Diagnostics.Append(response.Identity.Set(ctx, identity)...) // Save data into Terraform state - dataToSave := NewModelFromSecret(*apiResponse) + dataToSave, _ := NewModelFromSecret(ctx, *apiResponse) response.Diagnostics.Append(response.State.Set(ctx, &dataToSave)...) } @@ -451,7 +473,7 @@ func (r *ResourceSecret) Read(ctx context.Context, request resource.ReadRequest, //_ = d.Set("versions", versionsList) // Save updated data into Terraform state - dataToSave := NewModelFromSecret(*secretResponse) + dataToSave, _ := NewModelFromSecret(ctx, *secretResponse) response.Diagnostics.Append(response.State.Set(ctx, &dataToSave)...) } @@ -469,7 +491,8 @@ func (r *ResourceSecret) Update(ctx context.Context, request resource.UpdateRequ hasChanged := false if !plan.Description.Equal(state.Description) { - updateRequest.Description = plan.Description.ValueStringPointer() + desc := plan.Description.ValueString() + updateRequest.Description = &desc hasChanged = true } @@ -478,13 +501,19 @@ func (r *ResourceSecret) Update(ctx context.Context, request resource.UpdateRequ hasChanged = true } - //if !plan.Tags.Equal(state.Tags) { - // updateRequest.Tags = plan.Tags. - // hasChanged = true - //} - //if d.HasChange("tags") { - // updateRequest.Tags = types.ExpandUpdatedStringsPtr(d.Get("tags")) - //} + if !plan.Tags.Equal(state.Tags) { + updateRequest.Tags = &[]string{} + + elements := make([]string, 0, len(plan.Tags.Elements())) + diags := plan.Tags.ElementsAs(ctx, &elements, false) + response.Diagnostics.Append(diags...) + + if elements != nil { + updateRequest.Tags = &elements + } + + hasChanged = true + } if !plan.Path.Equal(state.Path) { updateRequest.Path = plan.Path.ValueStringPointer() @@ -510,7 +539,7 @@ func (r *ResourceSecret) Update(ctx context.Context, request resource.UpdateRequ return } - dataToSave := NewModelFromSecret(*secretResponse) + dataToSave, _ := NewModelFromSecret(ctx, *secretResponse) // Save updated data into Terraform state response.Diagnostics.Append(response.State.Set(ctx, &dataToSave)...)