diff --git a/.gitignore b/.gitignore index 894dd83..c9f041d 100644 --- a/.gitignore +++ b/.gitignore @@ -38,3 +38,5 @@ config.tfrc .env .DS_Store +.tools +.vscode diff --git a/Makefile b/Makefile index c2630b3..fc2bdaa 100644 --- a/Makefile +++ b/Makefile @@ -1,32 +1,33 @@ +include makefiles/golangci.mk + .PHONY: build test lint + default: build -build: +build: ## Compile the Go package. This is the default. @echo "==> Building package..." go build -lint: - @echo "==> Checking source code against linters..." - golangci-lint run -v ./... +clean: ## Remove the .tools folder and binaries. + @rm -rf .tools + @rm terraform-provider-aap -test: +test: ## Execute all unit tests with verbose output. @echo "==> Running unit tests..." go test -v ./... -testacc: - @echo "==> Running acceptance tests..." - TF_ACC=1 AAP_HOST="https://localhost:8043" AAP_INSECURE_SKIP_VERIFY=true go test -count=1 -v ./... - -testacc-aapdev: +testacc: ## Run Acceptance tests against aap instance (See README.md for env variables) @echo "==> Running acceptance tests..." - TF_ACC=1 AAP_HOST="http://localhost:9080" go test -count=1 -v ./... - -gofmt: - @echo "==> Format code using gofmt..." - gofmt -s -w internal/provider + TF_ACC=1 go test -count=1 -v ./... -generatedocs: +generatedocs: ## Format example Terraform configurations and generate plugin documentation. @echo "==> Formatting examples and generating docs..." terraform fmt -recursive ./examples/ go run github.com/hashicorp/terraform-plugin-docs/cmd/tfplugindocs generate + +.PHONY: help +help: ## Show this help message + @grep -hE '^[a-zA-Z0-9._-]+:.*?##' $(MAKEFILE_LIST) | \ + awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-16s\033[0m %s\n", $$1, $$2}' | \ + sort diff --git a/README.md b/README.md index 9068fa2..7d28947 100644 --- a/README.md +++ b/README.md @@ -44,9 +44,13 @@ Acceptance tests apply test terraform configurations to a running AAP instance a To run acceptance tests locally, start a local AAP instance following the [docker-compose instructions for local AWX development](https://github.com/ansible/awx/blob/devel/tools/docker-compose/README.md). Create an admin user for the AAP instance and save the credentials to these environment variables: +Create an admin user for the AAP instance and set the following environment variables: + ```bash export AAP_USERNAME= export AAP_PASSWORD= +export AAP_INSECURE_SKIP_VERIFY=true +export AAP_HOST= # "http://localhost:9080" or "https://localhost:8043" ``` In order to run the acceptance tests for the job resource, you must have a working job template already in your AAP instance. The job template must be set to require an inventory on launch. Export the id of this job template: diff --git a/internal/provider/group_resource_test.go b/internal/provider/group_resource_test.go index fca61d5..2bfc90b 100644 --- a/internal/provider/group_resource_test.go +++ b/internal/provider/group_resource_test.go @@ -6,7 +6,6 @@ import ( "encoding/json" "fmt" "reflect" - "regexp" "strings" "testing" @@ -35,14 +34,13 @@ func TestGroupResourceSchema(t *testing.T) { // Validate the schema diagnostics := schemaResponse.Schema.ValidateImplementation(ctx) - if diagnostics.HasError() { t.Fatalf("Schema validation diagnostics: %+v", diagnostics) } } func TestGroupResourceCreateRequestBody(t *testing.T) { - var testTable = []struct { + testCases := []struct { name string input GroupResourceModel expected []byte @@ -97,14 +95,14 @@ func TestGroupResourceCreateRequestBody(t *testing.T) { }, } - for _, test := range testTable { - t.Run(test.name, func(t *testing.T) { - actual, diags := test.input.CreateRequestBody() + for _, testCase := range testCases { + t.Run(testCase.name, func(t *testing.T) { + actual, diags := testCase.input.CreateRequestBody() if diags.HasError() { t.Fatal(diags.Errors()) } - if !bytes.Equal(test.expected, actual) { - t.Errorf("Expected (%s) not equal to actual (%s)", test.expected, actual) + if !bytes.Equal(testCase.expected, actual) { + t.Errorf("Expected (%s) not equal to actual (%s)", testCase.expected, actual) } }) } @@ -114,7 +112,15 @@ func TestGroupResourceParseHttpResponse(t *testing.T) { jsonError := diag.Diagnostics{} jsonError.AddError("Error parsing JSON response from AAP", "invalid character 'N' looking for beginning of value") - var testTable = []struct { + const groupJSON = `{ + "inventory": 1, + "description": "A basic test group", + "name": "group1", + "url": "/api/v2/groups/1/", + "variables": "{\"foo\":\"bar\",\"nested\":{\"foobar\":\"baz\"}}" + }` + + testCases := []struct { name string input []byte expected GroupResourceModel @@ -139,9 +145,8 @@ func TestGroupResourceParseHttpResponse(t *testing.T) { errors: diag.Diagnostics{}, }, { - name: "test with all values", - input: []byte(`{"inventory":1,"description":"A basic test group","name":"group1","url":"/api/v2/groups/1/",` + - `"variables":"{\"foo\":\"bar\",\"nested\":{\"foobar\":\"baz\"}}"}`), + name: "test with all values", + input: []byte(groupJSON), expected: GroupResourceModel{ InventoryId: types.Int64Value(1), Id: types.Int64Value(0), @@ -154,15 +159,15 @@ func TestGroupResourceParseHttpResponse(t *testing.T) { }, } - for _, test := range testTable { - t.Run(test.name, func(t *testing.T) { + for _, testCase := range testCases { + t.Run(testCase.name, func(t *testing.T) { resource := GroupResourceModel{} - diags := resource.ParseHttpResponse(test.input) - if !test.errors.Equal(diags) { - t.Errorf("Expected error diagnostics (%s), actual was (%s)", test.errors, diags) + diags := resource.ParseHttpResponse(testCase.input) + if !testCase.errors.Equal(diags) { + t.Errorf("Expected error diagnostics (%s), actual was (%s)", testCase.errors, diags) } - if !reflect.DeepEqual(test.expected, resource) { - t.Errorf("Expected (%s) not equal to actual (%s)", test.expected, resource) + if !reflect.DeepEqual(testCase.expected, resource) { + t.Errorf("Expected (%s) not equal to actual (%s)", testCase.expected, resource) } }) } @@ -172,42 +177,38 @@ func TestGroupResourceParseHttpResponse(t *testing.T) { func TestAccGroupResource(t *testing.T) { var groupApiModel GroupAPIModel - var description = "A test group" - var variables = "{\"foo\": \"bar\"}" inventoryName := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum) groupName := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum) updatedName := "updated" + groupName + description := "A test group" + variables := "{\"foo\": \"bar\"}" resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, Steps: []resource.TestStep{ - // Invalid variables testing + // Invalid variables testing. { Config: testAccGroupResourceBadVariables(inventoryName, updatedName), - ExpectError: regexp.MustCompile("Input type `str` is not a dictionary"), + ExpectError: reInvalidVars, }, - // Create and Read testing { Config: testAccGroupResourceMinimal(inventoryName, groupName), Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckGroupResourceExists("aap_group.test", &groupApiModel), + testAccCheckGroupResourceExists(resourceNameGroup, &groupApiModel), testAccCheckGroupResourceValues(&groupApiModel, groupName, "", ""), - resource.TestCheckResourceAttr("aap_group.test", "name", groupName), - resource.TestCheckResourceAttrPair("aap_group.test", "inventory_id", "aap_inventory.test", "id"), - resource.TestMatchResourceAttr("aap_group.test", "url", regexp.MustCompile("^/api(/controller)?/v2/groups/[0-9]*/$")), + checkBasicGroupAttributes(t, resourceNameGroup, groupName), ), }, { Config: testAccGroupResourceComplete(inventoryName, updatedName), Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckGroupResourceExists("aap_group.test", &groupApiModel), + testAccCheckGroupResourceExists(resourceNameGroup, &groupApiModel), testAccCheckGroupResourceValues(&groupApiModel, updatedName, description, variables), - resource.TestCheckResourceAttr("aap_group.test", "name", updatedName), - resource.TestCheckResourceAttrPair("aap_group.test", "inventory_id", "aap_inventory.test", "id"), - resource.TestCheckResourceAttr("aap_group.test", "description", description), - resource.TestCheckResourceAttr("aap_group.test", "variables", variables), - resource.TestMatchResourceAttr("aap_group.test", "url", regexp.MustCompile("^/api(/controller)?/v2/groups/[0-9]*/$")), + checkBasicGroupAttributes(t, resourceNameGroup, updatedName), + resource.TestCheckResourceAttr(resourceNameGroup, "name", updatedName), + resource.TestCheckResourceAttr(resourceNameGroup, "description", description), + resource.TestCheckResourceAttr(resourceNameGroup, "variables", variables), ), }, }, diff --git a/internal/provider/host_resource_test.go b/internal/provider/host_resource_test.go index 0747e88..387bc53 100644 --- a/internal/provider/host_resource_test.go +++ b/internal/provider/host_resource_test.go @@ -277,28 +277,20 @@ func TestAccHostResource(t *testing.T) { { Config: testAccHostResourceMinimal(inventoryName, hostName), Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckHostResourceExists("aap_host.test", &hostApiModel), + checkBasicHostAttributes(t, resourceNameHost, hostName), + testAccCheckHostResourceExists(resourceNameHost, &hostApiModel), testAccCheckHostResourceValues(&hostApiModel, hostName, "", ""), - resource.TestCheckResourceAttr("aap_host.test", "name", hostName), - resource.TestCheckResourceAttrPair("aap_host.test", "inventory_id", "aap_inventory.test", "id"), - resource.TestCheckResourceAttr("aap_host.test", "enabled", "true"), - resource.TestMatchResourceAttr("aap_host.test", "url", regexp.MustCompile("^/api(/controller)?/v2/hosts/[0-9]*/$")), - resource.TestCheckResourceAttrSet("aap_host.test", "id"), ), }, // Update and Read testing { Config: testAccHostResourceComplete(inventoryName, groupName, updatedName), Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckHostResourceExists("aap_host.test", &hostApiModel), + testAccCheckHostResourceExists(resourceNameHost, &hostApiModel), testAccCheckHostResourceValues(&hostApiModel, updatedName, updatedDescription, updatedVariables), - resource.TestCheckResourceAttr("aap_host.test", "name", updatedName), - resource.TestCheckResourceAttrPair("aap_host.test", "inventory_id", "aap_inventory.test", "id"), - resource.TestCheckResourceAttr("aap_host.test", "description", updatedDescription), - resource.TestCheckResourceAttr("aap_host.test", "variables", updatedVariables), - resource.TestCheckResourceAttr("aap_host.test", "enabled", "true"), - resource.TestMatchResourceAttr("aap_host.test", "url", regexp.MustCompile("^/api(/controller)?/v2/hosts/[0-9]*/$")), - resource.TestCheckResourceAttrSet("aap_host.test", "id"), + checkBasicHostAttributes(t, resourceNameHost, updatedName), + resource.TestCheckResourceAttr(resourceNameHost, "description", updatedDescription), + resource.TestCheckResourceAttr(resourceNameHost, "variables", updatedVariables), ), }, }, diff --git a/internal/provider/inventory_data_source_test.go b/internal/provider/inventory_data_source_test.go index 44c9956..bf732b4 100644 --- a/internal/provider/inventory_data_source_test.go +++ b/internal/provider/inventory_data_source_test.go @@ -110,11 +110,11 @@ func TestAccInventoryDataSource(t *testing.T) { { Config: testAccInventoryDataSource(randomName), Check: resource.ComposeAggregateTestCheckFunc( - resource.TestCheckResourceAttrPair("aap_inventory.test", "name", "data.aap_inventory.test", "name"), - resource.TestCheckResourceAttrPair("aap_inventory.test", "organization", "data.aap_inventory.test", "organization"), - resource.TestCheckResourceAttrPair("aap_inventory.test", "description", "data.aap_inventory.test", "description"), - resource.TestCheckResourceAttrPair("aap_inventory.test", "variables", "data.aap_inventory.test", "variables"), - resource.TestCheckResourceAttrPair("aap_inventory.test", "url", "data.aap_inventory.test", "url"), + resource.TestCheckResourceAttrPair(resourceNameInventory, "name", "data.aap_inventory.test", "name"), + resource.TestCheckResourceAttrPair(resourceNameInventory, "organization", "data.aap_inventory.test", "organization"), + resource.TestCheckResourceAttrPair(resourceNameInventory, "description", "data.aap_inventory.test", "description"), + resource.TestCheckResourceAttrPair(resourceNameInventory, "variables", "data.aap_inventory.test", "variables"), + resource.TestCheckResourceAttrPair(resourceNameInventory, "url", "data.aap_inventory.test", "url"), ), }, }, diff --git a/internal/provider/inventory_resource_test.go b/internal/provider/inventory_resource_test.go index d4ca1ab..6e4e74e 100644 --- a/internal/provider/inventory_resource_test.go +++ b/internal/provider/inventory_resource_test.go @@ -186,29 +186,20 @@ func TestAccInventoryResource(t *testing.T) { { Config: testAccInventoryResourceMinimal(randomName), Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckInventoryResourceExists("aap_inventory.test", &inventory), + testAccCheckInventoryResourceExists(resourceNameInventory, &inventory), testAccCheckInventoryResourceValues(&inventory, randomName, "", ""), - resource.TestCheckResourceAttr("aap_inventory.test", "name", randomName), - resource.TestCheckResourceAttr("aap_inventory.test", "organization", "1"), - resource.TestCheckResourceAttr("aap_inventory.test", "organization_name", "Default"), - resource.TestCheckResourceAttrSet("aap_inventory.test", "named_url"), - resource.TestCheckResourceAttrSet("aap_inventory.test", "id"), - resource.TestCheckResourceAttrSet("aap_inventory.test", "url"), + checkBasicInventoryAttributes(t, resourceNameInventory, randomName, "1", "Default"), ), }, // Update and Read testing { Config: testAccInventoryResourceComplete(updatedName), Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckInventoryResourceExists("aap_inventory.test", &inventory), + testAccCheckInventoryResourceExists(resourceNameInventory, &inventory), testAccCheckInventoryResourceValues(&inventory, updatedName, updatedDescription, updatedVariables), - resource.TestCheckResourceAttr("aap_inventory.test", "name", updatedName), - resource.TestCheckResourceAttr("aap_inventory.test", "organization", "1"), - resource.TestCheckResourceAttr("aap_inventory.test", "description", updatedDescription), - resource.TestCheckResourceAttr("aap_inventory.test", "variables", updatedVariables), - resource.TestCheckResourceAttr("aap_inventory.test", "named_url", fmt.Sprintf("/api/controller/v2/inventories/%s++%s/", updatedName, "Default")), - resource.TestCheckResourceAttrSet("aap_inventory.test", "id"), - resource.TestCheckResourceAttrSet("aap_inventory.test", "url"), + checkBasicInventoryAttributes(t, resourceNameInventory, updatedName, "1", "Default"), + resource.TestCheckResourceAttr(resourceNameInventory, "description", updatedDescription), + resource.TestCheckResourceAttr(resourceNameInventory, "variables", updatedVariables), ), }, }, diff --git a/internal/provider/job_resource_test.go b/internal/provider/job_resource_test.go index fc34f27..364b14e 100644 --- a/internal/provider/job_resource_test.go +++ b/internal/provider/job_resource_test.go @@ -6,7 +6,6 @@ import ( "fmt" "os" "reflect" - "regexp" "slices" "testing" "time" @@ -260,8 +259,6 @@ func testAccJobResourcePreCheck(t *testing.T) { } } -const resourceName = "aap_job.test" - func TestAccAAPJob_basic(t *testing.T) { jobTemplateID := os.Getenv("AAP_TEST_JOB_TEMPLATE_ID") @@ -273,9 +270,7 @@ func TestAccAAPJob_basic(t *testing.T) { { Config: testAccBasicJob(jobTemplateID), Check: resource.ComposeAggregateTestCheckFunc( - resource.TestMatchResourceAttr(resourceName, "status", regexp.MustCompile("^(failed|pending|running|complete|successful|waiting)$")), - resource.TestMatchResourceAttr(resourceName, "job_type", regexp.MustCompile("^(run|check)$")), - resource.TestMatchResourceAttr(resourceName, "url", regexp.MustCompile("^/api(/controller)?/v2/jobs/[0-9]*/$")), + checkBasicJobAttributes(t, resourceNameJob, reJobStatus), testAccCheckJobExists, ), }, @@ -297,18 +292,14 @@ func TestAccAAPJob_UpdateWithSameParameters(t *testing.T) { { Config: testAccBasicJob(jobTemplateID), Check: resource.ComposeAggregateTestCheckFunc( - resource.TestMatchResourceAttr(resourceName, "status", regexp.MustCompile("^(failed|pending|running|complete|successful|waiting)$")), - resource.TestMatchResourceAttr(resourceName, "job_type", regexp.MustCompile("^(run|check)$")), - resource.TestMatchResourceAttr(resourceName, "url", regexp.MustCompile("^/api(/controller)?/v2/jobs/[0-9]*/$")), + checkBasicJobAttributes(t, resourceNameJob, reJobStatus), testAccCheckJobUpdate(&jobURLBefore, false), ), }, { Config: testAccBasicJob(jobTemplateID), Check: resource.ComposeAggregateTestCheckFunc( - resource.TestMatchResourceAttr(resourceName, "status", regexp.MustCompile("^(failed|pending|running|complete|successful|waiting)$")), - resource.TestMatchResourceAttr(resourceName, "job_type", regexp.MustCompile("^(run|check)$")), - resource.TestMatchResourceAttr(resourceName, "url", regexp.MustCompile("^/api(/controller)?/v2/jobs/[0-9]*/$")), + checkBasicJobAttributes(t, resourceNameJob, reJobStatus), testAccCheckJobUpdate(&jobURLBefore, false), ), }, @@ -334,21 +325,17 @@ func TestAccAAPJob_UpdateWithNewInventoryIdPromptOnLaunch(t *testing.T) { { Config: testAccBasicJob(jobTemplateID), Check: resource.ComposeAggregateTestCheckFunc( - resource.TestMatchResourceAttr(resourceName, "status", regexp.MustCompile("^(failed|pending|running|complete|successful|waiting)$")), - resource.TestMatchResourceAttr(resourceName, "job_type", regexp.MustCompile("^(run|check)$")), - resource.TestMatchResourceAttr(resourceName, "url", regexp.MustCompile("^/api(/controller)?/v2/jobs/[0-9]*/$")), + checkBasicJobAttributes(t, resourceNameJob, reJobStatus), testAccCheckJobUpdate(&jobURLBefore, false), ), }, { Config: testAccUpdateJobWithInventoryID(inventoryName, jobTemplateID), Check: resource.ComposeAggregateTestCheckFunc( - resource.TestMatchResourceAttr(resourceName, "status", regexp.MustCompile("^(failed|pending|running|complete|successful|waiting)$")), - resource.TestMatchResourceAttr(resourceName, "job_type", regexp.MustCompile("^(run|check)$")), - resource.TestMatchResourceAttr(resourceName, "url", regexp.MustCompile("^/api(/controller)?/v2/jobs/[0-9]*/$")), + checkBasicJobAttributes(t, resourceNameJob, reJobStatus), testAccCheckJobUpdate(&jobURLBefore, true), // Wait for the job to finish so the inventory can be deleted - testAccCheckJobPause(resourceName), + testAccCheckJobPause(resourceNameJob), ), }, }, @@ -369,18 +356,14 @@ func TestAccAAPJob_UpdateWithTrigger(t *testing.T) { { Config: testAccBasicJob(jobTemplateID), Check: resource.ComposeAggregateTestCheckFunc( - resource.TestMatchResourceAttr(resourceName, "status", regexp.MustCompile("^(failed|pending|running|complete|successful|waiting)$")), - resource.TestMatchResourceAttr(resourceName, "job_type", regexp.MustCompile("^(run|check)$")), - resource.TestMatchResourceAttr(resourceName, "url", regexp.MustCompile("^/api(/controller)?/v2/jobs/[0-9]*/$")), + checkBasicJobAttributes(t, resourceNameJob, reJobStatus), testAccCheckJobUpdate(&jobURLBefore, false), ), }, { Config: testAccUpdateJobWithTrigger(jobTemplateID), Check: resource.ComposeAggregateTestCheckFunc( - resource.TestMatchResourceAttr(resourceName, "status", regexp.MustCompile("^(failed|pending|running|complete|successful|waiting)$")), - resource.TestMatchResourceAttr(resourceName, "job_type", regexp.MustCompile("^(run|check)$")), - resource.TestMatchResourceAttr(resourceName, "url", regexp.MustCompile("^/api(/controller)?/v2/jobs/[0-9]*/$")), + checkBasicJobAttributes(t, resourceNameJob, reJobStatus), testAccCheckJobUpdate(&jobURLBefore, true), ), }, @@ -466,9 +449,7 @@ func TestAccAAPJob_disappears(t *testing.T) { { Config: testAccBasicJob(jobTemplateID), Check: resource.ComposeAggregateTestCheckFunc( - resource.TestMatchResourceAttr(resourceName, "status", regexp.MustCompile("^(failed|pending|running|complete|successful|waiting)$")), - resource.TestMatchResourceAttr(resourceName, "job_type", regexp.MustCompile("^(run|check)$")), - resource.TestMatchResourceAttr(resourceName, "url", regexp.MustCompile("^/api(/controller)?/v2/jobs/[0-9]*/$")), + checkBasicJobAttributes(t, resourceNameJob, reJobStatus), testAccCheckJobUpdate(&jobUrl, false), ), }, @@ -476,20 +457,16 @@ func TestAccAAPJob_disappears(t *testing.T) { { Config: testAccBasicJob(jobTemplateID), Check: resource.ComposeAggregateTestCheckFunc( - resource.TestMatchResourceAttr(resourceName, "status", regexp.MustCompile("^(failed|pending|running|complete|successful|waiting)$")), - resource.TestMatchResourceAttr(resourceName, "job_type", regexp.MustCompile("^(run|check)$")), - resource.TestMatchResourceAttr(resourceName, "url", regexp.MustCompile("^/api(/controller)?/v2/jobs/[0-9]*/$")), + checkBasicJobAttributes(t, resourceNameJob, reJobStatus), // Wait for the job to finish so the inventory can be deleted - testAccCheckJobPause(resourceName), + testAccCheckJobPause(resourceNameJob), ), }, // Confirm the job is finished (fewer options in status), then delete directly via API, outside of terraform. { Config: testAccBasicJob(jobTemplateID), Check: resource.ComposeAggregateTestCheckFunc( - resource.TestMatchResourceAttr(resourceName, "status", regexp.MustCompile("^(failed|complete|successful)$")), - resource.TestMatchResourceAttr(resourceName, "job_type", regexp.MustCompile("^(run|check)$")), - resource.TestMatchResourceAttr(resourceName, "url", regexp.MustCompile("^/api(/controller)?/v2/jobs/[0-9]*/$")), + checkBasicJobAttributes(t, resourceNameJob, reJobStatusFinal), testAccDeleteJob(&jobUrl), ), ExpectNonEmptyPlan: true, @@ -498,9 +475,7 @@ func TestAccAAPJob_disappears(t *testing.T) { { Config: testAccBasicJob(jobTemplateID), Check: resource.ComposeAggregateTestCheckFunc( - resource.TestMatchResourceAttr(resourceName, "status", regexp.MustCompile("^(failed|pending|running|complete|successful|waiting)$")), - resource.TestMatchResourceAttr(resourceName, "job_type", regexp.MustCompile("^(run|check)$")), - resource.TestMatchResourceAttr(resourceName, "url", regexp.MustCompile("^/api(/controller)?/v2/jobs/[0-9]*/$")), + checkBasicJobAttributes(t, resourceNameJob, reJobStatus), testAccCheckJobUpdate(&jobUrl, true), ), }, diff --git a/internal/provider/utils_test.go b/internal/provider/utils_test.go index d53f294..a171692 100644 --- a/internal/provider/utils_test.go +++ b/internal/provider/utils_test.go @@ -2,12 +2,79 @@ package provider import ( "errors" + "fmt" + "regexp" "testing" "github.com/hashicorp/terraform-plugin-framework-jsontypes/jsontypes" "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" ) +const ( + resourceNameJob = "aap_job.test" + resourceNameHost = "aap_host.test" + resourceNameGroup = "aap_group.test" + resourceNameInventory = "aap_inventory.test" + resourceNameUser = "aap_user.test" +) + +var ( + reGroupURLPattern = regexp.MustCompile(`^/api(/controller)?/v2/groups/\d+/$`) + reInvalidVars = regexp.MustCompile("Input type `str` is not a dictionary") + + reJobStatus = regexp.MustCompile(`^(failed|pending|running|complete|successful|waiting)$`) + reJobStatusFinal = regexp.MustCompile(`^(failed|complete|successful)$`) + reJobType = regexp.MustCompile(`^(run|check)$`) + reJobURL = regexp.MustCompile(`^/api(/controller)?/v2/jobs/\d+/$`) + + reHostURL = regexp.MustCompile(`^/api(/controller)?/v2/hosts/\d+/$`) + reInventoryURLPattern = regexp.MustCompile(`^/api(/controller)?/v2/inventories/\d+/$`) +) + +//nolint:unparam // keeping name parameter for future test reuse +func checkBasicJobAttributes(t *testing.T, name string, statusPattern *regexp.Regexp) resource.TestCheckFunc { + t.Helper() + return resource.ComposeAggregateTestCheckFunc( + resource.TestMatchResourceAttr(name, "status", statusPattern), + resource.TestMatchResourceAttr(name, "job_type", reJobType), + resource.TestMatchResourceAttr(name, "url", reJobURL), + ) +} + +func checkBasicHostAttributes(t *testing.T, name string, expectedName string) resource.TestCheckFunc { + t.Helper() + return resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr(name, "enabled", "true"), + resource.TestCheckResourceAttrPair(name, "inventory_id", "aap_inventory.test", "id"), + resource.TestCheckResourceAttrSet(name, "id"), + resource.TestMatchResourceAttr(name, "url", reHostURL), + resource.TestCheckResourceAttr(name, "name", expectedName), + ) +} + +func checkBasicGroupAttributes(t *testing.T, name, expectedName string) resource.TestCheckFunc { + t.Helper() + return resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr(name, "name", expectedName), + resource.TestCheckResourceAttrPair(name, "inventory_id", resourceNameInventory, "id"), + resource.TestMatchResourceAttr(name, "url", reGroupURLPattern), + ) +} + +func checkBasicInventoryAttributes(t *testing.T, name, expectedName string, expectedOrgId string, expectedOrgName string) resource.TestCheckFunc { + t.Helper() + return resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr(name, "name", expectedName), + resource.TestCheckResourceAttr(name, "organization", expectedOrgId), + resource.TestCheckResourceAttr(name, "organization_name", expectedOrgName), + resource.TestMatchResourceAttr(name, "url", reInventoryURLPattern), + resource.TestCheckResourceAttr(name, "named_url", fmt.Sprintf("/api/controller/v2/inventories/%s++%s/", expectedName, "Default")), + resource.TestCheckResourceAttrSet(name, "id"), + resource.TestCheckResourceAttrSet("aap_inventory.test", "url"), + ) +} + func TestReturnAAPNamedURL(t *testing.T) { var testTable = []struct { id types.Int64 diff --git a/makefiles/golangci.mk b/makefiles/golangci.mk new file mode 100644 index 0000000..40203e1 --- /dev/null +++ b/makefiles/golangci.mk @@ -0,0 +1,28 @@ + +ifndef GOLANGCI_LINT_MK_INCLUDED + +TOOLS_DIR := $(CURDIR)/.tools +GOLANGCI_LINT := $(TOOLS_DIR)/golangci-lint +GOLANGCI_LINT_VERSION ?= v1.60.1 + +export GOLANGCI_LINT + +$(GOLANGCI_LINT): + @echo "==> Installing golangci-lint into $(TOOLS_DIR)..." + @mkdir -p $(TOOLS_DIR) + @curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(TOOLS_DIR) $(GOLANGCI_LINT_VERSION) + +.PHONY: lint-tools +lint-tools: $(GOLANGCI_LINT) + +.PHONY: lint +lint: lint-tools ## Run static analysis via golangci-lint + @echo "==> Checking source code against linters..." + $(GOLANGCI_LINT) run -v ./... + +gofmt: ## Format Go source code in 'internal/provider' using gofmt. + @echo "==> Format code using gofmt..." + gofmt -s -w internal/provider + +GOLANGCI_LINT_MK_INCLUDED := 1 +endif