From d12b0ee1487ad698e66f15b1e1f9afe9137f1038 Mon Sep 17 00:00:00 2001 From: vicentepinto98 Date: Tue, 10 Oct 2023 10:56:21 +0100 Subject: [PATCH 01/21] Onboard credentials group resource --- go.mod | 2 +- go.sum | 4 +- .../objectstorage/bucket/datasource.go | 2 +- .../services/objectstorage/bucket/resource.go | 26 +- .../credentialsgroup/datasource.go | 144 ++++++++ .../credentialsgroup/resource.go | 341 ++++++++++++++++++ .../credentialsgroup/resource_test.go | 101 ++++++ .../objectstorage/objectstorage_acc_test.go | 86 ++++- 8 files changed, 690 insertions(+), 16 deletions(-) create mode 100644 stackit/internal/services/objectstorage/credentialsgroup/datasource.go create mode 100644 stackit/internal/services/objectstorage/credentialsgroup/resource.go create mode 100644 stackit/internal/services/objectstorage/credentialsgroup/resource_test.go diff --git a/go.mod b/go.mod index 3d438c8c..6735ef4c 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/dns v0.3.0 github.com/stackitcloud/stackit-sdk-go/services/logme v0.4.0 github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.4.0 - github.com/stackitcloud/stackit-sdk-go/services/objectstorage v0.3.0 + github.com/stackitcloud/stackit-sdk-go/services/objectstorage v0.4.0 github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.4.0 github.com/stackitcloud/stackit-sdk-go/services/postgresflex v0.3.0 github.com/stackitcloud/stackit-sdk-go/services/postgresql v0.4.0 diff --git a/go.sum b/go.sum index 27c8bff2..da1a9355 100644 --- a/go.sum +++ b/go.sum @@ -135,8 +135,8 @@ github.com/stackitcloud/stackit-sdk-go/services/logme v0.4.0 h1:ZySWV2ZpSWY0qlV1 github.com/stackitcloud/stackit-sdk-go/services/logme v0.4.0/go.mod h1:CG5G3FlJVksfnhcxb8nXYAFxn4lnUBWkDMGNW+6jq2w= github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.4.0 h1:0U8sJFEeYcp9sC9ybqOo0ZM4Rco56wFk+xD4+BltthM= github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.4.0/go.mod h1:3dOLY0zIH/o2iP/DnkM2bnQIW/Dm79XNDw3gBY5se9s= -github.com/stackitcloud/stackit-sdk-go/services/objectstorage v0.3.0 h1:gV/8X4eU1M0r/s3On2Y/OyJw/CwYceMT0iIoOxEV9s8= -github.com/stackitcloud/stackit-sdk-go/services/objectstorage v0.3.0/go.mod h1:H0B0VBzyW90ksuG+Bu9iqOan80paw+J6Ik9AZuiz9M0= +github.com/stackitcloud/stackit-sdk-go/services/objectstorage v0.4.0 h1:cU0qGWg2mW4mRM5xeTaB5DSSFnzetyIx2J+ER3RmdIg= +github.com/stackitcloud/stackit-sdk-go/services/objectstorage v0.4.0/go.mod h1:H0B0VBzyW90ksuG+Bu9iqOan80paw+J6Ik9AZuiz9M0= github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.4.0 h1:6Q+ArGyOQDir05pJLc0TbJBGrYyNZ2tKzNY8AGVA0SA= github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.4.0/go.mod h1:syCy6+8GsJu9lHyhN0Qeg66AgTv5LjlgtppbOVFIaPc= github.com/stackitcloud/stackit-sdk-go/services/postgresflex v0.3.0 h1:ycLwGv3ILcnE3M9TYOXNtPWyxXqvpRHFeNhX8kJbB8g= diff --git a/stackit/internal/services/objectstorage/bucket/datasource.go b/stackit/internal/services/objectstorage/bucket/datasource.go index aea28f98..1ca5f77d 100644 --- a/stackit/internal/services/objectstorage/bucket/datasource.go +++ b/stackit/internal/services/objectstorage/bucket/datasource.go @@ -74,7 +74,7 @@ func (r *bucketDataSource) Configure(ctx context.Context, req datasource.Configu // Schema defines the schema for the data source. func (r *bucketDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) { descriptions := map[string]string{ - "main": "ObjectStorage credentials data source schema.", + "main": "ObjectStorage buckets data source schema.", "id": "Terraform's internal data source identifier. It is structured as \"`project_id`,`bucket_name`\".", "bucket_name": "The bucket name. It must be DNS conform.", "project_id": "STACKIT Project ID to which the bucket is associated.", diff --git a/stackit/internal/services/objectstorage/bucket/resource.go b/stackit/internal/services/objectstorage/bucket/resource.go index 1a851d5a..4ac2f5ad 100644 --- a/stackit/internal/services/objectstorage/bucket/resource.go +++ b/stackit/internal/services/objectstorage/bucket/resource.go @@ -6,6 +6,7 @@ import ( "strings" "time" + "github.com/hashicorp/terraform-plugin-framework/diag" "github.com/hashicorp/terraform-plugin-framework/schema/validator" "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/core" @@ -94,7 +95,7 @@ func (r *bucketResource) Schema(_ context.Context, _ resource.SchemaRequest, res "main": "ObjectStorage bucket resource schema.", "id": "Terraform's internal resource identifier. It is structured as \"`project_id`,`bucket_name`\".", "bucket_name": "The bucket name. It must be DNS conform.", - "project_id": "STACKIT Project ID to which the bucket is associated.", + "project_id": "STACKIT Project ID to which the bucket is associated to.", "url_path_style": "URL in path style.", "url_virtual_hosted_style": "URL in virtual hosted style.", } @@ -155,8 +156,15 @@ func (r *bucketResource) Create(ctx context.Context, req resource.CreateRequest, ctx = tflog.SetField(ctx, "project_id", projectId) ctx = tflog.SetField(ctx, "bucket_name", bucketName) - // Create new recordset - _, err := r.client.CreateBucket(ctx, projectId, bucketName).Execute() + // handle project init + err := r.enableProject(ctx, &resp.Diagnostics, &model) + if resp.Diagnostics.HasError() { + core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating credentials group", fmt.Sprintf("Enabling object storage project before creation: %v", err)) + return + } + + // Create new bucket + _, err = r.client.CreateBucket(ctx, projectId, bucketName).Execute() if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating bucket", fmt.Sprintf("Calling API: %v", err)) return @@ -294,3 +302,15 @@ func mapFields(bucketResp *objectstorage.GetBucketResponse, model *Model) error model.URLVirtualHostedStyle = types.StringPointerValue(bucket.UrlVirtualHostedStyle) return nil } + +// enableProject enables object storage for the specified project. If the project already exists, nothing happens +func (r *bucketResource) enableProject(ctx context.Context, diags *diag.Diagnostics, model *Model) error { + projectId := model.ProjectId.ValueString() + + // From the object storage OAS: Creation will also be successful if the project already exists, but will not create a duplicate + _, err := r.client.CreateProject(ctx, projectId).Execute() + if err != nil { + return fmt.Errorf("failed to create object storage project: %w", err) + } + return nil +} diff --git a/stackit/internal/services/objectstorage/credentialsgroup/datasource.go b/stackit/internal/services/objectstorage/credentialsgroup/datasource.go new file mode 100644 index 00000000..1c13cad7 --- /dev/null +++ b/stackit/internal/services/objectstorage/credentialsgroup/datasource.go @@ -0,0 +1,144 @@ +package objectstorage + +import ( + "context" + "fmt" + + "github.com/hashicorp/terraform-plugin-framework/datasource" + "github.com/hashicorp/terraform-plugin-framework/schema/validator" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/core" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/validate" + + "github.com/hashicorp/terraform-plugin-framework/datasource/schema" + "github.com/stackitcloud/stackit-sdk-go/core/config" + "github.com/stackitcloud/stackit-sdk-go/services/objectstorage" +) + +// Ensure the implementation satisfies the expected interfaces. +var ( + _ datasource.DataSource = &credentialsGroupDataSource{} +) + +// NewCredentialsGroupDataSource is a helper function to simplify the provider implementation. +func NewCredentialsGroupDataSource() datasource.DataSource { + return &credentialsGroupDataSource{} +} + +// credentialsGroupDataSource is the data source implementation. +type credentialsGroupDataSource struct { + client *objectstorage.APIClient +} + +// Metadata returns the data source type name. +func (r *credentialsGroupDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_objectstorage_credentialsgroup" +} + +// Configure adds the provider configured client to the data source. +func (r *credentialsGroupDataSource) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) { + // Prevent panic if the provider has not been configured. + if req.ProviderData == nil { + return + } + + providerData, ok := req.ProviderData.(core.ProviderData) + if !ok { + core.LogAndAddError(ctx, &resp.Diagnostics, "Error configuring API client", fmt.Sprintf("Expected configure type stackit.ProviderData, got %T", req.ProviderData)) + return + } + + var apiClient *objectstorage.APIClient + var err error + if providerData.ObjectStorageCustomEndpoint != "" { + apiClient, err = objectstorage.NewAPIClient( + config.WithCustomAuth(providerData.RoundTripper), + config.WithEndpoint(providerData.ObjectStorageCustomEndpoint), + ) + } else { + apiClient, err = objectstorage.NewAPIClient( + config.WithCustomAuth(providerData.RoundTripper), + config.WithRegion(providerData.Region), + ) + } + + if err != nil { + core.LogAndAddError(ctx, &resp.Diagnostics, "Error configuring API client", fmt.Sprintf("Configuring client: %v", err)) + return + } + + r.client = apiClient + tflog.Info(ctx, "ObjectStorage credentials group client configured") +} + +// Schema defines the schema for the data source. +func (r *credentialsGroupDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) { + descriptions := map[string]string{ + "main": "ObjectStorage credentials group data source schema.", + "id": "Terraform's internal data source identifier. It is structured as \"`project_id`,`credentials_group_id`\".", + "credentials_group_id": "The credentials group ID", + "name": "The credentials group's display name.", + "project_id": "Object Storage Project ID to which the credentials group is associated to. It can be retrieved from `stackit_object_storage_project` ", + "urn": "Credentials group uniform resource name (URN)", + } + + resp.Schema = schema.Schema{ + Description: descriptions["main"], + Attributes: map[string]schema.Attribute{ + "id": schema.StringAttribute{ + Description: descriptions["id"], + Computed: true, + }, + "credentials_group_id": schema.StringAttribute{ + Description: descriptions["id"], + Optional: true, + Computed: true, + }, + "project_id": schema.StringAttribute{ + Description: descriptions["project_id"], + Required: true, + Validators: []validator.String{ + validate.UUID(), + validate.NoSeparator(), + }, + }, + "name": schema.StringAttribute{ + Description: descriptions["name"], + Optional: true, + Computed: true, + }, + "urn": schema.StringAttribute{ + Computed: true, + Description: descriptions["urn"], + }, + }, + } +} + +// Read refreshes the Terraform state with the latest data. +func (r *credentialsGroupDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { // nolint:gocritic // function signature required by Terraform + var model Model + diags := req.Config.Get(ctx, &model) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + projectId := model.ProjectId.ValueString() + credentialsGroupId := model.CredentialsGroupId.ValueString() + ctx = tflog.SetField(ctx, "project_id", projectId) + ctx = tflog.SetField(ctx, "credentials_group_id", credentialsGroupId) + + err := readCredentialsGroups(ctx, &model, projectId, r.client) + if err != nil { + core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading credentialsGroup", fmt.Sprintf("getting credential group from list of credentials groups: %v", err)) + return + } + + // Set refreshed state + diags = resp.State.Set(ctx, model) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + tflog.Info(ctx, "ObjectStorage credentials group read") +} diff --git a/stackit/internal/services/objectstorage/credentialsgroup/resource.go b/stackit/internal/services/objectstorage/credentialsgroup/resource.go new file mode 100644 index 00000000..24e0c16f --- /dev/null +++ b/stackit/internal/services/objectstorage/credentialsgroup/resource.go @@ -0,0 +1,341 @@ +package objectstorage + +import ( + "context" + "fmt" + "strings" + + "github.com/hashicorp/terraform-plugin-framework/diag" + "github.com/hashicorp/terraform-plugin-framework/schema/validator" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/core" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/validate" + + "github.com/hashicorp/terraform-plugin-framework/path" + "github.com/hashicorp/terraform-plugin-framework/resource" + "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/types" + "github.com/stackitcloud/stackit-sdk-go/core/config" + "github.com/stackitcloud/stackit-sdk-go/core/utils" + "github.com/stackitcloud/stackit-sdk-go/services/objectstorage" +) + +// Ensure the implementation satisfies the expected interfaces. +var ( + _ resource.Resource = &credentialsGroupResource{} + _ resource.ResourceWithConfigure = &credentialsGroupResource{} + _ resource.ResourceWithImportState = &credentialsGroupResource{} +) + +type Model struct { + Id types.String `tfsdk:"id"` // needed by TF + CredentialsGroupId types.String `tfsdk:"credentials_group_id"` + Name types.String `tfsdk:"name"` + ProjectId types.String `tfsdk:"project_id"` + URN types.String `tfsdk:"urn"` +} + +// NewCredentialsGroupResource is a helper function to simplify the provider implementation. +func NewCredentialsGroupResource() resource.Resource { + return &credentialsGroupResource{} +} + +// credentialsGroupResource is the resource implementation. +type credentialsGroupResource struct { + client *objectstorage.APIClient +} + +// Metadata returns the resource type name. +func (r *credentialsGroupResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_objectstorage_credentials_group" +} + +// Configure adds the provider configured client to the resource. +func (r *credentialsGroupResource) Configure(ctx context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) { + // Prevent panic if the provider has not been configured. + if req.ProviderData == nil { + return + } + + providerData, ok := req.ProviderData.(core.ProviderData) + if !ok { + core.LogAndAddError(ctx, &resp.Diagnostics, "Error configuring API client", fmt.Sprintf("Expected configure type stackit.ProviderData, got %T", req.ProviderData)) + return + } + + var apiClient *objectstorage.APIClient + var err error + if providerData.ObjectStorageCustomEndpoint != "" { + apiClient, err = objectstorage.NewAPIClient( + config.WithCustomAuth(providerData.RoundTripper), + config.WithEndpoint(providerData.ObjectStorageCustomEndpoint), + ) + } else { + apiClient, err = objectstorage.NewAPIClient( + config.WithCustomAuth(providerData.RoundTripper), + config.WithRegion(providerData.Region), + ) + } + + if err != nil { + core.LogAndAddError(ctx, &resp.Diagnostics, "Error configuring API client", fmt.Sprintf("Configuring client: %v", err)) + return + } + + r.client = apiClient + tflog.Info(ctx, "ObjectStorage credentials group client configured") +} + +// Schema defines the schema for the resource. +func (r *credentialsGroupResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) { + descriptions := map[string]string{ + "main": "ObjectStorage credentials group resource schema.", + "id": "Terraform's internal data source identifier. It is structured as \"`project_id`,`credentials_group_id`\".", + "credentials_group_id": "The credentials group ID", + "name": "The credentials group's display name.", + "project_id": "Project ID to which the credentials group is associated to.", + "urn": "Credentials group uniform resource name (URN)", + } + + resp.Schema = schema.Schema{ + Description: descriptions["main"], + Attributes: map[string]schema.Attribute{ + "id": schema.StringAttribute{ + Description: descriptions["id"], + Computed: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.UseStateForUnknown(), + }, + }, + "name": schema.StringAttribute{ + Description: descriptions["name"], + Required: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + stringplanmodifier.UseStateForUnknown(), + }, + }, + "credentials_group_id": schema.StringAttribute{ + Description: descriptions["credentials_group_id"], + Computed: true, + }, + "project_id": schema.StringAttribute{ + Description: descriptions["project_id"], + Required: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + stringplanmodifier.UseStateForUnknown(), + }, + Validators: []validator.String{ + validate.UUID(), + validate.NoSeparator(), + }, + }, + "urn": schema.StringAttribute{ + Description: descriptions["urn"], + Computed: true, + }, + }, + } +} + +// Create creates the resource and sets the initial Terraform state. +func (r *credentialsGroupResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { // nolint:gocritic // function signature required by Terraform + var model Model + diags := req.Plan.Get(ctx, &model) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + projectId := model.ProjectId.ValueString() + credentialsGroupName := model.Name.ValueString() + ctx = tflog.SetField(ctx, "project_id", projectId) + ctx = tflog.SetField(ctx, "name", credentialsGroupName) + + createCredentialsGroupPayload := objectstorage.CreateCredentialsGroupPayload{ + DisplayName: utils.Ptr(credentialsGroupName), + } + + // handle project init + err := r.enableProject(ctx, &resp.Diagnostics, &model) + if resp.Diagnostics.HasError() { + core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating credentials group", fmt.Sprintf("Enabling object storage project before creation: %v", err)) + return + } + + // Create new credentials group + got, err := r.client.CreateCredentialsGroup(ctx, projectId).CreateCredentialsGroupPayload(createCredentialsGroupPayload).Execute() + if err != nil { + core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating credentials group", fmt.Sprintf("Calling API: %v", err)) + return + } + + // Map response body to schema + err = mapFields(got, &model) + if err != nil { + core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating credentialsGroup", fmt.Sprintf("Processing API payload: %v", err)) + return + } + diags = resp.State.Set(ctx, model) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + tflog.Info(ctx, "ObjectStorage credentials group created") +} + +// Read refreshes the Terraform state with the latest data. +func (r *credentialsGroupResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { // nolint:gocritic // function signature required by Terraform + var model Model + diags := req.State.Get(ctx, &model) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + projectId := model.ProjectId.ValueString() + credentialsGroupId := model.CredentialsGroupId.ValueString() + ctx = tflog.SetField(ctx, "project_id", projectId) + ctx = tflog.SetField(ctx, "credentials_group_id", credentialsGroupId) + + err := readCredentialsGroups(ctx, &model, projectId, r.client) + if err != nil { + core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading credentialsGroup", fmt.Sprintf("getting credential group from list of credentials groups: %v", err)) + return + } + + // Set refreshed state + diags = resp.State.Set(ctx, model) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + tflog.Info(ctx, "ObjectStorage credentials group read") +} + +// Update updates the resource and sets the updated Terraform state on success. +func (r *credentialsGroupResource) Update(ctx context.Context, _ resource.UpdateRequest, resp *resource.UpdateResponse) { // nolint:gocritic // function signature required by Terraform + // Update shouldn't be called + core.LogAndAddError(ctx, &resp.Diagnostics, "Error updating credentials group", "CredentialsGroup can't be updated") +} + +// Delete deletes the resource and removes the Terraform state on success. +func (r *credentialsGroupResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { // nolint:gocritic // function signature required by Terraform + var model Model + diags := req.State.Get(ctx, &model) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + projectId := model.ProjectId.ValueString() + credentialsGroupId := model.CredentialsGroupId.ValueString() + ctx = tflog.SetField(ctx, "project_id", projectId) + ctx = tflog.SetField(ctx, "credentials_group_id", credentialsGroupId) + + // Delete existing credentials group + _, err := r.client.DeleteCredentialsGroup(ctx, projectId, credentialsGroupId).Execute() + if err != nil { + core.LogAndAddError(ctx, &resp.Diagnostics, "Error deleting credentials group", fmt.Sprintf("Calling API: %v", err)) + } + + tflog.Info(ctx, "ObjectStorage credentials group deleted") +} + +// ImportState imports a resource into the Terraform state on success. +// The expected format of the resource import identifier is: project_id, credentials_group_id +func (r *credentialsGroupResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { + idParts := strings.Split(req.ID, core.Separator) + if len(idParts) != 2 || idParts[0] == "" || idParts[1] == "" { + core.LogAndAddError(ctx, &resp.Diagnostics, + "Error importing credentialsGroup", + fmt.Sprintf("Expected import identifier with format [project_id],[credentials_group_id], got %q", req.ID), + ) + return + } + + resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("project_id"), idParts[0])...) + resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("credentials_group_id"), idParts[1])...) + tflog.Info(ctx, "ObjectStorage credentials group state imported") +} + +func mapFields(credentialsGroupResp *objectstorage.CreateCredentialsGroupResponse, model *Model) error { + if credentialsGroupResp == nil { + return fmt.Errorf("response input is nil") + } + if credentialsGroupResp.CredentialsGroup == nil { + return fmt.Errorf("response credentialsGroup is nil") + } + if model == nil { + return fmt.Errorf("model input is nil") + } + credentialsGroup := credentialsGroupResp.CredentialsGroup + + model.Name = types.StringPointerValue(credentialsGroup.DisplayName) + model.URN = types.StringPointerValue(credentialsGroup.Urn) + + idParts := []string{ + model.ProjectId.ValueString(), + model.CredentialsGroupId.ValueString(), + } + model.Id = types.StringValue( + strings.Join(idParts, core.Separator), + ) + return nil +} + +// enableProject enables object storage for the specified project. If the project already exists, nothing happens +func (r *credentialsGroupResource) enableProject(ctx context.Context, diags *diag.Diagnostics, model *Model) error { + projectId := model.ProjectId.ValueString() + + // From the object storage OAS: Creation will also be successful if the project already exists, but will not create a duplicate + _, err := r.client.CreateProject(ctx, projectId).Execute() + if err != nil { + return fmt.Errorf("failed to create object storage project: %w", err) + } + return nil +} + +// readCredentialsGroups gets all the existing credentials groups for the specified project, +// finds the credentials group that is being read and updates the state. If the credentials group cannot be found, it throws an error +func readCredentialsGroups(ctx context.Context, model *Model, projectId string, client *objectstorage.APIClient) error { + found := false + + if model.CredentialsGroupId.ValueString() == "" && model.Name.ValueString() == "" { + return fmt.Errorf("missing configuration: either name or credentials group id must be provided") + } + + credentialsGroupsResp, err := client.GetCredentialsGroups(ctx, projectId).Execute() + if err != nil { + return fmt.Errorf("getting credentials groups: %w", err) + } + + if credentialsGroupsResp == nil { + return fmt.Errorf("nil response from GET credentials groups") + } + + for _, credentialsGroup := range *credentialsGroupsResp.CredentialsGroups { + if *credentialsGroup.CredentialsGroupId != model.CredentialsGroupId.ValueString() && *credentialsGroup.DisplayName != model.Name.ValueString() { + continue + } + found = true + model.CredentialsGroupId = types.StringValue(*credentialsGroup.CredentialsGroupId) + model.Name = types.StringValue(*credentialsGroup.DisplayName) + model.URN = types.StringValue(*credentialsGroup.Urn) + + idParts := []string{ + model.ProjectId.ValueString(), + model.CredentialsGroupId.ValueString(), + } + model.Id = types.StringValue( + strings.Join(idParts, core.Separator), + ) + break + } + + if !found { + return fmt.Errorf("credentials group could not be found") + } + + return nil +} diff --git a/stackit/internal/services/objectstorage/credentialsgroup/resource_test.go b/stackit/internal/services/objectstorage/credentialsgroup/resource_test.go new file mode 100644 index 00000000..bd8fc20d --- /dev/null +++ b/stackit/internal/services/objectstorage/credentialsgroup/resource_test.go @@ -0,0 +1,101 @@ +package objectstorage + +import ( + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/stackitcloud/stackit-sdk-go/core/utils" + "github.com/stackitcloud/stackit-sdk-go/services/objectstorage" +) + +func TestMapFields(t *testing.T) { + tests := []struct { + description string + input *objectstorage.CreateCredentialsGroupResponse + expected Model + isValid bool + }{ + { + "default_values", + &objectstorage.CreateCredentialsGroupResponse{ + CredentialsGroup: &objectstorage.CredentialsGroup{}, + }, + Model{ + Id: types.StringValue("pid,cid"), + Name: types.StringNull(), + ProjectId: types.StringValue("pid"), + CredentialsGroupId: types.StringValue("cid"), + URN: types.StringNull(), + }, + true, + }, + { + "simple_values", + &objectstorage.CreateCredentialsGroupResponse{ + CredentialsGroup: &objectstorage.CredentialsGroup{ + DisplayName: utils.Ptr("name"), + Urn: utils.Ptr("urn"), + }, + }, + Model{ + Id: types.StringValue("pid,cid"), + Name: types.StringValue("name"), + ProjectId: types.StringValue("pid"), + CredentialsGroupId: types.StringValue("cid"), + URN: types.StringValue("urn"), + }, + true, + }, + { + "empty_strings", + &objectstorage.CreateCredentialsGroupResponse{ + CredentialsGroup: &objectstorage.CredentialsGroup{ + DisplayName: utils.Ptr(""), + Urn: utils.Ptr(""), + }, + }, + Model{ + Id: types.StringValue("pid,cid"), + Name: types.StringValue(""), + ProjectId: types.StringValue("pid"), + CredentialsGroupId: types.StringValue("cid"), + URN: types.StringValue(""), + }, + true, + }, + { + "nil_response", + nil, + Model{}, + false, + }, + { + "no_bucket", + &objectstorage.CreateCredentialsGroupResponse{}, + Model{}, + false, + }, + } + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + model := &Model{ + ProjectId: tt.expected.ProjectId, + CredentialsGroupId: tt.expected.CredentialsGroupId, + } + err := mapFields(tt.input, model) + if !tt.isValid && err == nil { + t.Fatalf("Should have failed") + } + if tt.isValid && err != nil { + t.Fatalf("Should not have failed: %v", err) + } + if tt.isValid { + diff := cmp.Diff(model, &tt.expected) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + } + }) + } +} diff --git a/stackit/internal/services/objectstorage/objectstorage_acc_test.go b/stackit/internal/services/objectstorage/objectstorage_acc_test.go index e0631648..081948f4 100644 --- a/stackit/internal/services/objectstorage/objectstorage_acc_test.go +++ b/stackit/internal/services/objectstorage/objectstorage_acc_test.go @@ -24,6 +24,12 @@ var bucketResource = map[string]string{ "bucket_name": fmt.Sprintf("acc-test-%s", acctest.RandStringFromCharSet(20, acctest.CharSetAlpha)), } +// Credentials group resource data +var credentialsGroupResource = map[string]string{ + "project_id": testutil.ProjectId, + "credentials_group_name": fmt.Sprintf("acc-test-%s", acctest.RandStringFromCharSet(20, acctest.CharSetAlpha)), +} + func resourceConfig() string { return fmt.Sprintf(` %s @@ -32,10 +38,17 @@ func resourceConfig() string { project_id = "%s" bucket_name = "%s" } + + resource "stackit_objectstorage_credentials_group" "credentials_group" { + project_id = "%s" + bucket_name = "%s" + } `, testutil.ObjectStorageProviderConfig(), bucketResource["project_id"], bucketResource["bucket_name"], + credentialsGroupResource["project_id"], + credentialsGroupResource["credentials_group_name"], ) } @@ -49,11 +62,17 @@ func TestAccObjectStorageResource(t *testing.T) { { Config: resourceConfig(), Check: resource.ComposeAggregateTestCheckFunc( - // Instance data + // Bucket data resource.TestCheckResourceAttr("stackit_objectstorage_bucket.bucket", "project_id", bucketResource["project_id"]), resource.TestCheckResourceAttr("stackit_objectstorage_bucket.bucket", "bucket_name", bucketResource["bucket_name"]), resource.TestCheckResourceAttrSet("stackit_objectstorage_bucket.bucket", "url_path_style"), resource.TestCheckResourceAttrSet("stackit_objectstorage_bucket.bucket", "url_virtual_hosted_style"), + + // Credentials group data + resource.TestCheckResourceAttr("stackit_objectstorage_credentials_group.credentials_group", "project_id", credentialsGroupResource["project_id"]), + resource.TestCheckResourceAttr("stackit_objectstorage_credentials_group.credentials_group", "credentials_group_name", credentialsGroupResource["credentials_group_name"]), + resource.TestCheckResourceAttrSet("stackit_objectstorage_credentials_group.credentials_group", "credentials_group_id"), + resource.TestCheckResourceAttrSet("stackit_objectstorage_credentials_group.credentials_group", "urn"), ), }, // Data source @@ -64,11 +83,16 @@ func TestAccObjectStorageResource(t *testing.T) { data "stackit_objectstorage_bucket" "bucket" { project_id = stackit_objectstorage_bucket.bucket.project_id bucket_name = stackit_objectstorage_bucket.bucket.bucket_name + } + + data "stackit_objectstorage_credentials_group" "credentials_group" { + project_id = stackit_objectstorage_credentials_group.credentials_group.project_id + bucket_name = stackit_objectstorage_credentials_group.credentials_group.credentials_group_id }`, resourceConfig(), ), Check: resource.ComposeAggregateTestCheckFunc( - // Instance data + // Bucket data resource.TestCheckResourceAttr("data.stackit_objectstorage_bucket.bucket", "project_id", bucketResource["project_id"]), resource.TestCheckResourceAttrPair( "stackit_objectstorage_bucket.bucket", "bucket_name", @@ -82,22 +106,37 @@ func TestAccObjectStorageResource(t *testing.T) { "stackit_objectstorage_bucket.bucket", "url_virtual_hosted_style", "data.stackit_objectstorage_bucket.bucket", "url_virtual_hosted_style", ), + + // Credentials group data + resource.TestCheckResourceAttr("data.stackit_objectstorage_credentials_group.credentials_group", "project_id", credentialsGroupResource["project_id"]), + resource.TestCheckResourceAttrPair( + "stackit_objectstorage_credentials_group.credentials_group", "credentials_group_id", + "data.stackit_objectstorage_credentials_group.credentials_group", "credentials_group_id", + ), + resource.TestCheckResourceAttrPair( + "stackit_objectstorage_credentials_group.credentials_group", "credentials_group_name", + "data.stackit_objectstorage_credentials_group.credentials_group", "credentials_group_name", + ), + resource.TestCheckResourceAttrPair( + "stackit_objectstorage_credentials_group.credentials_group", "urn", + "data.stackit_objectstorage_credentials_group.credentials_group", "urn", + ), ), }, // Import { - ResourceName: "stackit_objectstorage_bucket.bucket", + ResourceName: "stackit_objectstorage_credentials_group.credentials_group", ImportStateIdFunc: func(s *terraform.State) (string, error) { - r, ok := s.RootModule().Resources["stackit_objectstorage_bucket.bucket"] + r, ok := s.RootModule().Resources["stackit_objectstorage_credentials_group.credentials_group"] if !ok { - return "", fmt.Errorf("couldn't find resource stackit_objectstorage_bucket.bucket") + return "", fmt.Errorf("couldn't find resource stackit_objectstorage_credentials_group.credentials_group") } - bucketName, ok := r.Primary.Attributes["bucket_name"] + credentialsGroupId, ok := r.Primary.Attributes["credentials_group_id"] if !ok { - return "", fmt.Errorf("couldn't find attribute bucket_name") + return "", fmt.Errorf("couldn't find attribute credentials_group_id") } - return fmt.Sprintf("%s,%s", testutil.ProjectId, bucketName), nil + return fmt.Sprintf("%s,%s", testutil.ProjectId, credentialsGroupId), nil }, ImportState: true, ImportStateVerify: true, @@ -145,7 +184,7 @@ func testAccCheckObjectStorageDestroy(s *terraform.State) error { continue } bucketName := *bucket.Name - if utils.Contains(bucketsToDestroy, *bucket.Name) { + if utils.Contains(bucketsToDestroy, bucketName) { _, err := client.DeleteBucketExecute(ctx, testutil.ProjectId, bucketName) if err != nil { return fmt.Errorf("destroying bucket %s during CheckDestroy: %w", bucketName, err) @@ -156,5 +195,34 @@ func testAccCheckObjectStorageDestroy(s *terraform.State) error { } } } + + credentialsGroupsToDestroy := []string{} + for _, rs := range s.RootModule().Resources { + if rs.Type != "stackit_objectstorage_credentials_group" { + continue + } + // credentials group terraform ID: "[project_id],[credentials_group_id]" + credentialsGroupId := strings.Split(rs.Primary.ID, core.Separator)[1] + credentialsGroupsToDestroy = append(credentialsGroupsToDestroy, credentialsGroupId) + } + + credentialsGroupsResp, err := client.GetCredentialsGroups(ctx, testutil.ProjectId).Execute() + if err != nil { + return fmt.Errorf("getting bucketsResp: %w", err) + } + + groups := *credentialsGroupsResp.CredentialsGroups + for _, group := range groups { + if group.CredentialsGroupId == nil { + continue + } + groupId := *group.CredentialsGroupId + if utils.Contains(credentialsGroupsToDestroy, groupId) { + _, err := client.DeleteCredentialsGroupExecute(ctx, testutil.ProjectId, groupId) + if err != nil { + return fmt.Errorf("destroying credentials group %s during CheckDestroy: %w", groupId, err) + } + } + } return nil } From a44fa7fc442a57c0cdcf3805c86a17113b6d3752 Mon Sep 17 00:00:00 2001 From: vicentepinto98 Date: Tue, 10 Oct 2023 14:30:35 +0100 Subject: [PATCH 02/21] Update object storage acc test --- stackit/internal/services/objectstorage/bucket/resource.go | 5 ++--- .../services/objectstorage/credentialsgroup/resource.go | 5 ++--- .../services/objectstorage/objectstorage_acc_test.go | 2 +- stackit/provider.go | 3 +++ 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/stackit/internal/services/objectstorage/bucket/resource.go b/stackit/internal/services/objectstorage/bucket/resource.go index 4ac2f5ad..f8f342fc 100644 --- a/stackit/internal/services/objectstorage/bucket/resource.go +++ b/stackit/internal/services/objectstorage/bucket/resource.go @@ -6,7 +6,6 @@ import ( "strings" "time" - "github.com/hashicorp/terraform-plugin-framework/diag" "github.com/hashicorp/terraform-plugin-framework/schema/validator" "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/core" @@ -157,7 +156,7 @@ func (r *bucketResource) Create(ctx context.Context, req resource.CreateRequest, ctx = tflog.SetField(ctx, "bucket_name", bucketName) // handle project init - err := r.enableProject(ctx, &resp.Diagnostics, &model) + err := r.enableProject(ctx, &model) if resp.Diagnostics.HasError() { core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating credentials group", fmt.Sprintf("Enabling object storage project before creation: %v", err)) return @@ -304,7 +303,7 @@ func mapFields(bucketResp *objectstorage.GetBucketResponse, model *Model) error } // enableProject enables object storage for the specified project. If the project already exists, nothing happens -func (r *bucketResource) enableProject(ctx context.Context, diags *diag.Diagnostics, model *Model) error { +func (r *bucketResource) enableProject(ctx context.Context, model *Model) error { projectId := model.ProjectId.ValueString() // From the object storage OAS: Creation will also be successful if the project already exists, but will not create a duplicate diff --git a/stackit/internal/services/objectstorage/credentialsgroup/resource.go b/stackit/internal/services/objectstorage/credentialsgroup/resource.go index 24e0c16f..f4955fd2 100644 --- a/stackit/internal/services/objectstorage/credentialsgroup/resource.go +++ b/stackit/internal/services/objectstorage/credentialsgroup/resource.go @@ -5,7 +5,6 @@ import ( "fmt" "strings" - "github.com/hashicorp/terraform-plugin-framework/diag" "github.com/hashicorp/terraform-plugin-framework/schema/validator" "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/core" @@ -159,7 +158,7 @@ func (r *credentialsGroupResource) Create(ctx context.Context, req resource.Crea } // handle project init - err := r.enableProject(ctx, &resp.Diagnostics, &model) + err := r.enableProject(ctx, &model) if resp.Diagnostics.HasError() { core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating credentials group", fmt.Sprintf("Enabling object storage project before creation: %v", err)) return @@ -285,7 +284,7 @@ func mapFields(credentialsGroupResp *objectstorage.CreateCredentialsGroupRespons } // enableProject enables object storage for the specified project. If the project already exists, nothing happens -func (r *credentialsGroupResource) enableProject(ctx context.Context, diags *diag.Diagnostics, model *Model) error { +func (r *credentialsGroupResource) enableProject(ctx context.Context, model *Model) error { projectId := model.ProjectId.ValueString() // From the object storage OAS: Creation will also be successful if the project already exists, but will not create a duplicate diff --git a/stackit/internal/services/objectstorage/objectstorage_acc_test.go b/stackit/internal/services/objectstorage/objectstorage_acc_test.go index 081948f4..4650b9fa 100644 --- a/stackit/internal/services/objectstorage/objectstorage_acc_test.go +++ b/stackit/internal/services/objectstorage/objectstorage_acc_test.go @@ -41,7 +41,7 @@ func resourceConfig() string { resource "stackit_objectstorage_credentials_group" "credentials_group" { project_id = "%s" - bucket_name = "%s" + name = "%s" } `, testutil.ObjectStorageProviderConfig(), diff --git a/stackit/provider.go b/stackit/provider.go index deda860c..66bf2497 100644 --- a/stackit/provider.go +++ b/stackit/provider.go @@ -19,6 +19,7 @@ import ( mariaDBCredentials "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/mariadb/credentials" mariaDBInstance "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/mariadb/instance" objectStorageBucket "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/objectstorage/bucket" + objecStorageCredentialsGroup "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/objectstorage/credentialsgroup" openSearchCredentials "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/opensearch/credentials" openSearchInstance "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/opensearch/instance" postgresFlexInstance "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/postgresflex/instance" @@ -313,6 +314,7 @@ func (p *Provider) DataSources(_ context.Context) []func() datasource.DataSource mariaDBInstance.NewInstanceDataSource, mariaDBCredentials.NewCredentialsDataSource, objectStorageBucket.NewBucketDataSource, + objecStorageCredentialsGroup.NewCredentialsGroupDataSource, openSearchInstance.NewInstanceDataSource, openSearchCredentials.NewCredentialsDataSource, rabbitMQInstance.NewInstanceDataSource, @@ -341,6 +343,7 @@ func (p *Provider) Resources(_ context.Context) []func() resource.Resource { mariaDBInstance.NewInstanceResource, mariaDBCredentials.NewCredentialsResource, objectStorageBucket.NewBucketResource, + objecStorageCredentialsGroup.NewCredentialsGroupResource, openSearchInstance.NewInstanceResource, openSearchCredentials.NewCredentialsResource, rabbitMQInstance.NewInstanceResource, From bbe520f25517f6b468f37e8713c4b54c872a73e6 Mon Sep 17 00:00:00 2001 From: vicentepinto98 Date: Tue, 10 Oct 2023 14:36:05 +0100 Subject: [PATCH 03/21] Fix typo --- stackit/internal/services/objectstorage/bucket/datasource.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stackit/internal/services/objectstorage/bucket/datasource.go b/stackit/internal/services/objectstorage/bucket/datasource.go index 1ca5f77d..58fef520 100644 --- a/stackit/internal/services/objectstorage/bucket/datasource.go +++ b/stackit/internal/services/objectstorage/bucket/datasource.go @@ -74,7 +74,7 @@ func (r *bucketDataSource) Configure(ctx context.Context, req datasource.Configu // Schema defines the schema for the data source. func (r *bucketDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) { descriptions := map[string]string{ - "main": "ObjectStorage buckets data source schema.", + "main": "ObjectStorage bucket data source schema.", "id": "Terraform's internal data source identifier. It is structured as \"`project_id`,`bucket_name`\".", "bucket_name": "The bucket name. It must be DNS conform.", "project_id": "STACKIT Project ID to which the bucket is associated.", From ceb27d07954e632a490c407314a1a829c02d660d Mon Sep 17 00:00:00 2001 From: vicentepinto98 Date: Tue, 10 Oct 2023 15:07:10 +0100 Subject: [PATCH 04/21] Generate docs, add examples, fix typos --- docs/data-sources/objectstorage_bucket.md | 4 +-- .../objectstorage_credentials_group.md | 30 +++++++++++++++++++ .../objectstorage_credentials_group.md | 27 +++++++++++++++++ .../data-source.tf | 4 +++ .../data-source.tf | 4 +++ .../stackit_object_storage_bucket/resource.tf | 4 +++ .../resource.tf | 4 +++ .../services/objectstorage/bucket/resource.go | 4 +-- .../credentialsgroup/datasource.go | 4 +-- .../credentialsgroup/resource.go | 4 +-- .../objectstorage/objectstorage_acc_test.go | 14 ++++----- 11 files changed, 88 insertions(+), 15 deletions(-) create mode 100644 docs/data-sources/objectstorage_credentials_group.md create mode 100644 docs/resources/objectstorage_credentials_group.md create mode 100644 examples/data-sources/stackit_object_storage_bucket/data-source.tf create mode 100644 examples/data-sources/stackit_object_storage_credentials_group/data-source.tf create mode 100644 examples/resources/stackit_object_storage_bucket/resource.tf create mode 100644 examples/resources/stackit_object_storage_credentials_group/resource.tf diff --git a/docs/data-sources/objectstorage_bucket.md b/docs/data-sources/objectstorage_bucket.md index 223d1599..f880af6f 100644 --- a/docs/data-sources/objectstorage_bucket.md +++ b/docs/data-sources/objectstorage_bucket.md @@ -3,12 +3,12 @@ page_title: "stackit_objectstorage_bucket Data Source - stackit" subcategory: "" description: |- - ObjectStorage credentials data source schema. + ObjectStorage bucket data source schema. --- # stackit_objectstorage_bucket (Data Source) -ObjectStorage credentials data source schema. +ObjectStorage bucket data source schema. diff --git a/docs/data-sources/objectstorage_credentials_group.md b/docs/data-sources/objectstorage_credentials_group.md new file mode 100644 index 00000000..d611c9d5 --- /dev/null +++ b/docs/data-sources/objectstorage_credentials_group.md @@ -0,0 +1,30 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "stackit_objectstorage_credentials_group Data Source - stackit" +subcategory: "" +description: |- + ObjectStorage credentials group data source schema. +--- + +# stackit_objectstorage_credentials_group (Data Source) + +ObjectStorage credentials group data source schema. + + + + +## Schema + +### Required + +- `project_id` (String) Object Storage Project ID to which the credentials group is associated. + +### Optional + +- `credentials_group_id` (String) Terraform's internal data source identifier. It is structured as "`project_id`,`credentials_group_id`". +- `name` (String) The credentials group's display name. + +### Read-Only + +- `id` (String) Terraform's internal data source identifier. It is structured as "`project_id`,`credentials_group_id`". +- `urn` (String) Credentials group uniform resource name (URN) diff --git a/docs/resources/objectstorage_credentials_group.md b/docs/resources/objectstorage_credentials_group.md new file mode 100644 index 00000000..7732da13 --- /dev/null +++ b/docs/resources/objectstorage_credentials_group.md @@ -0,0 +1,27 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "stackit_objectstorage_credentials_group Resource - stackit" +subcategory: "" +description: |- + ObjectStorage credentials group resource schema. +--- + +# stackit_objectstorage_credentials_group (Resource) + +ObjectStorage credentials group resource schema. + + + + +## Schema + +### Required + +- `name` (String) The credentials group's display name. +- `project_id` (String) Project ID to which the credentials group is associated. + +### Read-Only + +- `credentials_group_id` (String) The credentials group ID +- `id` (String) Terraform's internal data source identifier. It is structured as "`project_id`,`credentials_group_id`". +- `urn` (String) Credentials group uniform resource name (URN) diff --git a/examples/data-sources/stackit_object_storage_bucket/data-source.tf b/examples/data-sources/stackit_object_storage_bucket/data-source.tf new file mode 100644 index 00000000..97201b7f --- /dev/null +++ b/examples/data-sources/stackit_object_storage_bucket/data-source.tf @@ -0,0 +1,4 @@ +data "stackit_objectstorage_bucket" "example" { + project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" + bucket_name = "example-name" +} diff --git a/examples/data-sources/stackit_object_storage_credentials_group/data-source.tf b/examples/data-sources/stackit_object_storage_credentials_group/data-source.tf new file mode 100644 index 00000000..250795f8 --- /dev/null +++ b/examples/data-sources/stackit_object_storage_credentials_group/data-source.tf @@ -0,0 +1,4 @@ +data "stackit_objectstorage_credentials_group" "example" { + project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" + credentials_group_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" +} diff --git a/examples/resources/stackit_object_storage_bucket/resource.tf b/examples/resources/stackit_object_storage_bucket/resource.tf new file mode 100644 index 00000000..47522ea6 --- /dev/null +++ b/examples/resources/stackit_object_storage_bucket/resource.tf @@ -0,0 +1,4 @@ +resource "stackit_object_storage_credentials_group" "example" { + project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" + name = "example-credentials-group" +} diff --git a/examples/resources/stackit_object_storage_credentials_group/resource.tf b/examples/resources/stackit_object_storage_credentials_group/resource.tf new file mode 100644 index 00000000..0b347866 --- /dev/null +++ b/examples/resources/stackit_object_storage_credentials_group/resource.tf @@ -0,0 +1,4 @@ +resource "stackit_object_storage_bucket" "example" { + project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" + bucket_name = "example-bucket" +} diff --git a/stackit/internal/services/objectstorage/bucket/resource.go b/stackit/internal/services/objectstorage/bucket/resource.go index f8f342fc..c44c66cd 100644 --- a/stackit/internal/services/objectstorage/bucket/resource.go +++ b/stackit/internal/services/objectstorage/bucket/resource.go @@ -94,7 +94,7 @@ func (r *bucketResource) Schema(_ context.Context, _ resource.SchemaRequest, res "main": "ObjectStorage bucket resource schema.", "id": "Terraform's internal resource identifier. It is structured as \"`project_id`,`bucket_name`\".", "bucket_name": "The bucket name. It must be DNS conform.", - "project_id": "STACKIT Project ID to which the bucket is associated to.", + "project_id": "STACKIT Project ID to which the bucket is associated.", "url_path_style": "URL in path style.", "url_virtual_hosted_style": "URL in virtual hosted style.", } @@ -158,7 +158,7 @@ func (r *bucketResource) Create(ctx context.Context, req resource.CreateRequest, // handle project init err := r.enableProject(ctx, &model) if resp.Diagnostics.HasError() { - core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating credentials group", fmt.Sprintf("Enabling object storage project before creation: %v", err)) + core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating bucket", fmt.Sprintf("Enabling object storage project before creation: %v", err)) return } diff --git a/stackit/internal/services/objectstorage/credentialsgroup/datasource.go b/stackit/internal/services/objectstorage/credentialsgroup/datasource.go index 1c13cad7..5667f9f8 100644 --- a/stackit/internal/services/objectstorage/credentialsgroup/datasource.go +++ b/stackit/internal/services/objectstorage/credentialsgroup/datasource.go @@ -32,7 +32,7 @@ type credentialsGroupDataSource struct { // Metadata returns the data source type name. func (r *credentialsGroupDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { - resp.TypeName = req.ProviderTypeName + "_objectstorage_credentialsgroup" + resp.TypeName = req.ProviderTypeName + "_objectstorage_credentials_group" } // Configure adds the provider configured client to the data source. @@ -78,7 +78,7 @@ func (r *credentialsGroupDataSource) Schema(_ context.Context, _ datasource.Sche "id": "Terraform's internal data source identifier. It is structured as \"`project_id`,`credentials_group_id`\".", "credentials_group_id": "The credentials group ID", "name": "The credentials group's display name.", - "project_id": "Object Storage Project ID to which the credentials group is associated to. It can be retrieved from `stackit_object_storage_project` ", + "project_id": "Object Storage Project ID to which the credentials group is associated.", "urn": "Credentials group uniform resource name (URN)", } diff --git a/stackit/internal/services/objectstorage/credentialsgroup/resource.go b/stackit/internal/services/objectstorage/credentialsgroup/resource.go index f4955fd2..63df720f 100644 --- a/stackit/internal/services/objectstorage/credentialsgroup/resource.go +++ b/stackit/internal/services/objectstorage/credentialsgroup/resource.go @@ -94,7 +94,7 @@ func (r *credentialsGroupResource) Schema(_ context.Context, _ resource.SchemaRe "id": "Terraform's internal data source identifier. It is structured as \"`project_id`,`credentials_group_id`\".", "credentials_group_id": "The credentials group ID", "name": "The credentials group's display name.", - "project_id": "Project ID to which the credentials group is associated to.", + "project_id": "Project ID to which the credentials group is associated.", "urn": "Credentials group uniform resource name (URN)", } @@ -270,7 +270,7 @@ func mapFields(credentialsGroupResp *objectstorage.CreateCredentialsGroupRespons } credentialsGroup := credentialsGroupResp.CredentialsGroup - model.Name = types.StringPointerValue(credentialsGroup.DisplayName) + model.CredentialsGroupId = types.StringPointerValue(credentialsGroup.CredentialsGroupId) model.URN = types.StringPointerValue(credentialsGroup.Urn) idParts := []string{ diff --git a/stackit/internal/services/objectstorage/objectstorage_acc_test.go b/stackit/internal/services/objectstorage/objectstorage_acc_test.go index 4650b9fa..fcdeb833 100644 --- a/stackit/internal/services/objectstorage/objectstorage_acc_test.go +++ b/stackit/internal/services/objectstorage/objectstorage_acc_test.go @@ -26,8 +26,8 @@ var bucketResource = map[string]string{ // Credentials group resource data var credentialsGroupResource = map[string]string{ - "project_id": testutil.ProjectId, - "credentials_group_name": fmt.Sprintf("acc-test-%s", acctest.RandStringFromCharSet(20, acctest.CharSetAlpha)), + "project_id": testutil.ProjectId, + "name": fmt.Sprintf("acc-test-%s", acctest.RandStringFromCharSet(20, acctest.CharSetAlpha)), } func resourceConfig() string { @@ -48,7 +48,7 @@ func resourceConfig() string { bucketResource["project_id"], bucketResource["bucket_name"], credentialsGroupResource["project_id"], - credentialsGroupResource["credentials_group_name"], + credentialsGroupResource["name"], ) } @@ -70,7 +70,7 @@ func TestAccObjectStorageResource(t *testing.T) { // Credentials group data resource.TestCheckResourceAttr("stackit_objectstorage_credentials_group.credentials_group", "project_id", credentialsGroupResource["project_id"]), - resource.TestCheckResourceAttr("stackit_objectstorage_credentials_group.credentials_group", "credentials_group_name", credentialsGroupResource["credentials_group_name"]), + resource.TestCheckResourceAttr("stackit_objectstorage_credentials_group.credentials_group", "name", credentialsGroupResource["name"]), resource.TestCheckResourceAttrSet("stackit_objectstorage_credentials_group.credentials_group", "credentials_group_id"), resource.TestCheckResourceAttrSet("stackit_objectstorage_credentials_group.credentials_group", "urn"), ), @@ -87,7 +87,7 @@ func TestAccObjectStorageResource(t *testing.T) { data "stackit_objectstorage_credentials_group" "credentials_group" { project_id = stackit_objectstorage_credentials_group.credentials_group.project_id - bucket_name = stackit_objectstorage_credentials_group.credentials_group.credentials_group_id + credentials_group_id = stackit_objectstorage_credentials_group.credentials_group.credentials_group_id }`, resourceConfig(), ), @@ -114,8 +114,8 @@ func TestAccObjectStorageResource(t *testing.T) { "data.stackit_objectstorage_credentials_group.credentials_group", "credentials_group_id", ), resource.TestCheckResourceAttrPair( - "stackit_objectstorage_credentials_group.credentials_group", "credentials_group_name", - "data.stackit_objectstorage_credentials_group.credentials_group", "credentials_group_name", + "stackit_objectstorage_credentials_group.credentials_group", "name", + "data.stackit_objectstorage_credentials_group.credentials_group", "name", ), resource.TestCheckResourceAttrPair( "stackit_objectstorage_credentials_group.credentials_group", "urn", From d2ace73945464300fd68c3284662b640692855bf Mon Sep 17 00:00:00 2001 From: vicentepinto98 Date: Tue, 10 Oct 2023 15:16:41 +0100 Subject: [PATCH 05/21] Refactor map fiels --- .../credentialsgroup/resource.go | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/stackit/internal/services/objectstorage/credentialsgroup/resource.go b/stackit/internal/services/objectstorage/credentialsgroup/resource.go index 63df720f..86a2372c 100644 --- a/stackit/internal/services/objectstorage/credentialsgroup/resource.go +++ b/stackit/internal/services/objectstorage/credentialsgroup/resource.go @@ -270,8 +270,14 @@ func mapFields(credentialsGroupResp *objectstorage.CreateCredentialsGroupRespons } credentialsGroup := credentialsGroupResp.CredentialsGroup + mapCredentialsGroup(credentialsGroup, model) + return nil +} + +func mapCredentialsGroup(credentialsGroup *objectstorage.CredentialsGroup, model *Model) { model.CredentialsGroupId = types.StringPointerValue(credentialsGroup.CredentialsGroupId) model.URN = types.StringPointerValue(credentialsGroup.Urn) + model.Name = types.StringPointerValue(credentialsGroup.DisplayName) idParts := []string{ model.ProjectId.ValueString(), @@ -280,7 +286,6 @@ func mapFields(credentialsGroupResp *objectstorage.CreateCredentialsGroupRespons model.Id = types.StringValue( strings.Join(idParts, core.Separator), ) - return nil } // enableProject enables object storage for the specified project. If the project already exists, nothing happens @@ -318,17 +323,7 @@ func readCredentialsGroups(ctx context.Context, model *Model, projectId string, continue } found = true - model.CredentialsGroupId = types.StringValue(*credentialsGroup.CredentialsGroupId) - model.Name = types.StringValue(*credentialsGroup.DisplayName) - model.URN = types.StringValue(*credentialsGroup.Urn) - - idParts := []string{ - model.ProjectId.ValueString(), - model.CredentialsGroupId.ValueString(), - } - model.Id = types.StringValue( - strings.Join(idParts, core.Separator), - ) + mapCredentialsGroup(&credentialsGroup, model) break } From e1b6d8885a748be100cbc67d04b3b126e305e6d3 Mon Sep 17 00:00:00 2001 From: vicentepinto98 Date: Tue, 10 Oct 2023 15:43:14 +0100 Subject: [PATCH 06/21] Add unit test for readCredentialsGroups --- .../credentialsgroup/resource.go | 9 +- .../credentialsgroup/resource_test.go | 147 ++++++++++++++++++ 2 files changed, 154 insertions(+), 2 deletions(-) diff --git a/stackit/internal/services/objectstorage/credentialsgroup/resource.go b/stackit/internal/services/objectstorage/credentialsgroup/resource.go index 86a2372c..3d9b723a 100644 --- a/stackit/internal/services/objectstorage/credentialsgroup/resource.go +++ b/stackit/internal/services/objectstorage/credentialsgroup/resource.go @@ -28,6 +28,11 @@ var ( _ resource.ResourceWithImportState = &credentialsGroupResource{} ) +// needed for testing +type objectStorageClient interface { + GetCredentialsGroupsExecute(ctx context.Context, projectId string) (*objectstorage.GetCredentialsGroupsResponse, error) +} + type Model struct { Id types.String `tfsdk:"id"` // needed by TF CredentialsGroupId types.String `tfsdk:"credentials_group_id"` @@ -302,14 +307,14 @@ func (r *credentialsGroupResource) enableProject(ctx context.Context, model *Mod // readCredentialsGroups gets all the existing credentials groups for the specified project, // finds the credentials group that is being read and updates the state. If the credentials group cannot be found, it throws an error -func readCredentialsGroups(ctx context.Context, model *Model, projectId string, client *objectstorage.APIClient) error { +func readCredentialsGroups(ctx context.Context, model *Model, projectId string, client objectStorageClient) error { found := false if model.CredentialsGroupId.ValueString() == "" && model.Name.ValueString() == "" { return fmt.Errorf("missing configuration: either name or credentials group id must be provided") } - credentialsGroupsResp, err := client.GetCredentialsGroups(ctx, projectId).Execute() + credentialsGroupsResp, err := client.GetCredentialsGroupsExecute(ctx, projectId) if err != nil { return fmt.Errorf("getting credentials groups: %w", err) } diff --git a/stackit/internal/services/objectstorage/credentialsgroup/resource_test.go b/stackit/internal/services/objectstorage/credentialsgroup/resource_test.go index bd8fc20d..c01a1581 100644 --- a/stackit/internal/services/objectstorage/credentialsgroup/resource_test.go +++ b/stackit/internal/services/objectstorage/credentialsgroup/resource_test.go @@ -1,6 +1,8 @@ package objectstorage import ( + "context" + "fmt" "testing" "github.com/google/go-cmp/cmp" @@ -9,6 +11,19 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/objectstorage" ) +type objectStorageClientMocked struct { + getCredentialsGroupsFails bool + getCredentialsGroupsResponse *objectstorage.GetCredentialsGroupsResponse +} + +func (c *objectStorageClientMocked) GetCredentialsGroupsExecute(ctx context.Context, projectId string) (*objectstorage.GetCredentialsGroupsResponse, error) { + if c.getCredentialsGroupsFails { + return c.getCredentialsGroupsResponse, fmt.Errorf("get credentials groups failed") + } + + return c.getCredentialsGroupsResponse, nil +} + func TestMapFields(t *testing.T) { tests := []struct { description string @@ -99,3 +114,135 @@ func TestMapFields(t *testing.T) { }) } } + +func TestReadCredentialsGroups(t *testing.T) { + tests := []struct { + description string + mockedResp *objectstorage.GetCredentialsGroupsResponse + expected Model + getCredentialsGroupsFails bool + isValid bool + }{ + { + "default_values", + &objectstorage.GetCredentialsGroupsResponse{ + CredentialsGroups: &[]objectstorage.CredentialsGroup{ + { + CredentialsGroupId: utils.Ptr("cid"), + }, + }, + }, + Model{ + Id: types.StringValue("pid,cid"), + Name: types.StringNull(), + ProjectId: types.StringValue("pid"), + CredentialsGroupId: types.StringValue("cid"), + URN: types.StringNull(), + }, + false, + true, + }, + { + "simple_values", + &objectstorage.GetCredentialsGroupsResponse{ + CredentialsGroups: &[]objectstorage.CredentialsGroup{ + { + CredentialsGroupId: utils.Ptr("cid"), + DisplayName: utils.Ptr("name"), + Urn: utils.Ptr("urn"), + }, + }, + }, + Model{ + Id: types.StringValue("pid,cid"), + Name: types.StringValue("name"), + ProjectId: types.StringValue("pid"), + CredentialsGroupId: types.StringValue("cid"), + URN: types.StringValue("urn"), + }, + false, + true, + }, + { + "empty_credentials_groups", + &objectstorage.GetCredentialsGroupsResponse{ + CredentialsGroups: &[]objectstorage.CredentialsGroup{}, + }, + Model{}, + false, + false, + }, + { + "nil_credentials_groups", + &objectstorage.GetCredentialsGroupsResponse{ + CredentialsGroups: nil, + }, + Model{}, + false, + false, + }, + { + "nil_response", + nil, + Model{}, + false, + false, + }, + { + "non_matching_credentials_group", + &objectstorage.GetCredentialsGroupsResponse{ + CredentialsGroups: &[]objectstorage.CredentialsGroup{ + { + CredentialsGroupId: utils.Ptr("other_id"), + DisplayName: utils.Ptr("name"), + Urn: utils.Ptr("urn"), + }, + }, + }, + Model{}, + false, + false, + }, + { + "error_response", + &objectstorage.GetCredentialsGroupsResponse{ + CredentialsGroups: &[]objectstorage.CredentialsGroup{ + { + CredentialsGroupId: utils.Ptr("other_id"), + DisplayName: utils.Ptr("name"), + Urn: utils.Ptr("urn"), + }, + }, + }, + Model{}, + true, + false, + }, + } + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + + client := &objectStorageClientMocked{ + getCredentialsGroupsFails: tt.getCredentialsGroupsFails, + getCredentialsGroupsResponse: tt.mockedResp, + } + model := &Model{ + ProjectId: tt.expected.ProjectId, + CredentialsGroupId: tt.expected.CredentialsGroupId, + } + err := readCredentialsGroups(context.Background(), model, "pid", client) + if !tt.isValid && err == nil { + t.Fatalf("Should have failed") + } + if tt.isValid && err != nil { + t.Fatalf("Should not have failed: %v", err) + } + if tt.isValid { + diff := cmp.Diff(model, &tt.expected) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + } + }) + } +} From 4f7351722442fab61668a90d10dc67c9caafab84 Mon Sep 17 00:00:00 2001 From: vicentepinto98 Date: Tue, 10 Oct 2023 15:48:43 +0100 Subject: [PATCH 07/21] =?UTF-8?q?Fix=20lint=20issues=C2=A7=20g?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../services/objectstorage/credentialsgroup/resource.go | 6 +++--- .../objectstorage/credentialsgroup/resource_test.go | 3 +-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/stackit/internal/services/objectstorage/credentialsgroup/resource.go b/stackit/internal/services/objectstorage/credentialsgroup/resource.go index 3d9b723a..0f4e64a5 100644 --- a/stackit/internal/services/objectstorage/credentialsgroup/resource.go +++ b/stackit/internal/services/objectstorage/credentialsgroup/resource.go @@ -275,11 +275,11 @@ func mapFields(credentialsGroupResp *objectstorage.CreateCredentialsGroupRespons } credentialsGroup := credentialsGroupResp.CredentialsGroup - mapCredentialsGroup(credentialsGroup, model) + mapCredentialsGroup(*credentialsGroup, model) return nil } -func mapCredentialsGroup(credentialsGroup *objectstorage.CredentialsGroup, model *Model) { +func mapCredentialsGroup(credentialsGroup objectstorage.CredentialsGroup, model *Model) { model.CredentialsGroupId = types.StringPointerValue(credentialsGroup.CredentialsGroupId) model.URN = types.StringPointerValue(credentialsGroup.Urn) model.Name = types.StringPointerValue(credentialsGroup.DisplayName) @@ -328,7 +328,7 @@ func readCredentialsGroups(ctx context.Context, model *Model, projectId string, continue } found = true - mapCredentialsGroup(&credentialsGroup, model) + mapCredentialsGroup(credentialsGroup, model) break } diff --git a/stackit/internal/services/objectstorage/credentialsgroup/resource_test.go b/stackit/internal/services/objectstorage/credentialsgroup/resource_test.go index c01a1581..dc4111c2 100644 --- a/stackit/internal/services/objectstorage/credentialsgroup/resource_test.go +++ b/stackit/internal/services/objectstorage/credentialsgroup/resource_test.go @@ -16,7 +16,7 @@ type objectStorageClientMocked struct { getCredentialsGroupsResponse *objectstorage.GetCredentialsGroupsResponse } -func (c *objectStorageClientMocked) GetCredentialsGroupsExecute(ctx context.Context, projectId string) (*objectstorage.GetCredentialsGroupsResponse, error) { +func (c *objectStorageClientMocked) GetCredentialsGroupsExecute(_ context.Context, _ string) (*objectstorage.GetCredentialsGroupsResponse, error) { if c.getCredentialsGroupsFails { return c.getCredentialsGroupsResponse, fmt.Errorf("get credentials groups failed") } @@ -221,7 +221,6 @@ func TestReadCredentialsGroups(t *testing.T) { } for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - client := &objectStorageClientMocked{ getCredentialsGroupsFails: tt.getCredentialsGroupsFails, getCredentialsGroupsResponse: tt.mockedResp, From 65361839da4eb2096b6cca608c7cc02ad315bb1a Mon Sep 17 00:00:00 2001 From: vicentepinto98 Date: Tue, 10 Oct 2023 15:53:17 +0100 Subject: [PATCH 08/21] Use projectId from Model --- .../services/objectstorage/credentialsgroup/resource.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stackit/internal/services/objectstorage/credentialsgroup/resource.go b/stackit/internal/services/objectstorage/credentialsgroup/resource.go index 0f4e64a5..8da8ac32 100644 --- a/stackit/internal/services/objectstorage/credentialsgroup/resource.go +++ b/stackit/internal/services/objectstorage/credentialsgroup/resource.go @@ -203,7 +203,7 @@ func (r *credentialsGroupResource) Read(ctx context.Context, req resource.ReadRe ctx = tflog.SetField(ctx, "project_id", projectId) ctx = tflog.SetField(ctx, "credentials_group_id", credentialsGroupId) - err := readCredentialsGroups(ctx, &model, projectId, r.client) + err := readCredentialsGroups(ctx, &model, r.client) if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading credentialsGroup", fmt.Sprintf("getting credential group from list of credentials groups: %v", err)) return @@ -307,14 +307,14 @@ func (r *credentialsGroupResource) enableProject(ctx context.Context, model *Mod // readCredentialsGroups gets all the existing credentials groups for the specified project, // finds the credentials group that is being read and updates the state. If the credentials group cannot be found, it throws an error -func readCredentialsGroups(ctx context.Context, model *Model, projectId string, client objectStorageClient) error { +func readCredentialsGroups(ctx context.Context, model *Model, client objectStorageClient) error { found := false if model.CredentialsGroupId.ValueString() == "" && model.Name.ValueString() == "" { return fmt.Errorf("missing configuration: either name or credentials group id must be provided") } - credentialsGroupsResp, err := client.GetCredentialsGroupsExecute(ctx, projectId) + credentialsGroupsResp, err := client.GetCredentialsGroupsExecute(ctx, model.ProjectId.ValueString()) if err != nil { return fmt.Errorf("getting credentials groups: %w", err) } From 944be414cfe4042bf5a49198ee1b9daefe5edae3 Mon Sep 17 00:00:00 2001 From: vicentepinto98 Date: Tue, 10 Oct 2023 15:53:57 +0100 Subject: [PATCH 09/21] =?UTF-8?q?Fix=20errors=C2=A7=20g?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../services/objectstorage/credentialsgroup/datasource.go | 2 +- .../services/objectstorage/credentialsgroup/resource_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/stackit/internal/services/objectstorage/credentialsgroup/datasource.go b/stackit/internal/services/objectstorage/credentialsgroup/datasource.go index 5667f9f8..5d576e77 100644 --- a/stackit/internal/services/objectstorage/credentialsgroup/datasource.go +++ b/stackit/internal/services/objectstorage/credentialsgroup/datasource.go @@ -128,7 +128,7 @@ func (r *credentialsGroupDataSource) Read(ctx context.Context, req datasource.Re ctx = tflog.SetField(ctx, "project_id", projectId) ctx = tflog.SetField(ctx, "credentials_group_id", credentialsGroupId) - err := readCredentialsGroups(ctx, &model, projectId, r.client) + err := readCredentialsGroups(ctx, &model, r.client) if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading credentialsGroup", fmt.Sprintf("getting credential group from list of credentials groups: %v", err)) return diff --git a/stackit/internal/services/objectstorage/credentialsgroup/resource_test.go b/stackit/internal/services/objectstorage/credentialsgroup/resource_test.go index dc4111c2..a653e564 100644 --- a/stackit/internal/services/objectstorage/credentialsgroup/resource_test.go +++ b/stackit/internal/services/objectstorage/credentialsgroup/resource_test.go @@ -229,7 +229,7 @@ func TestReadCredentialsGroups(t *testing.T) { ProjectId: tt.expected.ProjectId, CredentialsGroupId: tt.expected.CredentialsGroupId, } - err := readCredentialsGroups(context.Background(), model, "pid", client) + err := readCredentialsGroups(context.Background(), model, client) if !tt.isValid && err == nil { t.Fatalf("Should have failed") } From e921ee34480bd3f5cd86a0f8f8de89aeea00c778 Mon Sep 17 00:00:00 2001 From: vicentepinto98 Date: Tue, 10 Oct 2023 16:06:29 +0100 Subject: [PATCH 10/21] Fix test --- .../internal/services/objectstorage/credentialsgroup/resource.go | 1 - 1 file changed, 1 deletion(-) diff --git a/stackit/internal/services/objectstorage/credentialsgroup/resource.go b/stackit/internal/services/objectstorage/credentialsgroup/resource.go index 8da8ac32..6425447e 100644 --- a/stackit/internal/services/objectstorage/credentialsgroup/resource.go +++ b/stackit/internal/services/objectstorage/credentialsgroup/resource.go @@ -280,7 +280,6 @@ func mapFields(credentialsGroupResp *objectstorage.CreateCredentialsGroupRespons } func mapCredentialsGroup(credentialsGroup objectstorage.CredentialsGroup, model *Model) { - model.CredentialsGroupId = types.StringPointerValue(credentialsGroup.CredentialsGroupId) model.URN = types.StringPointerValue(credentialsGroup.Urn) model.Name = types.StringPointerValue(credentialsGroup.DisplayName) From 6044f10dcd801aec93cf351d184fccae851f5a50 Mon Sep 17 00:00:00 2001 From: Henrique Santos Date: Wed, 11 Oct 2023 17:08:38 +0100 Subject: [PATCH 11/21] Simplify signature of enableProject --- .../services/objectstorage/bucket/resource.go | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/stackit/internal/services/objectstorage/bucket/resource.go b/stackit/internal/services/objectstorage/bucket/resource.go index c44c66cd..1f10471e 100644 --- a/stackit/internal/services/objectstorage/bucket/resource.go +++ b/stackit/internal/services/objectstorage/bucket/resource.go @@ -155,8 +155,8 @@ func (r *bucketResource) Create(ctx context.Context, req resource.CreateRequest, ctx = tflog.SetField(ctx, "project_id", projectId) ctx = tflog.SetField(ctx, "bucket_name", bucketName) - // handle project init - err := r.enableProject(ctx, &model) + // Handle project init + err := enableProject(ctx, &model, r.client) if resp.Diagnostics.HasError() { core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating bucket", fmt.Sprintf("Enabling object storage project before creation: %v", err)) return @@ -302,12 +302,16 @@ func mapFields(bucketResp *objectstorage.GetBucketResponse, model *Model) error return nil } +type objectStorageClient interface { + CreateProjectExecute(ctx context.Context, projectId string) (*objectstorage.GetProjectResponse, error) +} + // enableProject enables object storage for the specified project. If the project already exists, nothing happens -func (r *bucketResource) enableProject(ctx context.Context, model *Model) error { +func enableProject(ctx context.Context, model *Model, client objectStorageClient) error { projectId := model.ProjectId.ValueString() // From the object storage OAS: Creation will also be successful if the project already exists, but will not create a duplicate - _, err := r.client.CreateProject(ctx, projectId).Execute() + _, err := client.CreateProjectExecute(ctx, projectId) if err != nil { return fmt.Errorf("failed to create object storage project: %w", err) } From 113a8b1ee18b2768d0b3eba47dc99b9c78a5fc4e Mon Sep 17 00:00:00 2001 From: Henrique Santos Date: Wed, 11 Oct 2023 17:10:23 +0100 Subject: [PATCH 12/21] Change comment --- stackit/internal/services/objectstorage/bucket/resource.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stackit/internal/services/objectstorage/bucket/resource.go b/stackit/internal/services/objectstorage/bucket/resource.go index 1f10471e..fd3c4b7f 100644 --- a/stackit/internal/services/objectstorage/bucket/resource.go +++ b/stackit/internal/services/objectstorage/bucket/resource.go @@ -306,11 +306,11 @@ type objectStorageClient interface { CreateProjectExecute(ctx context.Context, projectId string) (*objectstorage.GetProjectResponse, error) } -// enableProject enables object storage for the specified project. If the project already exists, nothing happens +// enableProject enables object storage for the specified project. If the project is already enabled, nothing happens func enableProject(ctx context.Context, model *Model, client objectStorageClient) error { projectId := model.ProjectId.ValueString() - // From the object storage OAS: Creation will also be successful if the project already exists, but will not create a duplicate + // From the object storage OAS: Creation will also be successful if the project is already enabled, but will not create a duplicate _, err := client.CreateProjectExecute(ctx, projectId) if err != nil { return fmt.Errorf("failed to create object storage project: %w", err) From 891124d5bb5d6ce969111d05108334e799cd717f Mon Sep 17 00:00:00 2001 From: Henrique Santos Date: Wed, 11 Oct 2023 17:19:26 +0100 Subject: [PATCH 13/21] Add TestEnableProject --- .../objectstorage/bucket/resource_test.go | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/stackit/internal/services/objectstorage/bucket/resource_test.go b/stackit/internal/services/objectstorage/bucket/resource_test.go index 3330d7d8..fa110dc2 100644 --- a/stackit/internal/services/objectstorage/bucket/resource_test.go +++ b/stackit/internal/services/objectstorage/bucket/resource_test.go @@ -1,6 +1,8 @@ package objectstorage import ( + "context" + "fmt" "testing" "github.com/google/go-cmp/cmp" @@ -9,6 +11,19 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/objectstorage" ) +type objectStorageClientMocked struct { + enableFails bool + createProjectExecuteResp *objectstorage.GetProjectResponse +} + +func (c *objectStorageClientMocked) CreateProjectExecute(_ context.Context, _ string) (*objectstorage.GetProjectResponse, error) { + if c.enableFails { + return nil, fmt.Errorf("create project failed") + } + + return c.createProjectExecuteResp, nil +} + func TestMapFields(t *testing.T) { tests := []struct { description string @@ -99,3 +114,72 @@ func TestMapFields(t *testing.T) { }) } } + +func TestEnableProject(t *testing.T) { + tests := []struct { + description string + mockedResp *objectstorage.GetProjectResponse + expected Model + enableFails bool + isValid bool + }{ + { + "default_values", + &objectstorage.GetProjectResponse{}, + Model{ + Id: types.StringValue("pid,bname"), + BucketName: types.StringValue("bname"), + ProjectId: types.StringValue("pid"), + URLPathStyle: types.StringNull(), + URLVirtualHostedStyle: types.StringNull(), + }, + false, + true, + }, + { + "nil_response", + nil, + Model{ + Id: types.StringValue("pid,bname"), + BucketName: types.StringValue("bname"), + ProjectId: types.StringValue("pid"), + URLPathStyle: types.StringNull(), + URLVirtualHostedStyle: types.StringNull(), + }, + false, + true, + }, + { + "error_response", + &objectstorage.GetProjectResponse{}, + Model{ + Id: types.StringValue("pid,bname"), + BucketName: types.StringValue("bname"), + ProjectId: types.StringValue("pid"), + URLPathStyle: types.StringNull(), + URLVirtualHostedStyle: types.StringNull(), + }, + true, + false, + }, + } + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + client := &objectStorageClientMocked{ + enableFails: tt.enableFails, + createProjectExecuteResp: tt.mockedResp, + } + model := &Model{ + ProjectId: tt.expected.ProjectId, + BucketName: tt.expected.BucketName, + } + err := enableProject(context.Background(), model, client) + if !tt.isValid && err == nil { + t.Fatalf("Should have failed") + } + if tt.isValid && err != nil { + t.Fatalf("Should not have failed: %v", err) + } + }) + } +} From d4c2c0ccd88336342c9cf8be4a0d3de1aa9d49a2 Mon Sep 17 00:00:00 2001 From: Henrique Santos Date: Wed, 11 Oct 2023 17:20:12 +0100 Subject: [PATCH 14/21] Rename variable --- .../internal/services/objectstorage/bucket/resource_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stackit/internal/services/objectstorage/bucket/resource_test.go b/stackit/internal/services/objectstorage/bucket/resource_test.go index fa110dc2..e91ce4ed 100644 --- a/stackit/internal/services/objectstorage/bucket/resource_test.go +++ b/stackit/internal/services/objectstorage/bucket/resource_test.go @@ -12,12 +12,12 @@ import ( ) type objectStorageClientMocked struct { - enableFails bool + returnError bool createProjectExecuteResp *objectstorage.GetProjectResponse } func (c *objectStorageClientMocked) CreateProjectExecute(_ context.Context, _ string) (*objectstorage.GetProjectResponse, error) { - if c.enableFails { + if c.returnError { return nil, fmt.Errorf("create project failed") } @@ -166,7 +166,7 @@ func TestEnableProject(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { client := &objectStorageClientMocked{ - enableFails: tt.enableFails, + returnError: tt.enableFails, createProjectExecuteResp: tt.mockedResp, } model := &Model{ From dc14043b1ca220c052a68f3b30d0c2e29b25c2f3 Mon Sep 17 00:00:00 2001 From: Henrique Santos Date: Wed, 11 Oct 2023 17:25:49 +0100 Subject: [PATCH 15/21] Add enableProject test --- .../credentialsgroup/resource.go | 22 ++--- .../credentialsgroup/resource_test.go | 92 +++++++++++++++++-- 2 files changed, 96 insertions(+), 18 deletions(-) diff --git a/stackit/internal/services/objectstorage/credentialsgroup/resource.go b/stackit/internal/services/objectstorage/credentialsgroup/resource.go index 6425447e..7fdb21f3 100644 --- a/stackit/internal/services/objectstorage/credentialsgroup/resource.go +++ b/stackit/internal/services/objectstorage/credentialsgroup/resource.go @@ -28,11 +28,6 @@ var ( _ resource.ResourceWithImportState = &credentialsGroupResource{} ) -// needed for testing -type objectStorageClient interface { - GetCredentialsGroupsExecute(ctx context.Context, projectId string) (*objectstorage.GetCredentialsGroupsResponse, error) -} - type Model struct { Id types.String `tfsdk:"id"` // needed by TF CredentialsGroupId types.String `tfsdk:"credentials_group_id"` @@ -162,8 +157,8 @@ func (r *credentialsGroupResource) Create(ctx context.Context, req resource.Crea DisplayName: utils.Ptr(credentialsGroupName), } - // handle project init - err := r.enableProject(ctx, &model) + // Handle project init + err := enableProject(ctx, &model, r.client) if resp.Diagnostics.HasError() { core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating credentials group", fmt.Sprintf("Enabling object storage project before creation: %v", err)) return @@ -292,12 +287,17 @@ func mapCredentialsGroup(credentialsGroup objectstorage.CredentialsGroup, model ) } -// enableProject enables object storage for the specified project. If the project already exists, nothing happens -func (r *credentialsGroupResource) enableProject(ctx context.Context, model *Model) error { +type objectStorageClient interface { + CreateProjectExecute(ctx context.Context, projectId string) (*objectstorage.GetProjectResponse, error) + GetCredentialsGroupsExecute(ctx context.Context, projectId string) (*objectstorage.GetCredentialsGroupsResponse, error) +} + +// enableProject enables object storage for the specified project. If the project is already enabled, nothing happens +func enableProject(ctx context.Context, model *Model, client objectStorageClient) error { projectId := model.ProjectId.ValueString() - // From the object storage OAS: Creation will also be successful if the project already exists, but will not create a duplicate - _, err := r.client.CreateProject(ctx, projectId).Execute() + // From the object storage OAS: Creation will also be successful if the project is already enabled, but will not create a duplicate + _, err := client.CreateProjectExecute(ctx, projectId) if err != nil { return fmt.Errorf("failed to create object storage project: %w", err) } diff --git a/stackit/internal/services/objectstorage/credentialsgroup/resource_test.go b/stackit/internal/services/objectstorage/credentialsgroup/resource_test.go index a653e564..ac4b48db 100644 --- a/stackit/internal/services/objectstorage/credentialsgroup/resource_test.go +++ b/stackit/internal/services/objectstorage/credentialsgroup/resource_test.go @@ -12,16 +12,25 @@ import ( ) type objectStorageClientMocked struct { - getCredentialsGroupsFails bool - getCredentialsGroupsResponse *objectstorage.GetCredentialsGroupsResponse + returnError bool + createProjectExecuteResp *objectstorage.GetProjectResponse + getCredentialsGroupsResp *objectstorage.GetCredentialsGroupsResponse +} + +func (c *objectStorageClientMocked) CreateProjectExecute(_ context.Context, _ string) (*objectstorage.GetProjectResponse, error) { + if c.returnError { + return nil, fmt.Errorf("get credentials groups failed") + } + + return c.createProjectExecuteResp, nil } func (c *objectStorageClientMocked) GetCredentialsGroupsExecute(_ context.Context, _ string) (*objectstorage.GetCredentialsGroupsResponse, error) { - if c.getCredentialsGroupsFails { - return c.getCredentialsGroupsResponse, fmt.Errorf("get credentials groups failed") + if c.returnError { + return nil, fmt.Errorf("get credentials groups failed") } - return c.getCredentialsGroupsResponse, nil + return c.getCredentialsGroupsResp, nil } func TestMapFields(t *testing.T) { @@ -115,6 +124,75 @@ func TestMapFields(t *testing.T) { } } +func TestEnableProject(t *testing.T) { + tests := []struct { + description string + mockedResp *objectstorage.GetProjectResponse + expected Model + enableFails bool + isValid bool + }{ + { + "default_values", + &objectstorage.GetProjectResponse{}, + Model{ + Id: types.StringValue("pid,cid"), + Name: types.StringNull(), + ProjectId: types.StringValue("pid"), + CredentialsGroupId: types.StringValue("cid"), + URN: types.StringNull(), + }, + false, + true, + }, + { + "nil_response", + nil, + Model{ + Id: types.StringValue("pid,cid"), + Name: types.StringNull(), + ProjectId: types.StringValue("pid"), + CredentialsGroupId: types.StringValue("cid"), + URN: types.StringNull(), + }, + false, + true, + }, + { + "error_response", + &objectstorage.GetProjectResponse{}, + Model{ + Id: types.StringValue("pid,cid"), + Name: types.StringNull(), + ProjectId: types.StringValue("pid"), + CredentialsGroupId: types.StringValue("cid"), + URN: types.StringNull(), + }, + true, + false, + }, + } + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + client := &objectStorageClientMocked{ + returnError: tt.enableFails, + createProjectExecuteResp: tt.mockedResp, + } + model := &Model{ + ProjectId: tt.expected.ProjectId, + CredentialsGroupId: tt.expected.CredentialsGroupId, + } + err := enableProject(context.Background(), model, client) + if !tt.isValid && err == nil { + t.Fatalf("Should have failed") + } + if tt.isValid && err != nil { + t.Fatalf("Should not have failed: %v", err) + } + }) + } +} + func TestReadCredentialsGroups(t *testing.T) { tests := []struct { description string @@ -222,8 +300,8 @@ func TestReadCredentialsGroups(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { client := &objectStorageClientMocked{ - getCredentialsGroupsFails: tt.getCredentialsGroupsFails, - getCredentialsGroupsResponse: tt.mockedResp, + returnError: tt.getCredentialsGroupsFails, + getCredentialsGroupsResp: tt.mockedResp, } model := &Model{ ProjectId: tt.expected.ProjectId, From 728911ab221ae628020309eda13a04625dd7acad Mon Sep 17 00:00:00 2001 From: Henrique Santos Date: Wed, 11 Oct 2023 17:46:15 +0100 Subject: [PATCH 16/21] Remove unused test setting --- .../objectstorage/bucket/resource_test.go | 28 +------------------ .../credentialsgroup/resource_test.go | 28 +------------------ 2 files changed, 2 insertions(+), 54 deletions(-) diff --git a/stackit/internal/services/objectstorage/bucket/resource_test.go b/stackit/internal/services/objectstorage/bucket/resource_test.go index e91ce4ed..cb716150 100644 --- a/stackit/internal/services/objectstorage/bucket/resource_test.go +++ b/stackit/internal/services/objectstorage/bucket/resource_test.go @@ -119,46 +119,24 @@ func TestEnableProject(t *testing.T) { tests := []struct { description string mockedResp *objectstorage.GetProjectResponse - expected Model enableFails bool isValid bool }{ { "default_values", &objectstorage.GetProjectResponse{}, - Model{ - Id: types.StringValue("pid,bname"), - BucketName: types.StringValue("bname"), - ProjectId: types.StringValue("pid"), - URLPathStyle: types.StringNull(), - URLVirtualHostedStyle: types.StringNull(), - }, false, true, }, { "nil_response", nil, - Model{ - Id: types.StringValue("pid,bname"), - BucketName: types.StringValue("bname"), - ProjectId: types.StringValue("pid"), - URLPathStyle: types.StringNull(), - URLVirtualHostedStyle: types.StringNull(), - }, false, true, }, { "error_response", &objectstorage.GetProjectResponse{}, - Model{ - Id: types.StringValue("pid,bname"), - BucketName: types.StringValue("bname"), - ProjectId: types.StringValue("pid"), - URLPathStyle: types.StringNull(), - URLVirtualHostedStyle: types.StringNull(), - }, true, false, }, @@ -169,11 +147,7 @@ func TestEnableProject(t *testing.T) { returnError: tt.enableFails, createProjectExecuteResp: tt.mockedResp, } - model := &Model{ - ProjectId: tt.expected.ProjectId, - BucketName: tt.expected.BucketName, - } - err := enableProject(context.Background(), model, client) + err := enableProject(context.Background(), &Model{}, client) if !tt.isValid && err == nil { t.Fatalf("Should have failed") } diff --git a/stackit/internal/services/objectstorage/credentialsgroup/resource_test.go b/stackit/internal/services/objectstorage/credentialsgroup/resource_test.go index ac4b48db..491416c9 100644 --- a/stackit/internal/services/objectstorage/credentialsgroup/resource_test.go +++ b/stackit/internal/services/objectstorage/credentialsgroup/resource_test.go @@ -128,46 +128,24 @@ func TestEnableProject(t *testing.T) { tests := []struct { description string mockedResp *objectstorage.GetProjectResponse - expected Model enableFails bool isValid bool }{ { "default_values", &objectstorage.GetProjectResponse{}, - Model{ - Id: types.StringValue("pid,cid"), - Name: types.StringNull(), - ProjectId: types.StringValue("pid"), - CredentialsGroupId: types.StringValue("cid"), - URN: types.StringNull(), - }, false, true, }, { "nil_response", nil, - Model{ - Id: types.StringValue("pid,cid"), - Name: types.StringNull(), - ProjectId: types.StringValue("pid"), - CredentialsGroupId: types.StringValue("cid"), - URN: types.StringNull(), - }, false, true, }, { "error_response", &objectstorage.GetProjectResponse{}, - Model{ - Id: types.StringValue("pid,cid"), - Name: types.StringNull(), - ProjectId: types.StringValue("pid"), - CredentialsGroupId: types.StringValue("cid"), - URN: types.StringNull(), - }, true, false, }, @@ -178,11 +156,7 @@ func TestEnableProject(t *testing.T) { returnError: tt.enableFails, createProjectExecuteResp: tt.mockedResp, } - model := &Model{ - ProjectId: tt.expected.ProjectId, - CredentialsGroupId: tt.expected.CredentialsGroupId, - } - err := enableProject(context.Background(), model, client) + err := enableProject(context.Background(), &Model{}, client) if !tt.isValid && err == nil { t.Fatalf("Should have failed") } From f7275636fe9537956648cbe04c5bb25e8930d671 Mon Sep 17 00:00:00 2001 From: Henrique Santos Date: Wed, 11 Oct 2023 17:46:47 +0100 Subject: [PATCH 17/21] Fix wrong error message --- .../services/objectstorage/credentialsgroup/resource_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stackit/internal/services/objectstorage/credentialsgroup/resource_test.go b/stackit/internal/services/objectstorage/credentialsgroup/resource_test.go index 491416c9..7fcabdfe 100644 --- a/stackit/internal/services/objectstorage/credentialsgroup/resource_test.go +++ b/stackit/internal/services/objectstorage/credentialsgroup/resource_test.go @@ -19,7 +19,7 @@ type objectStorageClientMocked struct { func (c *objectStorageClientMocked) CreateProjectExecute(_ context.Context, _ string) (*objectstorage.GetProjectResponse, error) { if c.returnError { - return nil, fmt.Errorf("get credentials groups failed") + return nil, fmt.Errorf("create project failed") } return c.createProjectExecuteResp, nil From 2cd43f5d5672a5ce5d78c6543373c95a7dc78377 Mon Sep 17 00:00:00 2001 From: Henrique Santos Date: Wed, 11 Oct 2023 18:14:32 +0100 Subject: [PATCH 18/21] Improve test case, rename mocked data --- .../credentialsgroup/resource_test.go | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/stackit/internal/services/objectstorage/credentialsgroup/resource_test.go b/stackit/internal/services/objectstorage/credentialsgroup/resource_test.go index 7fcabdfe..67927a44 100644 --- a/stackit/internal/services/objectstorage/credentialsgroup/resource_test.go +++ b/stackit/internal/services/objectstorage/credentialsgroup/resource_test.go @@ -182,6 +182,9 @@ func TestReadCredentialsGroups(t *testing.T) { { CredentialsGroupId: utils.Ptr("cid"), }, + { + CredentialsGroupId: utils.Ptr("foo-id"), + }, }, }, Model{ @@ -203,6 +206,11 @@ func TestReadCredentialsGroups(t *testing.T) { DisplayName: utils.Ptr("name"), Urn: utils.Ptr("urn"), }, + { + CredentialsGroupId: utils.Ptr("foo-cid"), + DisplayName: utils.Ptr("foo-name"), + Urn: utils.Ptr("urnfoo-"), + }, }, }, Model{ @@ -245,9 +253,9 @@ func TestReadCredentialsGroups(t *testing.T) { &objectstorage.GetCredentialsGroupsResponse{ CredentialsGroups: &[]objectstorage.CredentialsGroup{ { - CredentialsGroupId: utils.Ptr("other_id"), - DisplayName: utils.Ptr("name"), - Urn: utils.Ptr("urn"), + CredentialsGroupId: utils.Ptr("foo-other"), + DisplayName: utils.Ptr("foo-name"), + Urn: utils.Ptr("foo-urn"), }, }, }, From f7b7c45af8315bda803463862d601de8773628e0 Mon Sep 17 00:00:00 2001 From: Henrique Santos Date: Thu, 12 Oct 2023 09:27:39 +0100 Subject: [PATCH 19/21] Fix typo --- .../services/objectstorage/credentialsgroup/resource_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stackit/internal/services/objectstorage/credentialsgroup/resource_test.go b/stackit/internal/services/objectstorage/credentialsgroup/resource_test.go index 67927a44..922c59e1 100644 --- a/stackit/internal/services/objectstorage/credentialsgroup/resource_test.go +++ b/stackit/internal/services/objectstorage/credentialsgroup/resource_test.go @@ -209,7 +209,7 @@ func TestReadCredentialsGroups(t *testing.T) { { CredentialsGroupId: utils.Ptr("foo-cid"), DisplayName: utils.Ptr("foo-name"), - Urn: utils.Ptr("urnfoo-"), + Urn: utils.Ptr("foo-urn"), }, }, }, From 3789e0f932f2be633dbfc2ce1332798e6b287116 Mon Sep 17 00:00:00 2001 From: Henrique Santos Date: Thu, 12 Oct 2023 09:31:11 +0100 Subject: [PATCH 20/21] Removed unnecessary test case --- .../credentialsgroup/resource_test.go | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/stackit/internal/services/objectstorage/credentialsgroup/resource_test.go b/stackit/internal/services/objectstorage/credentialsgroup/resource_test.go index 922c59e1..635b55fe 100644 --- a/stackit/internal/services/objectstorage/credentialsgroup/resource_test.go +++ b/stackit/internal/services/objectstorage/credentialsgroup/resource_test.go @@ -13,16 +13,17 @@ import ( type objectStorageClientMocked struct { returnError bool - createProjectExecuteResp *objectstorage.GetProjectResponse getCredentialsGroupsResp *objectstorage.GetCredentialsGroupsResponse } -func (c *objectStorageClientMocked) CreateProjectExecute(_ context.Context, _ string) (*objectstorage.GetProjectResponse, error) { +func (c *objectStorageClientMocked) CreateProjectExecute(_ context.Context, projectId string) (*objectstorage.GetProjectResponse, error) { if c.returnError { return nil, fmt.Errorf("create project failed") } - return c.createProjectExecuteResp, nil + return &objectstorage.GetProjectResponse{ + Project: utils.Ptr(projectId), + }, nil } func (c *objectStorageClientMocked) GetCredentialsGroupsExecute(_ context.Context, _ string) (*objectstorage.GetCredentialsGroupsResponse, error) { @@ -127,25 +128,16 @@ func TestMapFields(t *testing.T) { func TestEnableProject(t *testing.T) { tests := []struct { description string - mockedResp *objectstorage.GetProjectResponse enableFails bool isValid bool }{ { "default_values", - &objectstorage.GetProjectResponse{}, - false, - true, - }, - { - "nil_response", - nil, false, true, }, { "error_response", - &objectstorage.GetProjectResponse{}, true, false, }, @@ -153,8 +145,7 @@ func TestEnableProject(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { client := &objectStorageClientMocked{ - returnError: tt.enableFails, - createProjectExecuteResp: tt.mockedResp, + returnError: tt.enableFails, } err := enableProject(context.Background(), &Model{}, client) if !tt.isValid && err == nil { From 3f8c3c2ead6c85838d457c4a01937d7cb5d5e238 Mon Sep 17 00:00:00 2001 From: Henrique Santos Date: Thu, 12 Oct 2023 09:31:58 +0100 Subject: [PATCH 21/21] Removed unnecessary test case --- .../objectstorage/bucket/resource_test.go | 21 ++++++------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/stackit/internal/services/objectstorage/bucket/resource_test.go b/stackit/internal/services/objectstorage/bucket/resource_test.go index cb716150..aee118e6 100644 --- a/stackit/internal/services/objectstorage/bucket/resource_test.go +++ b/stackit/internal/services/objectstorage/bucket/resource_test.go @@ -12,16 +12,17 @@ import ( ) type objectStorageClientMocked struct { - returnError bool - createProjectExecuteResp *objectstorage.GetProjectResponse + returnError bool } -func (c *objectStorageClientMocked) CreateProjectExecute(_ context.Context, _ string) (*objectstorage.GetProjectResponse, error) { +func (c *objectStorageClientMocked) CreateProjectExecute(_ context.Context, projectId string) (*objectstorage.GetProjectResponse, error) { if c.returnError { return nil, fmt.Errorf("create project failed") } - return c.createProjectExecuteResp, nil + return &objectstorage.GetProjectResponse{ + Project: utils.Ptr(projectId), + }, nil } func TestMapFields(t *testing.T) { @@ -118,25 +119,16 @@ func TestMapFields(t *testing.T) { func TestEnableProject(t *testing.T) { tests := []struct { description string - mockedResp *objectstorage.GetProjectResponse enableFails bool isValid bool }{ { "default_values", - &objectstorage.GetProjectResponse{}, - false, - true, - }, - { - "nil_response", - nil, false, true, }, { "error_response", - &objectstorage.GetProjectResponse{}, true, false, }, @@ -144,8 +136,7 @@ func TestEnableProject(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { client := &objectStorageClientMocked{ - returnError: tt.enableFails, - createProjectExecuteResp: tt.mockedResp, + returnError: tt.enableFails, } err := enableProject(context.Background(), &Model{}, client) if !tt.isValid && err == nil {