diff --git a/.golangci.yml b/.golangci.yml index 4c9a24d..f51eded 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -9,9 +9,9 @@ linters: - gofmt - staticcheck - revive -# - godot -# - whitespace -# - goimports + - godot + - whitespace + - goimports - gosimple - errcheck - unconvert @@ -40,16 +40,13 @@ issues: linters: - gosec exclude: - - "should have a package comment" - "var-naming:.*Id.* should be .*ID" - "var-naming:.*Api.* should be .*API" - "var-naming:.*Http.* should be .*HTTP" - "exported: exported .* should have comment" - "exported: comment on exported .* should be of the form" - - "var-naming: don't use an underscore in package name" - "unused-parameter:" - "ifElseChain:" - "var-naming:.*ALL_CAPS.*" - "superfluous-else" - - "package-comments:" - "Error return value of .* is not checked" diff --git a/internal/acctest/acctest.go b/internal/acctest/acctest.go index 3ab5aca..0f0bf3b 100644 --- a/internal/acctest/acctest.go +++ b/internal/acctest/acctest.go @@ -1,3 +1,4 @@ +// Package acctest provides a harness for our acceptance tests and test sweepers. package acctest import ( diff --git a/internal/provider/folder/data_source.go b/internal/provider/folder/data_source.go index 5da5a6e..6efa2cd 100644 --- a/internal/provider/folder/data_source.go +++ b/internal/provider/folder/data_source.go @@ -1,3 +1,4 @@ +// Package folder provides implementation of the Folder resource and Folders data source. package folder import ( @@ -8,6 +9,7 @@ import ( "github.com/hashicorp/terraform-plugin-framework/datasource/schema" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/tryretool/terraform-provider-retool/internal/provider/utils" "github.com/tryretool/terraform-provider-retool/internal/sdk/api" ) @@ -133,7 +135,7 @@ func (d *foldersDataSource) Read(ctx context.Context, req datasource.ReadRequest } } - // Set state + // Set state. diags := resp.State.Set(ctx, &state) resp.Diagnostics.Append(diags...) if resp.Diagnostics.HasError() { diff --git a/internal/provider/folder/data_source_test.go b/internal/provider/folder/data_source_test.go index 3e6f681..f7b8e55 100644 --- a/internal/provider/folder/data_source_test.go +++ b/internal/provider/folder/data_source_test.go @@ -7,6 +7,7 @@ import ( "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/terraform" + "github.com/tryretool/terraform-provider-retool/internal/acctest" ) diff --git a/internal/provider/folder/resource.go b/internal/provider/folder/resource.go index 2ec9cc5..aa00c51 100644 --- a/internal/provider/folder/resource.go +++ b/internal/provider/folder/resource.go @@ -15,6 +15,7 @@ import ( "github.com/hashicorp/terraform-plugin-framework/schema/validator" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/tryretool/terraform-provider-retool/internal/provider/utils" "github.com/tryretool/terraform-provider-retool/internal/sdk/api" ) @@ -103,7 +104,7 @@ func (r *folderResource) Schema(_ context.Context, _ resource.SchemaRequest, res Required: true, Description: "The type of the folder: (app|file|resource|workflow).", PlanModifiers: []planmodifier.String{ - stringplanmodifier.RequiresReplace(), // Changing the folder type requires replacing the resource + stringplanmodifier.RequiresReplace(), // Changing the folder type requires replacing the resource. }, Validators: []validator.String{ stringvalidator.OneOf("app", "file", "resource", "workflow"), @@ -115,7 +116,7 @@ func (r *folderResource) Schema(_ context.Context, _ resource.SchemaRequest, res func (r *folderResource) getTrueParentFolderId(ctx context.Context, folderType, parentFolderId string, diags *diag.Diagnostics) string { if parentFolderId == ROOT_FOLDER_ID { - // Get root folder ID + // Get root folder ID. rootFolderId, err := getRootFolderId(ctx, folderType, r.client, r.rootFolderIdCache) if err != nil { diags.AddError( @@ -131,7 +132,7 @@ func (r *folderResource) getTrueParentFolderId(ctx context.Context, folderType, // Create creates the resource and sets the initial Terraform state. func (r *folderResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { - // Retrieve values from plan + // Retrieve values from plan. var plan folderModel diags := req.Plan.Get(ctx, &plan) resp.Diagnostics.Append(diags...) @@ -139,7 +140,7 @@ func (r *folderResource) Create(ctx context.Context, req resource.CreateRequest, return } - // Generate API request body from plan + // Generate API request body from plan. var folder api.FoldersPostRequest parentFolderId := r.getTrueParentFolderId(ctx, plan.FolderType.ValueString(), plan.ParentFolderId.ValueString(), &resp.Diagnostics) if resp.Diagnostics.HasError() { @@ -151,7 +152,7 @@ func (r *folderResource) Create(ctx context.Context, req resource.CreateRequest, folder.FolderType = plan.FolderType.ValueString() tflog.Info(ctx, "Creating a folder", map[string]any{"name": plan.Name.ValueString(), "folderType": plan.FolderType.ValueString(), "parentFolderId": parentFolderId}) - // Create new folder + // Create new folder. response, httpResponse, err := r.client.FoldersAPI.FoldersPost(ctx).FoldersPostRequest(folder).Execute() if err != nil { @@ -164,12 +165,12 @@ func (r *folderResource) Create(ctx context.Context, req resource.CreateRequest, } tflog.Info(ctx, "Folder created", map[string]any{"id": response.Data.Id, "legacyId": response.Data.LegacyId, "isSystemFolder": response.Data.IsSystemFolder}) - // Map response body to schema and populate Computed attribute values + // Map response body to schema and populate Computed attribute values. plan.Id = types.StringValue(response.Data.Id) plan.LegacyId = types.StringValue(response.Data.LegacyId) plan.IsSystemFolder = types.BoolValue(response.Data.IsSystemFolder) - // Set state to fully populated data + // Set state to fully populated data. diags = resp.State.Set(ctx, plan) resp.Diagnostics.Append(diags...) if resp.Diagnostics.HasError() { @@ -179,7 +180,7 @@ func (r *folderResource) Create(ctx context.Context, req resource.CreateRequest, // Read resource information. func (r *folderResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { - // Get current state + // Get current state. var state folderModel diags := req.State.Get(ctx, &state) resp.Diagnostics.Append(diags...) @@ -187,7 +188,7 @@ func (r *folderResource) Read(ctx context.Context, req resource.ReadRequest, res return } - // Get refreshed folder value from Retool API + // Get refreshed folder value from Retool API. tflog.Info(ctx, "Reading folder", map[string]any{"id": state.Id}) response, httpResponse, err := r.client.FoldersAPI.FoldersFolderIdGet(ctx, state.Id.ValueString()).Execute() if err != nil { @@ -204,10 +205,10 @@ func (r *folderResource) Read(ctx context.Context, req resource.ReadRequest, res return } - // Update the state + // Update the state. state.LegacyId = types.StringValue(response.Data.LegacyId) state.Name = types.StringValue(response.Data.Name) - // To keep the state consistent, we need to convert the root folder ID to the string constant ROOT_FOLDER_ID + // To keep the state consistent, we need to convert the root folder ID to the string constant ROOT_FOLDER_ID. state.ParentFolderId = types.StringPointerValue(maybeReplaceRootFolderIdWithConstant(ctx, response.Data.FolderType, response.Data.ParentFolderId.Get(), r.client, r.rootFolderIdCache, &resp.Diagnostics)) state.IsSystemFolder = types.BoolValue(response.Data.IsSystemFolder) state.FolderType = types.StringValue(response.Data.FolderType) @@ -215,7 +216,7 @@ func (r *folderResource) Read(ctx context.Context, req resource.ReadRequest, res return } - // Set refreshed state + // Set refreshed state. diags = resp.State.Set(ctx, &state) resp.Diagnostics.Append(diags...) if resp.Diagnostics.HasError() { @@ -240,12 +241,12 @@ func (r *folderResource) Update(ctx context.Context, req resource.UpdateRequest, } if plan.Name.Equal(state.Name) && plan.ParentFolderId.Equal(state.ParentFolderId) { - // No changes + // No changes. tflog.Info(ctx, "No changes detected for folder", map[string]any{"id": state.Id}) return } - // Generate API request body + // Generate API request body. patchReq := api.FoldersFolderIdPatchRequest{} if !plan.Name.Equal(state.Name) { op := api.NewUsersUserIdPatchRequestOperationsInnerAnyOf("replace", "/name") @@ -280,7 +281,7 @@ func (r *folderResource) Update(ctx context.Context, req resource.UpdateRequest, // Delete deletes the resource and removes the Terraform state on success. func (r *folderResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { - // Retrieve values from state + // Retrieve values from state. var state folderModel diags := req.State.Get(ctx, &state) resp.Diagnostics.Append(diags...) @@ -288,13 +289,13 @@ func (r *folderResource) Delete(ctx context.Context, req resource.DeleteRequest, return } - // Delete existing order + // Delete existing order. recursive := true deleteRequest := api.FoldersFolderIdDeleteRequest{} deleteRequest.Recursive = &recursive httpResponse, err := r.client.FoldersAPI.FoldersFolderIdDelete(ctx, state.Id.ValueString()).FoldersFolderIdDeleteRequest(deleteRequest).Execute() - if err != nil && !(httpResponse != nil && httpResponse.StatusCode == 404) { // it's ok to not find the resource being deleted + if err != nil && !(httpResponse != nil && httpResponse.StatusCode == 404) { // It's ok to not find the resource being deleted. resp.Diagnostics.AddError( "Error Deleting Folder", "Could not delete folder"+state.Id.ValueString()+", unexpected error: "+err.Error(), @@ -305,6 +306,6 @@ func (r *folderResource) Delete(ctx context.Context, req resource.DeleteRequest, } func (r *folderResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { - // Retrieve import ID and save to id attribute + // Retrieve import ID and save to id attribute. resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp) } diff --git a/internal/provider/folder/resource_test.go b/internal/provider/folder/resource_test.go index 968588f..d096bcf 100644 --- a/internal/provider/folder/resource_test.go +++ b/internal/provider/folder/resource_test.go @@ -9,6 +9,7 @@ import ( "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/tryretool/terraform-provider-retool/internal/acctest" "github.com/tryretool/terraform-provider-retool/internal/sdk/api" ) @@ -86,7 +87,7 @@ func init() { func TestAccFolder(t *testing.T) { acctest.Test(t, resource.TestCase{ Steps: []resource.TestStep{ - // Read and Create + // Read and Create. { Config: testFolderConfig, Check: resource.ComposeTestCheckFunc( @@ -105,13 +106,13 @@ func TestAccFolder(t *testing.T) { resource.TestCheckResourceAttrSet("retool_folder.child_folder", "legacy_id"), ), }, - // Import state + // Import state. { ResourceName: "retool_folder.test_folder", ImportState: true, ImportStateVerify: true, }, - // Update and Read + // Update and Read. { Config: testUpdatedFolderConfig, Check: resource.ComposeTestCheckFunc( diff --git a/internal/provider/folder/root_folder_utils.go b/internal/provider/folder/root_folder_utils.go index 31583b7..a5cbf81 100644 --- a/internal/provider/folder/root_folder_utils.go +++ b/internal/provider/folder/root_folder_utils.go @@ -6,6 +6,7 @@ import ( "github.com/hashicorp/terraform-plugin-framework/diag" "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/tryretool/terraform-provider-retool/internal/provider/utils" "github.com/tryretool/terraform-provider-retool/internal/sdk/api" ) diff --git a/internal/provider/group/resource.go b/internal/provider/group/resource.go index 6719582..f560bb2 100644 --- a/internal/provider/group/resource.go +++ b/internal/provider/group/resource.go @@ -1,3 +1,4 @@ +// Package group provides the implementation of the Group resource. package group import ( @@ -15,23 +16,24 @@ import ( "github.com/hashicorp/terraform-plugin-framework/schema/validator" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/tryretool/terraform-provider-retool/internal/provider/utils" "github.com/tryretool/terraform-provider-retool/internal/sdk/api" ) -// Ensure GroupResource implements the tfsdk.Resource interface +// Ensure GroupResource implements the tfsdk.Resource interface. var ( _ resource.Resource = &groupResource{} _ resource.ResourceWithConfigure = &groupResource{} _ resource.ResourceWithImportState = &groupResource{} ) -// groupResource schema structure +// groupResource schema structure. type groupResource struct { client *api.APIClient } -// groupResourceModel defines the data model for the Group resource +// groupResourceModel defines the data model for the Group resource. type groupResourceModel struct { Id types.String `tfsdk:"id"` LegacyId types.String `tfsdk:"legacy_id"` @@ -70,12 +72,12 @@ func (r *groupResource) Configure(_ context.Context, req resource.ConfigureReque r.client = providerData.Client } -// Metadata associated with the Group resource +// Metadata associated with the Group resource. func (r *groupResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { resp.TypeName = req.ProviderTypeName + "_group" } -// Schema returns the schema for the Group resource +// Schema returns the schema for the Group resource. func (r *groupResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { resp.Schema = schema.Schema{ Attributes: map[string]schema.Attribute{ @@ -173,7 +175,7 @@ func (r *groupResource) Schema(ctx context.Context, req resource.SchemaRequest, // Create creates the group resource and sets the initial Terraform state. func (r *groupResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { - // Retrieve values from plan + // Retrieve values from plan. var plan groupResourceModel diags := req.Plan.Get(ctx, &plan) resp.Diagnostics.Append(diags...) @@ -181,7 +183,7 @@ func (r *groupResource) Create(ctx context.Context, req resource.CreateRequest, return } - // Generate API request body from plan + // Generate API request body from plan. var group api.GroupsPostRequest group.Name = plan.Name.ValueString() group.UniversalAppAccess = plan.UniversalAppAccess.ValueStringPointer() @@ -199,7 +201,7 @@ func (r *groupResource) Create(ctx context.Context, req resource.CreateRequest, tflog.Info(ctx, "Creating a group", map[string]interface{}{"name": plan.Name.ValueString()}) - // Create new group + // Create new group. response, httpResponse, err := r.client.GroupsAPI.GroupsPost(ctx).GroupsPostRequest(group).Execute() if err != nil { resp.Diagnostics.AddError( @@ -219,11 +221,11 @@ func (r *groupResource) Create(ctx context.Context, req resource.CreateRequest, return } - // Map response body to schema and populate Computed attribute values + // Map response body to schema and populate Computed attribute values. plan.Id = types.StringValue(utils.Float32PtrToIntString(response.Data.Id.Get())) plan.LegacyId = types.StringValue(utils.Float32PtrToIntString(response.Data.LegacyId.Get())) - // Set state to fully populated data + // Set state to fully populated data. diags = resp.State.Set(ctx, plan) resp.Diagnostics.Append(diags...) if resp.Diagnostics.HasError() { @@ -234,7 +236,7 @@ func (r *groupResource) Create(ctx context.Context, req resource.CreateRequest, tflog.Info(ctx, "Group created", map[string]interface{}{"id": response.Data.Id.Get(), "legacyId": response.Data.LegacyId.Get()}) } -// Read a Group resource +// Read a Group resource. func (r *groupResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { var state groupResourceModel diags := req.State.Get(ctx, &state) @@ -243,7 +245,7 @@ func (r *groupResource) Read(ctx context.Context, req resource.ReadRequest, resp return } - // Use the ID from the state to read the group + // Use the ID from the state to read the group. groupID := state.Id.ValueString() group, httpResponse, err := r.client.GroupsAPI.GroupsGroupIdGet(ctx, groupID).Execute() if err != nil { @@ -260,7 +262,7 @@ func (r *groupResource) Read(ctx context.Context, req resource.ReadRequest, resp return } - // Map the API response to the Terraform state + // Map the API response to the Terraform state. state.Id = types.StringValue(utils.Float32PtrToIntString(group.Data.Id.Get())) state.LegacyId = types.StringValue(utils.Float32PtrToIntString(group.Data.LegacyId.Get())) state.Name = types.StringValue(group.Data.Name) @@ -282,7 +284,7 @@ func (r *groupResource) Read(ctx context.Context, req resource.ReadRequest, resp } } -// Update a Group resource +// Update a Group resource. func (r *groupResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { var plan groupResourceModel diags := req.Plan.Get(ctx, &plan) @@ -310,7 +312,7 @@ func (r *groupResource) Update(ctx context.Context, req resource.UpdateRequest, return } - // Prepare the update payload + // Prepare the update payload. updatePayload := api.GroupsGroupIdPutRequest{ Name: plan.Name.ValueStringPointer(), UniversalAppAccess: plan.UniversalAppAccess.ValueStringPointer(), @@ -327,7 +329,7 @@ func (r *groupResource) Update(ctx context.Context, req resource.UpdateRequest, } updatePayload.LandingPageAppId.Set(plan.LandingPageAppId.ValueStringPointer()) - // Perform the update operation + // Perform the update operation. _, httpResponse, err = r.client.GroupsAPI.GroupsGroupIdPut(ctx, groupID).GroupsGroupIdPutRequest(updatePayload).Execute() if err != nil { resp.Diagnostics.AddError( @@ -356,7 +358,7 @@ func convertGroupMembersToPutRequestType(responseMembers []api.GroupsGroupIdGet2 return members } -// Delete a Group resource +// Delete a Group resource. func (r *groupResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { var state groupResourceModel diags := req.State.Get(ctx, &state) @@ -367,7 +369,7 @@ func (r *groupResource) Delete(ctx context.Context, req resource.DeleteRequest, groupId := state.Id.ValueString() httpResponse, err := r.client.GroupsAPI.GroupsGroupIdDelete(ctx, groupId).Execute() - if err != nil && !(httpResponse != nil && httpResponse.StatusCode == 404) { // it's ok to not find the group when deleting + if err != nil && !(httpResponse != nil && httpResponse.StatusCode == 404) { // It's ok to not find the group when deleting. resp.Diagnostics.AddError( "Error Deleting Group", "Could not delete group with ID "+groupId+": "+err.Error(), @@ -377,8 +379,8 @@ func (r *groupResource) Delete(ctx context.Context, req resource.DeleteRequest, } } -// ImportState allows importing of a Group resource +// ImportState allows importing of a Group resource. func (r *groupResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { - // Retrieve import ID and save to id attribute + // Retrieve import ID and save to id attribute. resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp) } diff --git a/internal/provider/group/resource_schema_test.go b/internal/provider/group/resource_schema_test.go index 45abc07..df70148 100644 --- a/internal/provider/group/resource_schema_test.go +++ b/internal/provider/group/resource_schema_test.go @@ -6,7 +6,7 @@ import ( // The fwresource import alias is so there is no collistion // with the more typical acceptance testing import: - // "github.com/hashicorp/terraform-plugin-testing/helper/resource" + // "github.com/hashicorp/terraform-plugin-testing/helper/resource". fwresource "github.com/hashicorp/terraform-plugin-framework/resource" ) @@ -17,14 +17,14 @@ func TestGroupResourceSchema(t *testing.T) { schemaRequest := fwresource.SchemaRequest{} schemaResponse := &fwresource.SchemaResponse{} - // Instantiate the resource.Resource and call its Schema method + // Instantiate the resource.Resource and call its Schema method. NewResource().Schema(ctx, schemaRequest, schemaResponse) if schemaResponse.Diagnostics.HasError() { t.Fatalf("Schema method diagnostics: %+v", schemaResponse.Diagnostics) } - // Validate the schema + // Validate the schema. diagnostics := schemaResponse.Schema.ValidateImplementation(ctx) if diagnostics.HasError() { diff --git a/internal/provider/group/resource_test.go b/internal/provider/group/resource_test.go index f33325e..8dd8d02 100644 --- a/internal/provider/group/resource_test.go +++ b/internal/provider/group/resource_test.go @@ -8,6 +8,7 @@ import ( "testing" "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/tryretool/terraform-provider-retool/internal/acctest" "github.com/tryretool/terraform-provider-retool/internal/provider/utils" ) @@ -25,7 +26,7 @@ const testGroupConfig = ` usage_analytics_access = true account_details_access = true } - ` // not testing landing_page_app_id because it has to match an existing app id, which is hard to achieve when hitting random Retool instance + ` // Not testing landing_page_app_id because it has to match an existing app id, which is hard to achieve when hitting random Retool instance. const testUpdatedGroupConfig = ` resource "retool_group" "test_group" { @@ -55,7 +56,7 @@ func TestMain(m *testing.M) { func TestAccGroup(t *testing.T) { acctest.Test(t, resource.TestCase{ Steps: []resource.TestStep{ - // Read and Create + // Read and Create. { Config: testGroupConfig, Check: resource.ComposeTestCheckFunc( @@ -74,13 +75,13 @@ func TestAccGroup(t *testing.T) { resource.TestCheckNoResourceAttr("retool_group.test_group", "landing_page_app_id"), ), }, - // Import state + // Import state. { ResourceName: "retool_group.test_group", ImportState: true, ImportStateVerify: true, }, - // Update and Read + // Update and Read. { Config: testUpdatedGroupConfig, Check: resource.ComposeTestCheckFunc( @@ -99,7 +100,7 @@ func TestAccGroup(t *testing.T) { resource.TestCheckNoResourceAttr("retool_group.test_group", "landing_page_app_id"), ), }, - // Check default values + // Check default values. { Config: testDefaultValuesConfig, Check: resource.ComposeTestCheckFunc( diff --git a/internal/provider/permissions/resource.go b/internal/provider/permissions/resource.go index e07d619..9d76cb4 100644 --- a/internal/provider/permissions/resource.go +++ b/internal/provider/permissions/resource.go @@ -1,3 +1,4 @@ +// Package permissions provides the implementation of the Permissions resource. package permissions import ( @@ -16,22 +17,23 @@ import ( "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-plugin-framework/types/basetypes" "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/tryretool/terraform-provider-retool/internal/provider/utils" "github.com/tryretool/terraform-provider-retool/internal/sdk/api" ) -// Ensure GroupResource implements the tfsdk.Resource interface +// Ensure GroupResource implements the tfsdk.Resource interface. var ( _ resource.Resource = &permissionResource{} _ resource.ResourceWithConfigure = &permissionResource{} - // Note that unlike other resources, we don't implement ResourceWithImportState here, because there's not much to import for permission + // Note that unlike other resources, we don't implement ResourceWithImportState here, because there's not much to import for permission. ) type permissionResource struct { client *api.APIClient } -// The key is a combination of subject type and id +// The key is a combination of subject type and id. type permissionsResourceModel struct { Subject types.Object `tfsdk:"subject"` Permissions []permissionModel `tfsdk:"permissions"` @@ -54,7 +56,7 @@ func (m permissionObjectModel) AttributeTypes() map[string]attr.Type { } } -// A model for a single permission for a given subject +// A model for a single permission for a given subject. type permissionModel struct { Object types.Object `tfsdk:"object"` AccessLevel types.String `tfsdk:"access_level"` @@ -92,14 +94,14 @@ func (r *permissionResource) Schema(ctx context.Context, req resource.SchemaRequ Required: true, Description: "The ID of the subject.", PlanModifiers: []planmodifier.String{ - stringplanmodifier.RequiresReplace(), // Changing the subject of permission requires replacing it + stringplanmodifier.RequiresReplace(), // Changing the subject of permission requires replacing it. }, }, "type": schema.StringAttribute{ Required: true, Description: "The type of the subject - user or group.", PlanModifiers: []planmodifier.String{ - stringplanmodifier.RequiresReplace(), // Changing the subject of permission requires replacing it + stringplanmodifier.RequiresReplace(), // Changing the subject of permission requires replacing it. }, Validators: []validator.String{ stringvalidator.OneOf("user", "group"), @@ -151,7 +153,7 @@ func createNewApiPermissionsSubject(subjectModel permissionSubjectModel) api.Per if err != nil { return api.PermissionsListObjectsPostRequestSubject{} } - floatGroupId := float32(groupId) // our client uses float32 to represent "number" ids + floatGroupId := float32(groupId) // Our client uses float32 to represent "number" ids. subject.PermissionsListObjectsPostRequestSubjectOneOf = api.NewPermissionsListObjectsPostRequestSubjectOneOf("group", *api.NewNullableFloat32(&floatGroupId)) } else if subjectModel.Type.ValueString() == "user" { subject.PermissionsListObjectsPostRequestSubjectOneOf1 = api.NewPermissionsListObjectsPostRequestSubjectOneOf1("user", subjectModel.Id.ValueString()) @@ -170,7 +172,7 @@ func getPermissionId(subject permissionSubjectModel, object permissionObjectMode return subject.Type.ValueString() + "|" + subject.Id.ValueString() + "|" + object.Type.ValueString() + "|" + object.Id.ValueString() } -// Make an API call to revoke a permission +// Make an API call to revoke a permission. func (r *permissionResource) revokePermission(ctx context.Context, subject permissionSubjectModel, permission permissionModel) diag.Diagnostics { var object permissionObjectModel @@ -196,7 +198,7 @@ func (r *permissionResource) revokePermission(ctx context.Context, subject permi return diags } -// Make an API call to grant a permission +// Make an API call to grant a permission. func (r *permissionResource) grantPermission(ctx context.Context, subject permissionSubjectModel, permission permissionModel) diag.Diagnostics { var object permissionObjectModel @@ -205,10 +207,10 @@ func (r *permissionResource) grantPermission(ctx context.Context, subject permis return diags } - // only used for logging + // Only used for logging. permissionId := getPermissionId(subject, object) - // Generate API request body from plan + // Generate API request body from plan. apiSubject := createNewApiPermissionsSubject(subject) apiObject := createNewApiPermissionsObject(object) @@ -216,7 +218,7 @@ func (r *permissionResource) grantPermission(ctx context.Context, subject permis tflog.Info(ctx, "Creating a permission", map[string]interface{}{"id": permissionId, "access level": permission.AccessLevel.ValueString()}) - // Grant the permission + // Grant the permission. _, httpResponse, err := r.client.PermissionsAPI.PermissionsGrantPost(ctx).PermissionsGrantPostRequest(*grantRequest).Execute() if err != nil { diags.AddError( @@ -231,7 +233,7 @@ func (r *permissionResource) grantPermission(ctx context.Context, subject permis } func (r *permissionResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { - // Retrieve values from plan + // Retrieve values from plan. var plan permissionsResourceModel var planSubject permissionSubjectModel @@ -256,7 +258,7 @@ func (r *permissionResource) Create(ctx context.Context, req resource.CreateRequ } } - // Set state to fully populated data + // Set state to fully populated data. diags = resp.State.Set(ctx, plan) resp.Diagnostics.Append(diags...) if resp.Diagnostics.HasError() { @@ -286,7 +288,7 @@ func (r *permissionResource) Read(ctx context.Context, req resource.ReadRequest, subjectId := stateSubject.Id.ValueString() + "|" + stateSubject.Type.ValueString() - // We'll need to get all the permissions for the given subject + // We'll need to get all the permissions for the given subject. for _, objectType := range []string{"app", "folder", "resource", "resource_configuration"} { request := api.NewPermissionsListObjectsPostRequest(createNewApiPermissionsSubject(stateSubject), objectType) @@ -302,7 +304,7 @@ func (r *permissionResource) Read(ctx context.Context, req resource.ReadRequest, return } - // Now let's populate the state with permissions based on our API response + // Now let's populate the state with permissions based on our API response. for _, obj := range permissionsResponse.Data { var objId string var accessLevel string @@ -340,7 +342,7 @@ type objectKey struct { Type string } -// Converts a list of permissions to a map of permissions by object, for quick lookup +// Converts a list of permissions to a map of permissions by object, for quick lookup. func mapPermissionsByOjbect(ctx context.Context, permissions []permissionModel) (map[objectKey]permissionModel, diag.Diagnostics) { permissionsByObject := make(map[objectKey]permissionModel) var allDiags diag.Diagnostics @@ -364,7 +366,7 @@ type permissionDiff struct { func computePermissionDiff(ctx context.Context, statePermissions []permissionModel, planPermissions []permissionModel) (permissionDiff, diag.Diagnostics) { var diff permissionDiff - // Maps to hold the sets of permissions for quick lookup + // Maps to hold the sets of permissions for quick lookup. stateMap, diags := mapPermissionsByOjbect(ctx, statePermissions) if diags.HasError() { return diff, diags @@ -374,14 +376,14 @@ func computePermissionDiff(ctx context.Context, statePermissions []permissionMod return diff, diags } - // Find permissions to revoke (in state but not in plan) + // Find permissions to revoke (in state but not in plan). for key, statePerm := range stateMap { if _, found := planMap[key]; !found { diff.Revoke = append(diff.Revoke, statePerm) } } - // Find permissions to grant (in plan but not in state) + // Find permissions to grant (in plan but not in state). for key, planPerm := range planMap { if statePerm, found := stateMap[key]; !found || statePerm.AccessLevel.ValueString() != planPerm.AccessLevel.ValueString() { diff.Grant = append(diff.Grant, planPerm) @@ -424,7 +426,7 @@ func (r *permissionResource) Update(ctx context.Context, req resource.UpdateRequ subjectId := stateSubject.Id.ValueString() + "|" + stateSubject.Type.ValueString() tflog.Info(ctx, "Revoking old permissions", map[string]any{"subject_id": subjectId}) - // Revoke old permissions + // Revoke old permissions. for _, perm := range diff.Revoke { diags = r.revokePermission(ctx, stateSubject, perm) resp.Diagnostics.Append(diags...) @@ -434,7 +436,7 @@ func (r *permissionResource) Update(ctx context.Context, req resource.UpdateRequ } tflog.Info(ctx, "Granting new permissions", map[string]any{"subject_id": subjectId}) - // Grant new permissions + // Grant new permissions. for _, perm := range diff.Grant { diags = r.grantPermission(ctx, stateSubject, perm) resp.Diagnostics.Append(diags...) diff --git a/internal/provider/permissions/resource_schema_test.go b/internal/provider/permissions/resource_schema_test.go index 545a4c4..523fdf4 100644 --- a/internal/provider/permissions/resource_schema_test.go +++ b/internal/provider/permissions/resource_schema_test.go @@ -6,7 +6,7 @@ import ( // The fwresource import alias is so there is no collistion // with the more typical acceptance testing import: - // "github.com/hashicorp/terraform-plugin-testing/helper/resource" + // "github.com/hashicorp/terraform-plugin-testing/helper/resource". fwresource "github.com/hashicorp/terraform-plugin-framework/resource" ) @@ -17,14 +17,14 @@ func TestPermissionsResourceSchema(t *testing.T) { schemaRequest := fwresource.SchemaRequest{} schemaResponse := &fwresource.SchemaResponse{} - // Instantiate the resource.Resource and call its Schema method + // Instantiate the resource.Resource and call its Schema method. NewResource().Schema(ctx, schemaRequest, schemaResponse) if schemaResponse.Diagnostics.HasError() { t.Fatalf("Schema method diagnostics: %+v", schemaResponse.Diagnostics) } - // Validate the schema + // Validate the schema. diagnostics := schemaResponse.Schema.ValidateImplementation(ctx) if diagnostics.HasError() { diff --git a/internal/provider/permissions/resource_test.go b/internal/provider/permissions/resource_test.go index a4d7caa..984da8e 100644 --- a/internal/provider/permissions/resource_test.go +++ b/internal/provider/permissions/resource_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/tryretool/terraform-provider-retool/internal/acctest" ) @@ -81,7 +82,7 @@ func TestMain(m *testing.M) { func TestAccPermissions(t *testing.T) { acctest.Test(t, resource.TestCase{ Steps: []resource.TestStep{ - // Read and Create + // Read and Create. { Config: testPermissionsConfig, Check: resource.ComposeAggregateTestCheckFunc( @@ -93,7 +94,7 @@ func TestAccPermissions(t *testing.T) { resource.TestCheckResourceAttr("retool_permissions.test_permissions", "permissions.0.access_level", "use"), ), }, - // Update and Read + // Update and Read. { Config: testUpdatedPermissionsConfig, Check: resource.ComposeAggregateTestCheckFunc( @@ -107,5 +108,4 @@ func TestAccPermissions(t *testing.T) { }, }, }) - } diff --git a/internal/provider/provider.go b/internal/provider/provider.go index c8728bd..127bc6f 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -1,3 +1,4 @@ +// Package provider provides the implementation of the Retool Terraform provider. package provider import ( @@ -19,8 +20,8 @@ import ( "github.com/tryretool/terraform-provider-retool/internal/provider/folder" "github.com/tryretool/terraform-provider-retool/internal/provider/group" "github.com/tryretool/terraform-provider-retool/internal/provider/permissions" - "github.com/tryretool/terraform-provider-retool/internal/provider/source_control" - "github.com/tryretool/terraform-provider-retool/internal/provider/source_control_settings" + "github.com/tryretool/terraform-provider-retool/internal/provider/sourcecontrol" + "github.com/tryretool/terraform-provider-retool/internal/provider/sourcecontrolsettings" "github.com/tryretool/terraform-provider-retool/internal/provider/space" "github.com/tryretool/terraform-provider-retool/internal/provider/sso" "github.com/tryretool/terraform-provider-retool/internal/provider/utils" @@ -54,7 +55,7 @@ func NewWithHttpClient(version string, httpClient *http.Client) func() provider. // retoolProvider is the provider implementation. type retoolProvider struct { - // version is set to the provider version on release, "dev" when the + // Version is set to the provider version on release, "dev" when the // provider is built and ran locally, and "test" when running acceptance // testing. version string @@ -99,7 +100,7 @@ type HealthCheckResponse struct { } func checkMinimalVersion(ctx context.Context, host string, scheme string) bool { - // Create HTTP client, make GET /api/checkHealth request, parse the version field out of the JSON response + // Create HTTP client, make GET /api/checkHealth request, parse the version field out of the JSON response. httpResponse, err := http.Get(scheme + "://" + host + "/api/checkHealth") if err != nil { tflog.Error(ctx, "Failed to check Retool version", map[string]any{"error": err}) @@ -107,14 +108,14 @@ func checkMinimalVersion(ctx context.Context, host string, scheme string) bool { } defer httpResponse.Body.Close() - // Read the response body + // Read the response body. body, err := io.ReadAll(httpResponse.Body) if err != nil { tflog.Error(ctx, "Failed to read response body", map[string]any{"error": err}) return false } - // Parse the JSON response + // Parse the JSON response. var healthCheck HealthCheckResponse err = json.Unmarshal(body, &healthCheck) if err != nil { @@ -129,7 +130,7 @@ func checkMinimalVersion(ctx context.Context, host string, scheme string) bool { // Configure prepares a Retool API client for data sources and resources. func (p *retoolProvider) Configure(ctx context.Context, req provider.ConfigureRequest, resp *provider.ConfigureResponse) { tflog.Info(ctx, "Configuring Retool API client") - // Retrieve provider data from configuration + // Retrieve provider data from configuration. var config retoolProviderModel diags := req.Config.Get(ctx, &config) resp.Diagnostics.Append(diags...) @@ -213,7 +214,7 @@ func (p *retoolProvider) Configure(ctx context.Context, req provider.ConfigureRe } // We only check the minimum version if there's no HTTP client override - // This is a hacky way to avoid doing the check when running acceptance tests in "record" or "replay" mode + // This is a hacky way to avoid doing the check when running acceptance tests in "record" or "replay" mode. if p.httpClient == nil && !checkMinimalVersion(ctx, host, scheme) { resp.Diagnostics.AddError("Incompatible Retool version", "The Retool instance version is not supported. Minimum version required is "+MINIMUM_RETOOL_VERSION) return @@ -227,7 +228,7 @@ func (p *retoolProvider) Configure(ctx context.Context, req provider.ConfigureRe URL: "/api/v2", }, } - // We need this to be able to record and replay HTTP interactions in the acceptance tests + // We need this to be able to record and replay HTTP interactions in the acceptance tests. if p.httpClient != nil { clientConfig.HTTPClient = p.httpClient } @@ -262,7 +263,7 @@ func (p *retoolProvider) Resources(_ context.Context) []func() resource.Resource permissions.NewResource, space.NewResource, sso.NewResource, - source_control.NewResource, - source_control_settings.NewResource, + sourcecontrol.NewResource, + sourcecontrolsettings.NewResource, } } diff --git a/internal/provider/source_control/resource.go b/internal/provider/sourcecontrol/resource.go similarity index 97% rename from internal/provider/source_control/resource.go rename to internal/provider/sourcecontrol/resource.go index 46b76e6..b436ae7 100644 --- a/internal/provider/source_control/resource.go +++ b/internal/provider/sourcecontrol/resource.go @@ -1,4 +1,5 @@ -package source_control +// Package sourcecontrol provides implementation of the Source Control resource. +package sourcecontrol import ( "context" @@ -14,11 +15,12 @@ import ( "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-plugin-framework/types/basetypes" "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/tryretool/terraform-provider-retool/internal/provider/utils" "github.com/tryretool/terraform-provider-retool/internal/sdk/api" ) -// Ensure sourceControlResource implements the tfsdk.Resource interface +// Ensure sourceControlResource implements the tfsdk.Resource interface. var ( _ resource.Resource = &sourceControlResource{} _ resource.ResourceWithConfigure = &sourceControlResource{} @@ -160,12 +162,12 @@ func (r *sourceControlResource) Configure(_ context.Context, req resource.Config r.client = providerData.Client } -// Metadata associated with the Source Control resource +// Metadata associated with the Source Control resource. func (r *sourceControlResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { resp.TypeName = req.ProviderTypeName + "_source_control" } -// Schema returns the schema for the Source Control resource +// Schema returns the schema for the Source Control resource. func (r *sourceControlResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { resp.Schema = schema.Schema{ Attributes: map[string]schema.Attribute{ @@ -332,7 +334,7 @@ func (r *sourceControlResource) Schema(ctx context.Context, req resource.SchemaR } } -// Custom validation implementation to prevent common errors in the Source Control config +// Custom validation implementation to prevent common errors in the Source Control config. func (r *sourceControlResource) ValidateConfig(ctx context.Context, req resource.ValidateConfigRequest, resp *resource.ValidateConfigResponse) { var model sourceControlModel diags := req.Config.Get(ctx, &model) @@ -404,7 +406,7 @@ func updateSourceControlConfig(ctx context.Context, client *api.APIClient, model EnterpriseApiUrl: githubConfig.EnterpriseAPIURL.ValueStringPointer(), } } else { - // assuming here that the personal access token is set + // Assuming here that the personal access token is set. innerConfig.SourceControlConfigGet200ResponseDataOneOfConfigOneOf1 = &api.SourceControlConfigGet200ResponseDataOneOfConfigOneOf1{ Type: "Personal", PersonalAccessToken: githubConfig.PersonalAccessToken.ValueString(), @@ -534,7 +536,7 @@ func updateSourceControlConfig(ctx context.Context, client *api.APIClient, model } } -// Updates Source Control config and sets state +// Updates Source Control config and sets state. func (r *sourceControlResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { var plan sourceControlModel diags := req.Plan.Get(ctx, &plan) @@ -548,7 +550,7 @@ func (r *sourceControlResource) Create(ctx context.Context, req resource.CreateR return } - // Set state to fully populated data + // Set state to fully populated data. diags = resp.State.Set(ctx, plan) resp.Diagnostics.Append(diags...) if resp.Diagnostics.HasError() { @@ -559,7 +561,7 @@ func (r *sourceControlResource) Create(ctx context.Context, req resource.CreateR tflog.Info(ctx, "Source Control config created") } -// Read Source Control config +// Read Source Control config. func (r *sourceControlResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { response, httpResponse, err := r.client.SourceControlAPI.SourceControlConfigGet(context.Background()).Execute() if err != nil { @@ -577,7 +579,7 @@ func (r *sourceControlResource) Read(ctx context.Context, req resource.ReadReque } var state sourceControlModel - // First init all object fields to empty objects + // First init all object fields to empty objects. state.GitHub = types.ObjectNull(githubConfigModel{}.attributeTypes()) state.GitLab = types.ObjectNull(gitlabConfigModel{}.attributeTypes()) state.AWSCodeCommit = types.ObjectNull(awsCodeCommitConfigModel{}.attributeTypes()) @@ -595,7 +597,7 @@ func (r *sourceControlResource) Read(ctx context.Context, req resource.ReadReque appAuthConfig := appAuthConfigModel{ AppID: types.StringValue(response.Data.SourceControlConfigGet200ResponseDataOneOf.Config.SourceControlConfigGet200ResponseDataOneOfConfigOneOf.AppId), InstallationID: types.StringValue(response.Data.SourceControlConfigGet200ResponseDataOneOf.Config.SourceControlConfigGet200ResponseDataOneOfConfigOneOf.InstallationId), - PrivateKey: types.StringNull(), // API sends placeholder value that we don't need + PrivateKey: types.StringNull(), // API sends placeholder value that we don't need. } appAuthConfigModelObj, diags := types.ObjectValueFrom(ctx, appAuthConfig.attributeTypes(), appAuthConfig) resp.Diagnostics.Append(diags...) @@ -607,7 +609,7 @@ func (r *sourceControlResource) Read(ctx context.Context, req resource.ReadReque githubConfigModel.URL = types.StringPointerValue(response.Data.SourceControlConfigGet200ResponseDataOneOf.Config.SourceControlConfigGet200ResponseDataOneOfConfigOneOf.Url) githubConfigModel.EnterpriseAPIURL = types.StringPointerValue(response.Data.SourceControlConfigGet200ResponseDataOneOf.Config.SourceControlConfigGet200ResponseDataOneOfConfigOneOf.EnterpriseApiUrl) } else { - githubConfigModel.PersonalAccessToken = types.StringNull() // API sends placeholder value that we don't need + githubConfigModel.PersonalAccessToken = types.StringNull() // API sends placeholder value that we don't need. githubConfigModel.AppAuthentication = types.ObjectNull(appAuthConfigModel{}.attributeTypes()) githubConfigModel.URL = types.StringPointerValue(response.Data.SourceControlConfigGet200ResponseDataOneOf.Config.SourceControlConfigGet200ResponseDataOneOfConfigOneOf1.Url) githubConfigModel.EnterpriseAPIURL = types.StringPointerValue(response.Data.SourceControlConfigGet200ResponseDataOneOf.Config.SourceControlConfigGet200ResponseDataOneOfConfigOneOf1.EnterpriseApiUrl) @@ -627,7 +629,7 @@ func (r *sourceControlResource) Read(ctx context.Context, req resource.ReadReque gitlabConfigModel := gitlabConfigModel{ ProjectID: types.StringValue(utils.Float32PtrToIntString(&response.Data.SourceControlConfigGet200ResponseDataOneOf1.Config.ProjectId)), URL: types.StringValue(response.Data.SourceControlConfigGet200ResponseDataOneOf1.Config.Url), - ProjectAccessToken: types.StringNull(), // API sends placeholder value that we don't need + ProjectAccessToken: types.StringNull(), // API sends placeholder value that we don't need. } gitlabConfigModelObj, diags := types.ObjectValueFrom(ctx, gitlabConfigModel.attributeTypes(), gitlabConfigModel) resp.Diagnostics.Append(diags...) @@ -644,10 +646,10 @@ func (r *sourceControlResource) Read(ctx context.Context, req resource.ReadReque awsCodeCommitConfigModel := awsCodeCommitConfigModel{ URL: types.StringValue(response.Data.SourceControlConfigGet200ResponseDataOneOf2.Config.Url), Region: types.StringValue(response.Data.SourceControlConfigGet200ResponseDataOneOf2.Config.Region), - AccessKeyID: types.StringNull(), // API sends placeholder value that we don't need - SecretAccessKey: types.StringNull(), // API sends placeholder value that we don't need, + AccessKeyID: types.StringNull(), // API sends placeholder value that we don't need. + SecretAccessKey: types.StringNull(), // API sends placeholder value that we don't need,. HTTPSUsername: types.StringValue(response.Data.SourceControlConfigGet200ResponseDataOneOf2.Config.HttpsUsername), - HTTPSPassword: types.StringNull(), // API sends placeholder value that we don't need + HTTPSPassword: types.StringNull(), // API sends placeholder value that we don't need. } awsCodeCommitConfigModelObj, diags := types.ObjectValueFrom(ctx, awsCodeCommitConfigModel.attributeTypes(), awsCodeCommitConfigModel) resp.Diagnostics.Append(diags...) @@ -665,7 +667,7 @@ func (r *sourceControlResource) Read(ctx context.Context, req resource.ReadReque Username: types.StringValue(response.Data.SourceControlConfigGet200ResponseDataOneOf3.Config.Username), URL: types.StringPointerValue(response.Data.SourceControlConfigGet200ResponseDataOneOf3.Config.Url), EnterpriseAPIURL: types.StringPointerValue(response.Data.SourceControlConfigGet200ResponseDataOneOf3.Config.EnterpriseApiUrl), - AppPassword: types.StringNull(), // API sends placeholder value that we don't need + AppPassword: types.StringNull(), // API sends placeholder value that we don't need. } bitbucketConfigModelObj, diags := types.ObjectValueFrom(ctx, bitbucketConfigModel.attributeTypes(), bitbucketConfigModel) resp.Diagnostics.Append(diags...) @@ -683,7 +685,7 @@ func (r *sourceControlResource) Read(ctx context.Context, req resource.ReadReque URL: types.StringValue(response.Data.SourceControlConfigGet200ResponseDataOneOf4.Config.Url), Project: types.StringValue(response.Data.SourceControlConfigGet200ResponseDataOneOf4.Config.Project), User: types.StringValue(response.Data.SourceControlConfigGet200ResponseDataOneOf4.Config.User), - PersonalAccessToken: types.StringNull(), // API sends placeholder value that we don't need + PersonalAccessToken: types.StringNull(), // API sends placeholder value that we don't need. UseBasicAuth: types.BoolValue(response.Data.SourceControlConfigGet200ResponseDataOneOf4.Config.UseBasicAuth), } azureReposConfigModelObj, diags := types.ObjectValueFrom(ctx, azureReposConfigModel.attributeTypes(), azureReposConfigModel) @@ -701,7 +703,7 @@ func (r *sourceControlResource) Read(ctx context.Context, req resource.ReadReque } } -// Update Source Control config +// Update Source Control config. func (r *sourceControlResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { var plan sourceControlModel diags := req.Plan.Get(ctx, &plan) @@ -715,7 +717,7 @@ func (r *sourceControlResource) Update(ctx context.Context, req resource.UpdateR return } - // Set state to fully populated data + // Set state to fully populated data. diags = resp.State.Set(ctx, plan) resp.Diagnostics.Append(diags...) if resp.Diagnostics.HasError() { @@ -726,10 +728,10 @@ func (r *sourceControlResource) Update(ctx context.Context, req resource.UpdateR tflog.Info(ctx, "Source Control config updated") } -// Delete Source Control config +// Delete Source Control config. func (r *sourceControlResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { httpResponse, err := r.client.SourceControlAPI.SourceControlConfigDelete(context.Background()).Execute() - if err != nil && !(httpResponse != nil && httpResponse.StatusCode == 404) { // it's ok to not find the source control config when deleting + if err != nil && !(httpResponse != nil && httpResponse.StatusCode == 404) { // It's ok to not find the source control config when deleting. resp.Diagnostics.AddError( "Error Deleting Source Control Config", "Could not Source Control config: "+err.Error(), diff --git a/internal/provider/source_control/resource_schema_test.go b/internal/provider/sourcecontrol/resource_schema_test.go similarity index 94% rename from internal/provider/source_control/resource_schema_test.go rename to internal/provider/sourcecontrol/resource_schema_test.go index 42802a8..f4525ce 100644 --- a/internal/provider/source_control/resource_schema_test.go +++ b/internal/provider/sourcecontrol/resource_schema_test.go @@ -1,4 +1,4 @@ -package source_control +package sourcecontrol import ( "context" @@ -6,7 +6,7 @@ import ( // The fwresource import alias is so there is no collistion // with the more typical acceptance testing import: - // "github.com/hashicorp/terraform-plugin-testing/helper/resource" + // "github.com/hashicorp/terraform-plugin-testing/helper/resource". fwresource "github.com/hashicorp/terraform-plugin-framework/resource" ) @@ -17,14 +17,14 @@ func TestSourceControlResourceSchema(t *testing.T) { schemaRequest := fwresource.SchemaRequest{} schemaResponse := &fwresource.SchemaResponse{} - // Instantiate the resource.Resource and call its Schema method + // Instantiate the resource.Resource and call its Schema method. NewResource().Schema(ctx, schemaRequest, schemaResponse) if schemaResponse.Diagnostics.HasError() { t.Fatalf("Schema method diagnostics: %+v", schemaResponse.Diagnostics) } - // Validate the schema + // Validate the schema. diagnostics := schemaResponse.Schema.ValidateImplementation(ctx) if diagnostics.HasError() { diff --git a/internal/provider/source_control/resource_test.go b/internal/provider/sourcecontrol/resource_test.go similarity index 94% rename from internal/provider/source_control/resource_test.go rename to internal/provider/sourcecontrol/resource_test.go index a367983..9bf0800 100644 --- a/internal/provider/source_control/resource_test.go +++ b/internal/provider/sourcecontrol/resource_test.go @@ -1,4 +1,4 @@ -package source_control_test +package sourcecontrol_test import ( "context" @@ -7,6 +7,7 @@ import ( "testing" "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/tryretool/terraform-provider-retool/internal/acctest" ) @@ -127,7 +128,7 @@ func TestMain(m *testing.M) { func TestAccSourceControl(t *testing.T) { acctest.Test(t, resource.TestCase{ Steps: []resource.TestStep{ - // Read and Create + // Read and Create. { Config: testGithubAppConfig, Check: resource.ComposeTestCheckFunc( @@ -141,7 +142,7 @@ func TestAccSourceControl(t *testing.T) { resource.TestCheckResourceAttr("retool_source_control.scm", "github.url", "https://github.com"), resource.TestCheckResourceAttr("retool_source_control.scm", "github.enterprise_api_url", "https://github.mycompany.com/api/v3"), ), - ExpectNonEmptyPlan: true, // because it'd want to refresh secret strings + ExpectNonEmptyPlan: true, // Because it'd want to refresh secret strings. }, { Config: testGithubPersonalConfig, @@ -154,7 +155,7 @@ func TestAccSourceControl(t *testing.T) { resource.TestCheckResourceAttr("retool_source_control.scm", "github.url", "https://github.com"), resource.TestCheckResourceAttr("retool_source_control.scm", "github.enterprise_api_url", "https://github.mycompany.com/api/v3"), ), - ExpectNonEmptyPlan: true, // because it'd want to refresh secret strings + ExpectNonEmptyPlan: true, // Because it'd want to refresh secret strings. }, { Config: testGitLabConfig, @@ -167,7 +168,7 @@ func TestAccSourceControl(t *testing.T) { resource.TestCheckResourceAttr("retool_source_control.scm", "gitlab.project_access_token", "project-access-token"), resource.TestCheckResourceAttr("retool_source_control.scm", "gitlab.project_id", "12345"), ), - ExpectNonEmptyPlan: true, // because it'd want to refresh secret strings + ExpectNonEmptyPlan: true, // Because it'd want to refresh secret strings. }, { Config: testAWSCodeCommitConfig, @@ -183,7 +184,7 @@ func TestAccSourceControl(t *testing.T) { resource.TestCheckResourceAttr("retool_source_control.scm", "aws_codecommit.https_username", "https-username"), resource.TestCheckResourceAttr("retool_source_control.scm", "aws_codecommit.https_password", "https-password"), ), - ExpectNonEmptyPlan: true, // because it'd want to refresh secret strings + ExpectNonEmptyPlan: true, // Because it'd want to refresh secret strings. }, { Config: testBitbucketConfig, @@ -197,7 +198,7 @@ func TestAccSourceControl(t *testing.T) { resource.TestCheckResourceAttr("retool_source_control.scm", "bitbucket.url", "https://bitbucket.org"), resource.TestCheckResourceAttr("retool_source_control.scm", "bitbucket.enterprise_api_url", "https://bitbucket.mycompany.com/api/v3"), ), - ExpectNonEmptyPlan: true, // because it'd want to refresh secret strings + ExpectNonEmptyPlan: true, // Because it'd want to refresh secret strings. }, { Config: testAzureReposConfig, @@ -212,9 +213,9 @@ func TestAccSourceControl(t *testing.T) { resource.TestCheckResourceAttr("retool_source_control.scm", "azure_repos.personal_access_token", "personal-access-token"), resource.TestCheckResourceAttr("retool_source_control.scm", "azure_repos.use_basic_auth", "true"), ), - ExpectNonEmptyPlan: true, // because it'd want to refresh secret strings + ExpectNonEmptyPlan: true, // Because it'd want to refresh secret strings. }, - // Update + // Update. { Config: testAzureReposUpdatedConfig, Check: resource.ComposeTestCheckFunc( @@ -228,7 +229,7 @@ func TestAccSourceControl(t *testing.T) { resource.TestCheckResourceAttr("retool_source_control.scm", "azure_repos.personal_access_token", "personal-access-token-updated"), resource.TestCheckResourceAttr("retool_source_control.scm", "azure_repos.use_basic_auth", "false"), ), - ExpectNonEmptyPlan: true, // because it'd want to refresh secret strings + ExpectNonEmptyPlan: true, // Because it'd want to refresh secret strings. }, }, }) diff --git a/internal/provider/source_control/source_control_api_test.go b/internal/provider/sourcecontrol/source_control_api_test.go similarity index 99% rename from internal/provider/source_control/source_control_api_test.go rename to internal/provider/sourcecontrol/source_control_api_test.go index c807f8a..6095600 100644 --- a/internal/provider/source_control/source_control_api_test.go +++ b/internal/provider/sourcecontrol/source_control_api_test.go @@ -1,4 +1,4 @@ -package source_control +package sourcecontrol import ( "context" @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/tryretool/terraform-provider-retool/internal/sdk/api" ) diff --git a/internal/provider/source_control_settings/resource.go b/internal/provider/sourcecontrolsettings/resource.go similarity index 93% rename from internal/provider/source_control_settings/resource.go rename to internal/provider/sourcecontrolsettings/resource.go index 63edbd2..a1d41c9 100644 --- a/internal/provider/source_control_settings/resource.go +++ b/internal/provider/sourcecontrolsettings/resource.go @@ -1,4 +1,5 @@ -package source_control_settings +// Package sourcecontrolsettings provides the implementation of the Source Control Settings resource. +package sourcecontrolsettings import ( "context" @@ -11,11 +12,12 @@ import ( "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringdefault" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/tryretool/terraform-provider-retool/internal/provider/utils" "github.com/tryretool/terraform-provider-retool/internal/sdk/api" ) -// Ensure SCM settings implements the tfsdk.Resource interface +// Ensure SCM settings implements the tfsdk.Resource interface. var ( _ resource.Resource = &scmSettingsResource{} _ resource.ResourceWithConfigure = &scmSettingsResource{} @@ -54,12 +56,12 @@ func (r *scmSettingsResource) Configure(_ context.Context, req resource.Configur r.client = providerData.Client } -// Metadata associated with the Source Control Settings resource +// Metadata associated with the Source Control Settings resource. func (r *scmSettingsResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { resp.TypeName = req.ProviderTypeName + "_source_control_settings" } -// Schema returns the schema for the Source Control resource +// Schema returns the schema for the Source Control resource. func (r *scmSettingsResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { resp.Schema = schema.Schema{ Attributes: map[string]schema.Attribute{ @@ -109,7 +111,7 @@ func updateSourceControlSettings(ctx context.Context, client *api.APIClient, mod } } -// Updates Source Control settings and sets state +// Updates Source Control settings and sets state. func (r *scmSettingsResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { var plan scmSettingsModel diags := req.Plan.Get(ctx, &plan) @@ -123,7 +125,7 @@ func (r *scmSettingsResource) Create(ctx context.Context, req resource.CreateReq return } - // Set state to fully populated data + // Set state to fully populated data. diags = resp.State.Set(ctx, plan) resp.Diagnostics.Append(diags...) if resp.Diagnostics.HasError() { @@ -134,7 +136,7 @@ func (r *scmSettingsResource) Create(ctx context.Context, req resource.CreateReq tflog.Info(ctx, "Source Control settings updated") } -// Read Source Control settings +// Read Source Control settings. func (r *scmSettingsResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { response, httpResponse, err := r.client.SourceControlAPI.SourceControlSettingsGet(context.Background()).Execute() if err != nil { @@ -166,7 +168,7 @@ func (r *scmSettingsResource) Read(ctx context.Context, req resource.ReadRequest } } -// Update Source Control settings +// Update Source Control settings. func (r *scmSettingsResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { var plan scmSettingsModel diags := req.Plan.Get(ctx, &plan) @@ -180,7 +182,7 @@ func (r *scmSettingsResource) Update(ctx context.Context, req resource.UpdateReq return } - // Set state to fully populated data + // Set state to fully populated data. diags = resp.State.Set(ctx, plan) resp.Diagnostics.Append(diags...) if resp.Diagnostics.HasError() { @@ -191,10 +193,10 @@ func (r *scmSettingsResource) Update(ctx context.Context, req resource.UpdateReq tflog.Info(ctx, "Source Control settings updated") } -// Delete Source Control settings +// Delete Source Control settings. func (r *scmSettingsResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { // There's no DELETE endpoint, so we'll just set everything to default values - // and call the update function + // and call the update function. model := scmSettingsModel{ AutoBranchNamingEnabled: types.BoolValue(true), CustomPullRequestTemplateEnabled: types.BoolValue(false), diff --git a/internal/provider/source_control_settings/resource_schema_test.go b/internal/provider/sourcecontrolsettings/resource_schema_test.go similarity index 93% rename from internal/provider/source_control_settings/resource_schema_test.go rename to internal/provider/sourcecontrolsettings/resource_schema_test.go index 1f98cc9..775cc8e 100644 --- a/internal/provider/source_control_settings/resource_schema_test.go +++ b/internal/provider/sourcecontrolsettings/resource_schema_test.go @@ -1,4 +1,4 @@ -package source_control_settings +package sourcecontrolsettings import ( "context" @@ -6,7 +6,7 @@ import ( // The fwresource import alias is so there is no collistion // with the more typical acceptance testing import: - // "github.com/hashicorp/terraform-plugin-testing/helper/resource" + // "github.com/hashicorp/terraform-plugin-testing/helper/resource". fwresource "github.com/hashicorp/terraform-plugin-framework/resource" ) @@ -17,14 +17,14 @@ func TestSourceControlSettingsResourceSchema(t *testing.T) { schemaRequest := fwresource.SchemaRequest{} schemaResponse := &fwresource.SchemaResponse{} - // Instantiate the resource.Resource and call its Schema method + // Instantiate the resource.Resource and call its Schema method. NewResource().Schema(ctx, schemaRequest, schemaResponse) if schemaResponse.Diagnostics.HasError() { t.Fatalf("Schema method diagnostics: %+v", schemaResponse.Diagnostics) } - // Validate the schema + // Validate the schema. diagnostics := schemaResponse.Schema.ValidateImplementation(ctx) if diagnostics.HasError() { diff --git a/internal/provider/source_control_settings/resource_test.go b/internal/provider/sourcecontrolsettings/resource_test.go similarity index 97% rename from internal/provider/source_control_settings/resource_test.go rename to internal/provider/sourcecontrolsettings/resource_test.go index acdff3a..5e85f79 100644 --- a/internal/provider/source_control_settings/resource_test.go +++ b/internal/provider/sourcecontrolsettings/resource_test.go @@ -1,4 +1,4 @@ -package source_control_settings_test +package sourcecontrolsettings_test import ( "context" @@ -7,6 +7,7 @@ import ( "testing" "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/tryretool/terraform-provider-retool/internal/acctest" "github.com/tryretool/terraform-provider-retool/internal/sdk/api" ) @@ -41,7 +42,7 @@ func TestMain(m *testing.M) { func TestAccSourceControlSettings(t *testing.T) { acctest.Test(t, resource.TestCase{ Steps: []resource.TestStep{ - // Read and Create + // Read and Create. { Config: testSCMSettings, Check: resource.ComposeTestCheckFunc( @@ -51,7 +52,7 @@ func TestAccSourceControlSettings(t *testing.T) { resource.TestCheckResourceAttr("retool_source_control_settings.scm_settings", "version_control_locked", "true"), ), }, - // Update and Read + // Update and Read. { Config: testSCMSettingsUpdated, Check: resource.ComposeTestCheckFunc( @@ -61,7 +62,7 @@ func TestAccSourceControlSettings(t *testing.T) { resource.TestCheckResourceAttr("retool_source_control_settings.scm_settings", "version_control_locked", "false"), ), }, - // Use default values + // Use default values. { Config: testSCMSettingsDefaults, Check: resource.ComposeTestCheckFunc( diff --git a/internal/provider/space/resource.go b/internal/provider/space/resource.go index 763a597..f51367e 100644 --- a/internal/provider/space/resource.go +++ b/internal/provider/space/resource.go @@ -1,3 +1,4 @@ +// Package space provides implementation of the Space resource. package space import ( @@ -27,7 +28,7 @@ type spaceResource struct { client *api.APIClient } -// Ensure SpaceResource implements the tfsdk.Resource interface +// Ensure SpaceResource implements the tfsdk.Resource interface. var ( _ resource.Resource = &spaceResource{} _ resource.ResourceWithConfigure = &spaceResource{} @@ -311,8 +312,8 @@ func (r *spaceResource) Delete(ctx context.Context, req resource.DeleteRequest, } } -// ImportState allows importing of a Space resource +// ImportState allows importing of a Space resource. func (r *spaceResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { - // Retrieve import ID and save to id attribute + // Retrieve import ID and save to id attribute. resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp) } diff --git a/internal/provider/space/resource_schema_test.go b/internal/provider/space/resource_schema_test.go index 72af54a..a4955a1 100644 --- a/internal/provider/space/resource_schema_test.go +++ b/internal/provider/space/resource_schema_test.go @@ -6,7 +6,7 @@ import ( // The fwresource import alias is so there is no collistion // with the more typical acceptance testing import: - // "github.com/hashicorp/terraform-plugin-testing/helper/resource" + // "github.com/hashicorp/terraform-plugin-testing/helper/resource". fwresource "github.com/hashicorp/terraform-plugin-framework/resource" ) @@ -17,14 +17,14 @@ func TestSpaceResourceSchema(t *testing.T) { schemaRequest := fwresource.SchemaRequest{} schemaResponse := &fwresource.SchemaResponse{} - // Instantiate the resource.Resource and call its Schema method + // Instantiate the resource.Resource and call its Schema method. NewResource().Schema(ctx, schemaRequest, schemaResponse) if schemaResponse.Diagnostics.HasError() { t.Fatalf("Schema method diagnostics: %+v", schemaResponse.Diagnostics) } - // Validate the schema + // Validate the schema. diagnostics := schemaResponse.Schema.ValidateImplementation(ctx) if diagnostics.HasError() { diff --git a/internal/provider/space/resource_test.go b/internal/provider/space/resource_test.go index cb5c96b..1aabbc5 100644 --- a/internal/provider/space/resource_test.go +++ b/internal/provider/space/resource_test.go @@ -8,6 +8,7 @@ import ( "testing" "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/tryretool/terraform-provider-retool/internal/acctest" ) @@ -51,7 +52,7 @@ func TestMain(m *testing.M) { func TestAccSpace(t *testing.T) { acctest.Test(t, resource.TestCase{ Steps: []resource.TestStep{ - // Read and Create + // Read and Create. { Config: testSpaceConfig, Check: resource.ComposeTestCheckFunc( @@ -64,12 +65,12 @@ func TestAccSpace(t *testing.T) { resource.TestCheckResourceAttr("retool_space.test_space", "create_options.users_to_copy_as_admins.0", "admin@example.com"), ), }, - // Import state + // Import state. { ResourceName: "retool_space.test_space", ImportState: true, }, - // Update and Read + // Update and Read. { Config: testUpdatedSpaceConfig, Check: resource.ComposeTestCheckFunc( @@ -82,7 +83,7 @@ func TestAccSpace(t *testing.T) { resource.TestCheckResourceAttr("retool_space.test_space", "create_options.users_to_copy_as_admins.0", "admin@example.com"), ), }, - // Check default values + // Check default values. { Config: testDefaultValuesConfig, Check: resource.ComposeTestCheckFunc( diff --git a/internal/provider/sso/resource.go b/internal/provider/sso/resource.go index a08bafd..2e5cfc7 100644 --- a/internal/provider/sso/resource.go +++ b/internal/provider/sso/resource.go @@ -1,3 +1,4 @@ +// Package sso provides implementation of the SSO resource. package sso import ( @@ -17,17 +18,18 @@ import ( "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-plugin-framework/types/basetypes" "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/tryretool/terraform-provider-retool/internal/provider/utils" "github.com/tryretool/terraform-provider-retool/internal/sdk/api" ) -// Ensure SSOResource implements the tfsdk.Resource interface +// Ensure SSOResource implements the tfsdk.Resource interface. var ( _ resource.Resource = &ssoResource{} _ resource.ResourceWithConfigure = &ssoResource{} ) -// ssoResource schema structure +// ssoResource schema structure. type ssoResource struct { client *api.APIClient } @@ -167,12 +169,12 @@ func (r *ssoResource) Configure(_ context.Context, req resource.ConfigureRequest r.client = providerData.Client } -// Metadata associated with the SSO resource +// Metadata associated with the SSO resource. func (r *ssoResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { resp.TypeName = req.ProviderTypeName + "_sso" } -// Schema returns the schema for the SSO resource +// Schema returns the schema for the SSO resource. func (r *ssoResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { resp.Schema = schema.Schema{ Attributes: map[string]schema.Attribute{ @@ -396,7 +398,7 @@ func (r *ssoResource) Schema(ctx context.Context, req resource.SchemaRequest, re } } -// Custom validation implementation to prevent common errors in the SSO config +// Custom validation implementation to prevent common errors in the SSO config. func (r *ssoResource) ValidateConfig(ctx context.Context, req resource.ValidateConfigRequest, resp *resource.ValidateConfigResponse) { var model ssoResourceModel diags := req.Config.Get(ctx, &model) @@ -405,20 +407,20 @@ func (r *ssoResource) ValidateConfig(ctx context.Context, req resource.ValidateC return } - // Either google, oidc, or saml must be configured + // Either google, oidc, or saml must be configured. if utils.IsEmptyObject(model.Google) && utils.IsEmptyObject(model.OIDC) && utils.IsEmptyObject(model.SAML) { resp.Diagnostics.AddError("sso_config_validation", "Either google, oidc, or saml must be configured") return } - // You can't configure both SAML and OIDC at the same time + // You can't configure both SAML and OIDC at the same time. if !utils.IsEmptyObject(model.OIDC) && !utils.IsEmptyObject(model.SAML) { resp.Diagnostics.AddError("sso_config_validation", "You can't configure both SAML and OIDC at the same time") } } // Converts a saml/ldap role mapping from a map to a string -// The encoding is "multivalue", so { "key1": ["value1", "value2"], "key2": ["value3"] } becomes "key1->value1,key1->value2,key2->value3" +// The encoding is "multivalue", so { "key1": ["value1", "value2"], "key2": ["value3"] } becomes "key1->value1,key1->value2,key2->value3". func getLdapRolesMapping(ctx context.Context, samlConfig samlConfigModel, diags *diag.Diagnostics) *string { if utils.IsEmptyMap(samlConfig.RolesMapping) { return nil @@ -430,7 +432,7 @@ func getLdapRolesMapping(ctx context.Context, samlConfig samlConfigModel, diags if diags.HasError() { return nil } - // Iterate over elements, convert each value to a list of strings, and add to the tokens array + // Iterate over elements, convert each value to a list of strings, and add to the tokens array. roleMapping := make([]string, 0, len(elements)) for key, value := range elements { for _, v := range utils.GetStringListValue(ctx, value, diags) { @@ -445,7 +447,7 @@ func getLdapRolesMapping(ctx context.Context, samlConfig samlConfigModel, diags } // Converts OIDC role mapping from a map to a string -// { "key1": "value1", "key2: value2"} is converted to "key1->value1,key2->value2" +// { "key1": "value1", "key2: value2"} is converted to "key1->value1,key2->value2". func getOidcRolesMapping(ctx context.Context, oidcConfig oidcConfigModel, diags *diag.Diagnostics) *string { if utils.IsEmptyMap(oidcConfig.RolesMapping) { return nil @@ -466,7 +468,7 @@ func getOidcRolesMapping(ctx context.Context, oidcConfig oidcConfigModel, diags return &result } -// Converts RestrictedDomains list attribute to a comma-separated string +// Converts RestrictedDomains list attribute to a comma-separated string. func getRestrictedDomains(ctx context.Context, restrictedDomains types.List, diags *diag.Diagnostics) *string { if utils.IsEmptyList(restrictedDomains) { return nil @@ -485,9 +487,9 @@ type encryptedSecrets struct { } // Helper method that prepares and makes the API POST request to update the SSO config -// Returns a struct containing the encrypted secrets - these need to be stored in the state +// Returns a struct containing the encrypted secrets - these need to be stored in the state. func (r *ssoResource) updateSSOConfig(ctx context.Context, plan ssoResourceModel, globalDiags *diag.Diagnostics) *encryptedSecrets { - // Generate API request body from plan + // Generate API request body from plan. var apiRequest api.SsoConfigPostRequest // Request object is a union of 5 structs - one for each SSO type @@ -497,7 +499,7 @@ func (r *ssoResource) updateSSOConfig(ctx context.Context, plan ssoResourceModel if !utils.IsEmptyObject(plan.SAML) { tflog.Info(ctx, "Google & SAML SSO settings detected") // SSO type is "google & saml" - // Get google and saml configs + // Get google and saml configs. var googleConfig googleConfigModel diags := plan.Google.As(ctx, &googleConfig, basetypes.ObjectAsOptions{}) globalDiags.Append(diags...) @@ -526,7 +528,7 @@ func (r *ssoResource) updateSSOConfig(ctx context.Context, plan ssoResourceModel TriggerLoginAutomatically: samlConfig.TriggerLoginAutomatically.ValueBool(), RestrictedDomain: getRestrictedDomains(ctx, samlConfig.RestrictedDomains, globalDiags), } - // Add ldap config if present + // Add ldap config if present. if !utils.IsEmptyObject(samlConfig.LDAPConfig) { var ldapConfig ldapConfigModel diags = samlConfig.LDAPConfig.As(ctx, &ldapConfig, basetypes.ObjectAsOptions{}) @@ -546,7 +548,7 @@ func (r *ssoResource) updateSSOConfig(ctx context.Context, plan ssoResourceModel apiRequest.Data.SsoConfigPostRequestDataOneOf4 = &ssoConfig } else if !utils.IsEmptyObject(plan.OIDC) { // SSO type is "google & oidc" - // Get google and oidc configs + // Get google and oidc configs. var googleConfig googleConfigModel diags := plan.Google.As(ctx, &googleConfig, basetypes.ObjectAsOptions{}) globalDiags.Append(diags...) @@ -585,7 +587,7 @@ func (r *ssoResource) updateSSOConfig(ctx context.Context, plan ssoResourceModel } apiRequest.Data.SsoConfigPostRequestDataOneOf2 = &ssoConfig } else { - // SSO type is "google" + // SSO type is "google". var googleConfig googleConfigModel diags := plan.Google.As(ctx, &googleConfig, basetypes.ObjectAsOptions{}) globalDiags.Append(diags...) @@ -604,7 +606,7 @@ func (r *ssoResource) updateSSOConfig(ctx context.Context, plan ssoResourceModel apiRequest.Data.SsoConfigPostRequestDataOneOf = &ssoConfig } } else if !utils.IsEmptyObject(plan.OIDC) { - // SSO type is "oidc" + // SSO type is "oidc". var oidcConfig oidcConfigModel diags := plan.OIDC.As(ctx, &oidcConfig, basetypes.ObjectAsOptions{}) globalDiags.Append(diags...) @@ -634,9 +636,8 @@ func (r *ssoResource) updateSSOConfig(ctx context.Context, plan ssoResourceModel return nil } apiRequest.Data.SsoConfigPostRequestDataOneOf1 = &ssoConfig - } else if !utils.IsEmptyObject(plan.SAML) { - // SSO type is "saml" + // SSO type is "saml". var samlConfig samlConfigModel diags := plan.SAML.As(ctx, &samlConfig, basetypes.ObjectAsOptions{}) globalDiags.Append(diags...) @@ -657,7 +658,7 @@ func (r *ssoResource) updateSSOConfig(ctx context.Context, plan ssoResourceModel TriggerLoginAutomatically: samlConfig.TriggerLoginAutomatically.ValueBool(), RestrictedDomain: getRestrictedDomains(ctx, samlConfig.RestrictedDomains, globalDiags), } - // Add ldap config if present + // Add ldap config if present. if !utils.IsEmptyObject(samlConfig.LDAPConfig) { var ldapConfig ldapConfigModel diags = samlConfig.LDAPConfig.As(ctx, &ldapConfig, basetypes.ObjectAsOptions{}) @@ -703,7 +704,7 @@ func (r *ssoResource) updateSSOConfig(ctx context.Context, plan ssoResourceModel return secrets } -// Sets encrypted secrets in the state +// Sets encrypted secrets in the state. func setEncryptedSecrets(ctx context.Context, state *tfsdk.State, secrets *encryptedSecrets, globalDiags *diag.Diagnostics) { var obj types.Object if diags := state.GetAttribute(ctx, path.Root("google"), &obj); !diags.HasError() && !obj.IsNull() { @@ -722,9 +723,9 @@ func setEncryptedSecrets(ctx context.Context, state *tfsdk.State, secrets *encry } } -// Updates SSO config and sets state +// Updates SSO config and sets state. func (r *ssoResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { - // Retrieve values from plan + // Retrieve values from plan. tflog.Info(ctx, "Getting the plan model") var plan ssoResourceModel diags := req.Plan.Get(ctx, &plan) @@ -739,14 +740,14 @@ func (r *ssoResource) Create(ctx context.Context, req resource.CreateRequest, re return } - // Set state to fully populated data + // Set state to fully populated data. diags = resp.State.Set(ctx, plan) resp.Diagnostics.Append(diags...) if resp.Diagnostics.HasError() { tflog.Error(ctx, "Error creating SSO conifg", map[string]interface{}{"error": "Could not set state"}) return } - // Update encrypted secret strings in the state + // Update encrypted secret strings in the state. setEncryptedSecrets(ctx, &resp.State, secrets, &resp.Diagnostics) if resp.Diagnostics.HasError() { tflog.Error(ctx, "Error creating SSO config", map[string]interface{}{"error": "Could not set encrypted secrets"}) @@ -776,7 +777,7 @@ func getSecretValue(ctx context.Context, state *tfsdk.State, newEncryptedSecret return types.StringNull() } -// Converts a string of the form "key1->value1,key1->value2,key2->value3" to a map of the form { "key1": ["value1", "value2"], "key2": ["value3"] } +// Converts a string of the form "key1->value1,key1->value2,key2->value3" to a map of the form { "key1": ["value1", "value2"], "key2": ["value3"] }. func parseLdapRolesMappingValue(ctx context.Context, rolesMappingValue string) map[string][]string { rolesMapping := make(map[string][]string) roleMapTuples := strings.Split(rolesMappingValue, ",") @@ -793,7 +794,7 @@ func parseLdapRolesMappingValue(ctx context.Context, rolesMappingValue string) m return rolesMapping } -// Check if any of the LDAP config attributes are present +// Check if any of the LDAP config attributes are present. func isLdapConfigPresent(ssoConfig *api.SSOConfig) bool { return ssoConfig.LdapServerUrl != nil || ssoConfig.LdapBaseDomainComponents != nil || @@ -802,7 +803,7 @@ func isLdapConfigPresent(ssoConfig *api.SSOConfig) bool { ssoConfig.LdapServerCertificate != nil } -// Read SSO config +// Read SSO config. func (r *ssoResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { var state ssoResourceModel diags := req.State.Get(ctx, &state) @@ -991,7 +992,7 @@ func (r *ssoResource) Read(ctx context.Context, req resource.ReadRequest, resp * } } -// Update SSO config +// Update SSO config. func (r *ssoResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { var plan ssoResourceModel diags := req.Plan.Get(ctx, &plan) @@ -1011,16 +1012,15 @@ func (r *ssoResource) Update(ctx context.Context, req resource.UpdateRequest, re return } - // Update encrypted secret strings in the state + // Update encrypted secret strings in the state. setEncryptedSecrets(ctx, &resp.State, secrets, &resp.Diagnostics) if resp.Diagnostics.HasError() { return } } -// Delete SSO config +// Delete SSO config. func (r *ssoResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { - httpResponse, err := r.client.SSOAPI.SsoConfigDelete(ctx).Execute() if err != nil { resp.Diagnostics.AddError( diff --git a/internal/provider/sso/resource_schema_test.go b/internal/provider/sso/resource_schema_test.go index f61ccca..d27ce5e 100644 --- a/internal/provider/sso/resource_schema_test.go +++ b/internal/provider/sso/resource_schema_test.go @@ -6,7 +6,7 @@ import ( // The fwresource import alias is so there is no collistion // with the more typical acceptance testing import: - // "github.com/hashicorp/terraform-plugin-testing/helper/resource" + // "github.com/hashicorp/terraform-plugin-testing/helper/resource". fwresource "github.com/hashicorp/terraform-plugin-framework/resource" ) @@ -17,14 +17,14 @@ func TestSsoResourceSchema(t *testing.T) { schemaRequest := fwresource.SchemaRequest{} schemaResponse := &fwresource.SchemaResponse{} - // Instantiate the resource.Resource and call its Schema method + // Instantiate the resource.Resource and call its Schema method. NewResource().Schema(ctx, schemaRequest, schemaResponse) if schemaResponse.Diagnostics.HasError() { t.Fatalf("Schema method diagnostics: %+v", schemaResponse.Diagnostics) } - // Validate the schema + // Validate the schema. diagnostics := schemaResponse.Schema.ValidateImplementation(ctx) if diagnostics.HasError() { diff --git a/internal/provider/sso/resource_test.go b/internal/provider/sso/resource_test.go index 934c55d..9039d6b 100644 --- a/internal/provider/sso/resource_test.go +++ b/internal/provider/sso/resource_test.go @@ -7,6 +7,7 @@ import ( "testing" "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/tryretool/terraform-provider-retool/internal/acctest" ) @@ -174,7 +175,7 @@ func TestMain(m *testing.M) { func TestAccSSO(t *testing.T) { acctest.Test(t, resource.TestCase{ Steps: []resource.TestStep{ - // Read and Create + // Read and Create. { Config: testGoogleConfig, Check: resource.ComposeTestCheckFunc( @@ -294,7 +295,7 @@ func TestAccSSO(t *testing.T) { resource.TestCheckResourceAttrSet("retool_sso.sso", "saml.ldap_config.encrypted_server_certificate"), ), }, - // Update and Read + // Update and Read. { Config: testUpdatedGoogleSamlConfig, Check: resource.ComposeTestCheckFunc( diff --git a/internal/provider/utils/utils.go b/internal/provider/utils/utils.go index 2c6b060..9190704 100644 --- a/internal/provider/utils/utils.go +++ b/internal/provider/utils/utils.go @@ -1,3 +1,4 @@ +// Package utils provides utility functions for the provider and resources. package utils import ( @@ -8,10 +9,11 @@ import ( "github.com/hashicorp/terraform-plugin-framework/diag" "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/tryretool/terraform-provider-retool/internal/sdk/api" ) -// providerData is the data structure that is passed to the DataSource and Resource +// providerData is the data structure that is passed to the DataSource and Resource. type ProviderData struct { Client *api.APIClient RootFolderIdCache *map[string]string @@ -28,7 +30,7 @@ func AddHttpStatusCode(props map[string]any, httpResponse *http.Response) map[st // Some of the ids are returned as numbers, and our SDK client represents them as float32, but we need them as strings. func Float32PtrToIntString(f *float32) string { if f == nil { - return "" // or some default value + return "" // Or some default value. } rounded := math.Round(float64(*f)) return strconv.Itoa(int(rounded)) diff --git a/internal/sdk/client/main.go b/internal/sdk/client/main.go index abb9a82..3a1b53a 100644 --- a/internal/sdk/client/main.go +++ b/internal/sdk/client/main.go @@ -1,3 +1,4 @@ +// Package main provides a simple example of how to use the generated SDK. package main import ( diff --git a/internal/sdk/generate.go b/internal/sdk/generate.go index 4e83035..3b4c742 100644 --- a/internal/sdk/generate.go +++ b/internal/sdk/generate.go @@ -1,2 +1,4 @@ +// Package sdk : contains the generated code from the openAPI spec +// //go:generate sh -c "OPENAPI_GENERATOR_VERSION=7.6.0 openapi-generator-cli generate -i openAPISpec.json -g go -o ./api -c generatorConfig.yaml --minimal-update" package sdk diff --git a/main.go b/main.go index f7e249a..f57bc60 100644 --- a/main.go +++ b/main.go @@ -1,3 +1,4 @@ +// Package main provides the entrypoint for the provider. It sets up the provider and starts the provider server. package main import ( @@ -6,10 +7,11 @@ import ( "log" "github.com/hashicorp/terraform-plugin-framework/providerserver" + "github.com/tryretool/terraform-provider-retool/internal/provider" ) -// Run "go generate" to format example terraform files and generate the docs for the registry/website +// Run "go generate" to format example terraform files and generate the docs for the registry/website. // If you do not have terraform installed, you can remove the formatting command, but its suggested to // ensure the documentation is formatted properly. @@ -20,11 +22,11 @@ import ( //go:generate go run github.com/hashicorp/terraform-plugin-docs/cmd/tfplugindocs generate -provider-name retool var ( - // these will be set by the goreleaser configuration + // These will be set by the goreleaser configuration // to appropriate values for the compiled binary. version = "dev" - // goreleaser can pass other information to the main package, such as the specific commit + // Goreleaser can pass other information to the main package, such as the specific commit // https://goreleaser.com/cookbooks/using-main.version/ )