From ddb16964d91cd50387be860822821857cd3185e5 Mon Sep 17 00:00:00 2001 From: 1riatsila1 Date: Tue, 5 Nov 2024 10:56:25 +0400 Subject: [PATCH] feat: acceptance-tests | groups --- Justfile | 11 ++ test/live/provider/provider.go | 24 ++++ test/live/resources/group_test.go | 189 ++++++++++++++++++++++++++++++ test/live/util/util.go | 56 +++++++++ 4 files changed, 280 insertions(+) create mode 100644 test/live/provider/provider.go create mode 100644 test/live/resources/group_test.go create mode 100644 test/live/util/util.go diff --git a/Justfile b/Justfile index b15a8130..55cbdb26 100644 --- a/Justfile +++ b/Justfile @@ -87,6 +87,17 @@ coverage-provider: tidy-tools: cd {{ TOOLS_PROVIDER_DIR }} && go mod tidy +acceptance-tests +ARGS='': + #!/usr/bin/env bash + + read -p "This is going to run requests against UXI backend. Continue (y/Y)? " -n 1 -r + echo + if [[ $REPLY =~ ^[Yy]$ ]] + then + TF_ACC=1 go test -v ./test/live/... -race -covermode=atomic -coverprofile=.coverage {{ ARGS }} + fi + + test +ARGS='': just test-client {{ ARGS }} just test-provider {{ ARGS }} diff --git a/test/live/provider/provider.go b/test/live/provider/provider.go new file mode 100644 index 00000000..7ae3024f --- /dev/null +++ b/test/live/provider/provider.go @@ -0,0 +1,24 @@ +package provider + +import ( + "github.com/aruba-uxi/terraform-provider-configuration-api/internal/provider" + "github.com/aruba-uxi/terraform-provider-configuration-api/test/live/util" + "github.com/hashicorp/terraform-plugin-framework/providerserver" + "github.com/hashicorp/terraform-plugin-go/tfprotov6" +) + +var ( + ProviderConfig = `provider "uxi" { + host = "api.staging.capedev.io" + client_id = "` + util.CLIENT_ID + `" + client_secret = "` + util.CLIENT_SECRET + `" + token_url = "https://sso.common.cloud.hpe.com/as/token.oauth2" + }` + // TestAccProtoV6ProviderFactories are used to instantiate a provider during + // acceptance testing. The factory function will be invoked for every Terraform + // CLI command executed to create a provider server to which the CLI can + // reattach. + TestAccProtoV6ProviderFactories = map[string]func() (tfprotov6.ProviderServer, error){ + "uxi": providerserver.NewProtocol6WithError(provider.New("test")()), + } +) diff --git a/test/live/resources/group_test.go b/test/live/resources/group_test.go new file mode 100644 index 00000000..217b311e --- /dev/null +++ b/test/live/resources/group_test.go @@ -0,0 +1,189 @@ +package resource_test + +import ( + "fmt" + "regexp" + "testing" + + "github.com/aruba-uxi/terraform-provider-configuration-api/test/live/provider" + "github.com/aruba-uxi/terraform-provider-configuration-api/test/live/util" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" +) + +type Fetcher interface { + FetchData() ([]byte, error) +} + +var rootGroup = util.GetRoot() + +func TestGroupResource(t *testing.T) { + resource.Test(t, resource.TestCase{ + ProtoV6ProviderFactories: provider.TestAccProtoV6ProviderFactories, + Steps: []resource.TestStep{ + // Create and Read testing + { + // Node without parent (attached to root) + Config: provider.ProviderConfig + ` + resource "uxi_group" "parent" { + name = "tf_provider_acceptance_test_parent" + }`, + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr( + "uxi_group.parent", + "name", + "tf_provider_acceptance_test_parent", + ), + resource.TestCheckResourceAttrPtr( + "uxi_group.parent", + "parent_group_id", + &rootGroup.Id, + ), + ), + }, + // ImportState testing + { + ResourceName: "uxi_group.parent", + ImportState: true, + ImportStateVerify: true, + }, + // Update that does not trigger a recreate + { + Config: provider.ProviderConfig + ` + resource "uxi_group" "parent" { + name = "tf_provider_acceptance_test_parent_name_updated" + }`, + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr( + "uxi_group.parent", + "name", + "tf_provider_acceptance_test_parent_name_updated", + ), + resource.TestCheckResourceAttrPtr( + "uxi_group.parent", + "parent_group_id", + &rootGroup.Id, + ), + ), + }, + // Create nodes attached to non root node + { + Config: provider.ProviderConfig + ` + resource "uxi_group" "parent" { + name = "tf_provider_acceptance_test_parent_name_updated" + } + + resource "uxi_group" "child" { + name = "tf_provider_acceptance_test_child" + parent_group_id = uxi_group.parent.id + } + + resource "uxi_group" "grandchild" { + name = "tf_provider_acceptance_test_grandchild" + parent_group_id = uxi_group.child.id + }`, + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr( + "uxi_group.child", + "name", + "tf_provider_acceptance_test_child", + ), + resource.TestCheckResourceAttrWith( + "uxi_group.child", + "parent_group_id", + func(parentGroupId string) error { + return checkGroupIsChildOfNode( + parentGroupId, + "tf_provider_acceptance_test_parent_name_updated", + ) + }, + ), + resource.TestCheckResourceAttr( + "uxi_group.grandchild", + "name", + "tf_provider_acceptance_test_grandchild", + ), + resource.TestCheckResourceAttrWith( + "uxi_group.grandchild", + "parent_group_id", + func(parentGroupId string) error { + return checkGroupIsChildOfNode( + parentGroupId, "tf_provider_acceptance_test_child", + ) + }, + ), + ), + }, + // Update that does trigger a recreate (moving group) + { + Config: provider.ProviderConfig + ` + resource "uxi_group" "parent" { + name = "tf_provider_acceptance_test_parent_name_updated" + } + + resource "uxi_group" "child" { + name = "tf_provider_acceptance_test_child" + parent_group_id = uxi_group.parent.id + } + + # move grandchild from child to parent + resource "uxi_group" "grandchild" { + name = "tf_provider_acceptance_test_grandchild_moved_to_parent" + parent_group_id = uxi_group.parent.id + }`, + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr( + "uxi_group.grandchild", + "name", + "tf_provider_acceptance_test_grandchild_moved_to_parent", + ), + resource.TestCheckResourceAttrWith( + "uxi_group.grandchild", + "parent_group_id", + func(parentGroupId string) error { + return checkGroupIsChildOfNode( + parentGroupId, + "tf_provider_acceptance_test_parent_name_updated", + ) + }, + ), + ), + }, + // Deletes happen automatically + }, + }) +} + +func TestRootGroupResource(t *testing.T) { + resource.Test(t, resource.TestCase{ + ProtoV6ProviderFactories: provider.TestAccProtoV6ProviderFactories, + Steps: []resource.TestStep{ + // Importing the root group does not work + { + Config: provider.ProviderConfig + ` + resource "uxi_group" "my_root_group" { + name = "root" + } + + import { + to = uxi_group.my_root_group + id = "` + rootGroup.Id + `" + }`, + ExpectError: regexp.MustCompile(`The root group cannot be used as a resource`), + }, + }, + }) +} + +func checkGroupIsChildOfNode(actualParentGroupId, expectedParentName string) error { + expectedParentGroupId := util.GetNodeByName(expectedParentName).GetId() + + if expectedParentGroupId != actualParentGroupId { + return fmt.Errorf( + "expected \"%s\", but got \"%s\"", + expectedParentGroupId, + actualParentGroupId, + ) + } + + return nil +} diff --git a/test/live/util/util.go b/test/live/util/util.go new file mode 100644 index 00000000..a04cbdd0 --- /dev/null +++ b/test/live/util/util.go @@ -0,0 +1,56 @@ +package util + +import ( + "context" + "os" + + resources_util "github.com/aruba-uxi/terraform-provider-configuration-api/internal/provider/util" + "github.com/aruba-uxi/terraform-provider-configuration-api/pkg/config-api-client" + "golang.org/x/oauth2" + "golang.org/x/oauth2/clientcredentials" +) + +var CLIENT_ID = os.Getenv("UXI_CLIENT_ID") +var CLIENT_SECRET = os.Getenv("UXI_CLIENT_SECRET") + +const HOST = "api.staging.capedev.io" +const TOKEN_URL = "https://sso.common.cloud.hpe.com/as/token.oauth2" + +func NewClient() *config_api_client.APIClient { + config := &clientcredentials.Config{ + ClientID: CLIENT_ID, + ClientSecret: CLIENT_SECRET, + TokenURL: TOKEN_URL, + AuthStyle: oauth2.AuthStyleInParams, + } + + // Create a context and fetch a token + uxiConfiguration := config_api_client.NewConfiguration() + uxiConfiguration.Host = HOST + uxiConfiguration.Scheme = "https" + uxiConfiguration.HTTPClient = config.Client(context.Background()) + + return config_api_client.NewAPIClient(uxiConfiguration) +} + +func GetRoot() *config_api_client.GroupsGetItem { + groups, _, _ := Client.ConfigurationAPI.GroupsGet(context.Background()).Execute() + for _, group := range groups.Items { + if resources_util.IsRoot(group) { + return &group + } + } + return nil +} + +func GetNodeByName(name string) *config_api_client.GroupsGetItem { + groups, _, _ := Client.ConfigurationAPI.GroupsGet(context.Background()).Execute() + for _, group := range groups.Items { + if group.Name == name { + return &group + } + } + return nil +} + +var Client = NewClient()