diff --git a/client/fc/fc_service_test.go b/client/fc/fc_service_test.go new file mode 100644 index 000000000..1146c09fc --- /dev/null +++ b/client/fc/fc_service_test.go @@ -0,0 +1,618 @@ +package foundationcentral + +import ( + "context" + "fmt" + "net/http" + "net/http/httptest" + "net/url" + "reflect" + "testing" + + "github.com/terraform-providers/terraform-provider-nutanix/client" + "github.com/terraform-providers/terraform-provider-nutanix/utils" +) + +func setup() (*http.ServeMux, *client.Client, *httptest.Server) { + mux := http.NewServeMux() + server := httptest.NewServer(mux) + c, _ := client.NewClient(&client.Credentials{ + URL: "https://10.2.242.13:9440", + Username: "admin", + Password: "Nutanix.123", + Port: "9440", + Endpoint: "10.2.242.13", + Insecure: true}, + userAgent, + absolutePath, + false) + c.BaseURL, _ = url.Parse(server.URL) + + return mux, c, server +} + +func testHTTPMethod(t *testing.T, r *http.Request, expected string) { + if expected != r.Method { + t.Errorf("Request method = %v, expected %v", r.Method, expected) + } +} + +func TestOperations_ListImagedNodes(t *testing.T) { + mux, c, server := setup() + + defer server.Close() + + mux.HandleFunc("/api/fc/v1/imaged_nodes/list", func(w http.ResponseWriter, r *http.Request) { + testHTTPMethod(t, r, http.MethodPost) + fmt.Fprint(w, `{"imaged_nodes":[{"node_state": "STATE_AVAILABLE"}]}`) + }) + + list := &ImagedNodesListResponse{} + list.ImagedNodes = make([]*ImagedNodeDetails, 1) + list.ImagedNodes[0] = &ImagedNodeDetails{} + list.ImagedNodes[0].NodeState = utils.StringPtr("STATE_AVAILABLE") + + input := &ImagedNodesListInput{ + Length: utils.IntPtr(1), + } + + type fields struct { + client *client.Client + } + + type args struct { + getEntitiesRequest *ImagedNodesListInput + } + ctx := context.TODO() + tests := []struct { + name string + fields fields + args args + want *ImagedNodesListResponse + wantErr bool + }{ + { + "Test Imaged Nodes", + fields{c}, + args{input}, + list, + false, + }, + } + + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + op := Operations{ + client: tt.fields.client, + } + got, err := op.ListImagedNodes(ctx, tt.args.getEntitiesRequest) + if (err != nil) != tt.wantErr { + t.Errorf("Operations.ListImagedNodes() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("Operations.ListImagedNodes() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestOperations_ListImagedClusters(t *testing.T) { + mux, c, server := setup() + + defer server.Close() + + mux.HandleFunc("/api/fc/v1/imaged_clusters/list", func(w http.ResponseWriter, r *http.Request) { + testHTTPMethod(t, r, http.MethodPost) + fmt.Fprint(w, `{"imaged_clusters":[{"cluster_name": "Test-Cluster"}]}`) + }) + + list := &ImagedClustersListResponse{} + list.ImagedClusters = make([]*ImagedClusterDetails, 1) + list.ImagedClusters[0] = &ImagedClusterDetails{} + list.ImagedClusters[0].ClusterName = utils.StringPtr("Test-Cluster") + + input := &ImagedClustersListInput{ + Length: utils.IntPtr(1), + } + + type fields struct { + client *client.Client + } + + type args struct { + getEntitiesRequest *ImagedClustersListInput + } + ctx := context.TODO() + tests := []struct { + name string + fields fields + args args + want *ImagedClustersListResponse + wantErr bool + }{ + { + "Test Imaged Clusters", + fields{c}, + args{input}, + list, + false, + }, + } + + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + op := Operations{ + client: tt.fields.client, + } + got, err := op.ListImagedClusters(ctx, tt.args.getEntitiesRequest) + if (err != nil) != tt.wantErr { + t.Errorf("Operations.ListImagedClusters() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("Operations.ListImagedClusters() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestOperations_ListAPIKeys(t *testing.T) { + mux, c, server := setup() + + defer server.Close() + + mux.HandleFunc("/api/fc/v1/api_keys/list", func(w http.ResponseWriter, r *http.Request) { + testHTTPMethod(t, r, http.MethodPost) + fmt.Fprint(w, `{"api_keys":[{"api_key": "00a9-23h9", "alias":"test-1"}]}`) + }) + + list := &ListAPIKeysResponse{} + list.APIKeys = make([]*CreateAPIKeysResponse, 1) + list.APIKeys[0] = &CreateAPIKeysResponse{} + list.APIKeys[0].APIKey = "00a9-23h9" + list.APIKeys[0].Alias = "test-1" + + input := &ListMetadataInput{ + Length: utils.IntPtr(1), + } + + type fields struct { + client *client.Client + } + + type args struct { + getEntitiesRequest *ListMetadataInput + } + ctx := context.TODO() + tests := []struct { + name string + fields fields + args args + want *ListAPIKeysResponse + wantErr bool + }{ + { + "Test List API Keys", + fields{c}, + args{input}, + list, + false, + }, + } + + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + op := Operations{ + client: tt.fields.client, + } + got, err := op.ListAPIKeys(ctx, tt.args.getEntitiesRequest) + if (err != nil) != tt.wantErr { + t.Errorf("Operations.ListAPIKeys() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("Operations.ListAPIKeys() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestOperations_GetImagedNode(t *testing.T) { + mux, c, server := setup() + + defer server.Close() + + mux.HandleFunc("/api/fc/v1/imaged_nodes/0a8x-23d8", func(w http.ResponseWriter, r *http.Request) { + testHTTPMethod(t, r, http.MethodGet) + fmt.Fprint(w, `{"api_key_uuid": "234d-876f", "available": true, "cvm_ip": "10.0.0.0"}`) + }) + + node := &ImagedNodeDetails{} + node.APIKeyUUID = utils.StringPtr("234d-876f") + node.Available = utils.BoolPtr(true) + node.CvmIP = utils.StringPtr("10.0.0.0") + + type fields struct { + client *client.Client + } + + type args struct { + KeyUUID string + } + ctx := context.TODO() + tests := []struct { + name string + fields fields + args args + want *ImagedNodeDetails + wantErr bool + }{ + { + "Get Imaged Node Details", + fields{c}, + args{"0a8x-23d8"}, + node, + false, + }, + } + + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + op := Operations{ + client: tt.fields.client, + } + got, err := op.GetImagedNode(ctx, tt.args.KeyUUID) + if (err != nil) != tt.wantErr { + t.Errorf("Operations.GetImagedNode() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("Operations.GetImagedNode() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestOperations_GetImagedCluster(t *testing.T) { + mux, c, server := setup() + + defer server.Close() + + mux.HandleFunc("/api/fc/v1/imaged_clusters/0a8x-23d8", func(w http.ResponseWriter, r *http.Request) { + testHTTPMethod(t, r, http.MethodGet) + fmt.Fprint(w, `{"cluster_name": "test-cluster", "archived": true, "cluster_external_ip": "10.0.0.0"}`) + }) + + cluster := &ImagedClusterDetails{} + cluster.ClusterName = utils.StringPtr("test-cluster") + cluster.Archived = utils.BoolPtr(true) + cluster.ClusterExternalIP = utils.StringPtr("10.0.0.0") + + type fields struct { + client *client.Client + } + + type args struct { + KeyUUID string + } + ctx := context.TODO() + tests := []struct { + name string + fields fields + args args + want *ImagedClusterDetails + wantErr bool + }{ + { + "Get Imaged Cluster Details", + fields{c}, + args{"0a8x-23d8"}, + cluster, + false, + }, + } + + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + op := Operations{ + client: tt.fields.client, + } + got, err := op.GetImagedCluster(ctx, tt.args.KeyUUID) + if (err != nil) != tt.wantErr { + t.Errorf("Operations.GetImagedCluster() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("Operations.GetImagedCluster() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestOperations_GetAPIKey(t *testing.T) { + mux, c, server := setup() + + defer server.Close() + + mux.HandleFunc("/api/fc/v1/api_keys/20ca-4d4c-61fd", func(w http.ResponseWriter, r *http.Request) { + testHTTPMethod(t, r, http.MethodGet) + + fmt.Fprint(w, `{ + "api_key": "1243-7645", + "alias": "test-key", + "created_timestamp": "2022-04-27T05:15:59.000-07:00", + "current_time": "2022-04-27T09:33:25.000-07:00", + "key_uuid": "20ca-4d4c-61fd" + }`) + }) + + apiKey := &CreateAPIKeysResponse{} + apiKey.APIKey = "1243-7645" + apiKey.Alias = "test-key" + apiKey.CreatedTimestamp = "2022-04-27T05:15:59.000-07:00" + apiKey.CurrentTime = "2022-04-27T09:33:25.000-07:00" + apiKey.KeyUUID = "20ca-4d4c-61fd" + + type fields struct { + client *client.Client + } + + type args struct { + KeyUUID string + } + ctx := context.TODO() + tests := []struct { + name string + fields fields + args args + want *CreateAPIKeysResponse + wantErr bool + }{ + { + "Get API Key Details", + fields{c}, + args{"20ca-4d4c-61fd"}, + apiKey, + false, + }, + } + + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + op := Operations{ + client: tt.fields.client, + } + got, err := op.GetAPIKey(ctx, tt.args.KeyUUID) + if (err != nil) != tt.wantErr { + t.Errorf("Operations.GetAPIKey() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("Operations.GetAPIKey() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestOperations_CreateAPIKey(t *testing.T) { + mux, c, server := setup() + + defer server.Close() + + mux.HandleFunc("/api/fc/v1/api_keys", func(w http.ResponseWriter, r *http.Request) { + testHTTPMethod(t, r, http.MethodPost) + + fmt.Fprint(w, `{ + "api_key": "1243-7645", + "alias": "test-key", + "created_timestamp": "2022-04-27T05:15:59.000-07:00", + "current_time": "2022-04-27T09:33:25.000-07:00", + "key_uuid": "20ca-4d4c-61fd" + }`) + }) + + apiKey := &CreateAPIKeysResponse{} + apiKey.APIKey = "1243-7645" + apiKey.Alias = "test-key" + apiKey.CreatedTimestamp = "2022-04-27T05:15:59.000-07:00" + apiKey.CurrentTime = "2022-04-27T09:33:25.000-07:00" + apiKey.KeyUUID = "20ca-4d4c-61fd" + + input := &CreateAPIKeysInput{ + Alias: "test-key", + } + + type fields struct { + client *client.Client + } + + type args struct { + alias *CreateAPIKeysInput + } + + ctx := context.TODO() + tests := []struct { + name string + fields fields + args args + want *CreateAPIKeysResponse + wantErr bool + }{ + { + "Create API Key", + fields{c}, + args{input}, + apiKey, + false, + }, + } + + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + op := Operations{ + client: tt.fields.client, + } + got, err := op.CreateAPIKey(ctx, tt.args.alias) + if (err != nil) != tt.wantErr { + t.Errorf("Operations.CreateAPIKey() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("Operations.CreateAPIKey() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestOperations_CreateCluster(t *testing.T) { + mux, c, server := setup() + + defer server.Close() + + mux.HandleFunc("/api/fc/v1/imaged_clusters", func(w http.ResponseWriter, r *http.Request) { + testHTTPMethod(t, r, http.MethodPost) + + fmt.Fprint(w, `{ + "imaged_cluster_uuid": "123-654-678" + }`) + }) + + clusterUUID := &CreateClusterResponse{ + ImagedClusterUUID: utils.StringPtr("123-654-678"), + } + + input := &CreateClusterInput{ + CommonNetworkSettings: &CommonNetworkSettings{ + CvmDNSServers: []string{"10.0.0.0"}, + HypervisorDNSServers: []string{"10.0.0.0"}, + CvmNtpServers: []string{"0.0.0.0"}, + HypervisorNtpServers: []string{"0.0.0.0"}, + }, + RedundancyFactor: utils.IntPtr(2), + AosPackageURL: utils.StringPtr("test_aos.tar.gz"), + ClusterName: utils.StringPtr("test-cluster"), + NodesList: []*Node{ + { + CvmGateway: utils.StringPtr("0.0.0.0"), + IpmiNetmask: utils.StringPtr("255.255.255.0"), + ImagedNodeUUID: utils.StringPtr("12n0-vh87"), + HypervisorType: utils.StringPtr("kvm"), + ImageNow: utils.BoolPtr(true), + HypervisorHostname: utils.StringPtr("HOST-1"), + HypervisorNetmask: utils.StringPtr("255.255.255.0"), + HypervisorGateway: utils.StringPtr("0.0.0.0"), + CvmIP: utils.StringPtr("10.0.0.0"), + CvmNetmask: utils.StringPtr("255.255.255.0"), + IpmiIP: utils.StringPtr("10.0.0.0"), + HypervisorIP: utils.StringPtr("10.0.0.0"), + IpmiGateway: utils.StringPtr("0.0.0.0"), + UseExistingNetworkSettings: utils.BoolPtr(false), + }, + }, + HypervisorIsoDetails: &HypervisorIsoDetails{ + URL: utils.StringPtr("hypervisor.iso.tar.gz"), + }, + } + + type fields struct { + client *client.Client + } + + type args struct { + spec *CreateClusterInput + } + + ctx := context.TODO() + tests := []struct { + name string + fields fields + args args + want *CreateClusterResponse + wantErr bool + }{ + { + "Imaged Nodes and create Cluster ", + fields{c}, + args{input}, + clusterUUID, + false, + }, + } + + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + op := Operations{ + client: tt.fields.client, + } + got, err := op.CreateCluster(ctx, tt.args.spec) + if (err != nil) != tt.wantErr { + t.Errorf("Operations.CreateCluster() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("Operations.CreateCluster() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestOperations_DeleteCluster(t *testing.T) { + mux, c, server := setup() + + defer server.Close() + + mux.HandleFunc("/api/fc/v1/imaged_clusters/4e87-4a75-960f", func(w http.ResponseWriter, r *http.Request) { + testHTTPMethod(t, r, http.MethodDelete) + }) + + type fields struct { + client *client.Client + } + + type args struct { + UUID string + } + ctx := context.TODO() + + tests := []struct { + name string + fields fields + args args + wantErr bool + }{ + { + "Test Delete Cluster OK", + fields{c}, + args{"4e87-4a75-960f"}, + false, + }, + + { + "Test Delete Cluster Errored", + fields{c}, + args{}, + true, + }, + } + + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + op := Operations{ + client: tt.fields.client, + } + if err := op.DeleteCluster(ctx, tt.args.UUID); (err != nil) != tt.wantErr { + t.Errorf("Operations.DeleteCluster() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/client/fc/fc_test.go b/client/fc/fc_test.go new file mode 100644 index 000000000..f2718a2e3 --- /dev/null +++ b/client/fc/fc_test.go @@ -0,0 +1,44 @@ +package foundationcentral + +import ( + "testing" + + "github.com/terraform-providers/terraform-provider-nutanix/client" +) + +func TestNewFoundationCentralClient(t *testing.T) { + // verifies positive client creation + cred := client.Credentials{ + URL: "foo.com", + Username: "username", + Password: "password", + Port: "", + Endpoint: "0.0.0.0", + Insecure: true, + FoundationEndpoint: "10.0.0.0", + FoundationPort: "8000", + RequiredFields: nil, + } + _, err := NewFoundationCentralClient(cred) + if err != nil { + t.Errorf(err.Error()) + } + + // verify missing client scenario + cred2 := client.Credentials{ + URL: "foo.com", + Insecure: true, + RequiredFields: map[string][]string{ + "prism_central": {"username", "password", "endpoint"}, + "foundation_central": {"username", "password", "endpoint"}, + }, + } + FcClient2, err2 := NewFoundationCentralClient(cred2) + if err2 != nil { + t.Errorf(err2.Error()) + } + + if FcClient2.client.ErrorMsg == "" { + t.Errorf("NewFoundationCentralClient(%v) expected the base client in v3 client to have some error message", cred2) + } +} diff --git a/nutanix/data_source_nutanix_foundation_central_api_keys_test.go b/nutanix/data_source_nutanix_foundation_central_api_keys_test.go new file mode 100644 index 000000000..8db86e6b4 --- /dev/null +++ b/nutanix/data_source_nutanix_foundation_central_api_keys_test.go @@ -0,0 +1,62 @@ +package nutanix + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +func TestAccFCAPIKeysDataSource_basic(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccAPIKeysDataSourceConfig(), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.nutanix_foundation_central_list_api_keys.test", "api_keys.#"), + ), + }, + }, + }) +} + +func TestAccFCAPIKeysDataSource_KeyUUID(t *testing.T) { + apiKeyName := acctest.RandomWithPrefix("test-key") + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccAPIKeysDataSourceConfigWithKeyUUID(apiKeyName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("data.nutanix_foundation_central_api_keys.k1", "alias", apiKeyName), + resource.TestCheckResourceAttrSet("data.nutanix_foundation_central_api_keys.k1", "alias"), + resource.TestCheckResourceAttrSet("data.nutanix_foundation_central_api_keys.k1", "created_timestamp"), + resource.TestCheckResourceAttrSet("data.nutanix_foundation_central_api_keys.k1", "current_time"), + ), + }, + }, + }) +} + +func testAccAPIKeysDataSourceConfig() string { + return ` + data "nutanix_foundation_central_list_api_keys" "test"{} + ` +} + +func testAccAPIKeysDataSourceConfigWithKeyUUID(apiKeyName string) string { + return fmt.Sprintf(` + resource "nutanix_foundation_central_api_keys" "apk"{ + alias = "%s" + } + + data "nutanix_foundation_central_api_keys" "k1"{ + key_uuid = "${nutanix_foundation_central_api_keys.apk.key_uuid}" + } + + `, apiKeyName) +} diff --git a/nutanix/data_source_nutanix_foundation_central_cluster_details_test.go b/nutanix/data_source_nutanix_foundation_central_cluster_details_test.go new file mode 100644 index 000000000..f4033d796 --- /dev/null +++ b/nutanix/data_source_nutanix_foundation_central_cluster_details_test.go @@ -0,0 +1,55 @@ +package nutanix + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +func TestAccFCClusterDetailsDataSource_basic(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccFCClusterDetailsDataSourceConfig(), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.nutanix_foundation_central_imaged_clusters_list.cls", "imaged_clusters.#"), + ), + }, + }, + }) +} + +func TestAccFCClusterDetailsDataSource_ClusterUUID(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccFCClusterDetailsDataSourceConfigWithUUID(), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.nutanix_foundation_central_imaged_clusters_list.cls", "imaged_clusters.#"), + resource.TestCheckResourceAttr("data.nutanix_foundation_central_cluster_details.k1", "storage_node_count", "0"), + resource.TestCheckResourceAttrSet("data.nutanix_foundation_central_cluster_details.k1", "imaged_cluster_uuid"), + ), + }, + }, + }) +} + +func testAccFCClusterDetailsDataSourceConfig() string { + return ` + data "nutanix_foundation_central_imaged_clusters_list" "cls" {} + ` +} + +func testAccFCClusterDetailsDataSourceConfigWithUUID() string { + return ` + data "nutanix_foundation_central_imaged_clusters_list" "cls" {} + + data "nutanix_foundation_central_cluster_details" "k1"{ + imaged_cluster_uuid = "${data.nutanix_foundation_central_imaged_clusters_list.cls.imaged_clusters[0].imaged_cluster_uuid}" + } + ` +} diff --git a/nutanix/data_source_nutanix_foundation_central_imaged_clusters_list_test.go b/nutanix/data_source_nutanix_foundation_central_imaged_clusters_list_test.go new file mode 100644 index 000000000..3644bf33d --- /dev/null +++ b/nutanix/data_source_nutanix_foundation_central_imaged_clusters_list_test.go @@ -0,0 +1,28 @@ +package nutanix + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +func TestAccFCClusterListDataSource_basic(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccFCClusterListDataSourceConfig(), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.nutanix_foundation_central_imaged_clusters_list.cls", "imaged_clusters.#"), + ), + }, + }, + }) +} + +func testAccFCClusterListDataSourceConfig() string { + return ` + data "nutanix_foundation_central_imaged_clusters_list" "cls" {} + ` +} diff --git a/nutanix/data_source_nutanix_foundation_central_imaged_node_details_test.go b/nutanix/data_source_nutanix_foundation_central_imaged_node_details_test.go new file mode 100644 index 000000000..fdd6b295a --- /dev/null +++ b/nutanix/data_source_nutanix_foundation_central_imaged_node_details_test.go @@ -0,0 +1,55 @@ +package nutanix + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +func TestAccFCNodeDetailsDataSource_basic(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccFCNodeDetailsDataSourceConfig(), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.nutanix_foundation_central_imaged_nodes_list.cls", "imaged_nodes.#"), + ), + }, + }, + }) +} + +func TestAccFCNodeDetailsDataSource_NodeUUID(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccFCNodeDetailsDataSourceConfigWithUUID(), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.nutanix_foundation_central_imaged_nodes_list.cls", "imaged_nodes.#"), + resource.TestCheckResourceAttr("data.nutanix_foundation_central_imaged_node_details.k1", "cvm_vlan_id", "0"), + resource.TestCheckResourceAttrSet("data.nutanix_foundation_central_imaged_node_details.k1", "imaged_node_uuid"), + ), + }, + }, + }) +} + +func testAccFCNodeDetailsDataSourceConfig() string { + return ` + data "nutanix_foundation_central_imaged_nodes_list" "cls" {} + ` +} + +func testAccFCNodeDetailsDataSourceConfigWithUUID() string { + return ` + data "nutanix_foundation_central_imaged_nodes_list" "cls" {} + + data "nutanix_foundation_central_imaged_node_details" "k1"{ + imaged_node_uuid = "${data.nutanix_foundation_central_imaged_nodes_list.cls.imaged_nodes[0].imaged_node_uuid}" + } + ` +} diff --git a/nutanix/data_source_nutanix_foundation_central_imaged_nodes_list_test.go b/nutanix/data_source_nutanix_foundation_central_imaged_nodes_list_test.go new file mode 100644 index 000000000..78301d276 --- /dev/null +++ b/nutanix/data_source_nutanix_foundation_central_imaged_nodes_list_test.go @@ -0,0 +1,28 @@ +package nutanix + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +func TestAccFCNodesListDataSource_basic(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccFCNodeListDataSourceConfig(), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.nutanix_foundation_central_imaged_nodes_list.cls", "imaged_nodes.#"), + ), + }, + }, + }) +} + +func testAccFCNodeListDataSourceConfig() string { + return ` + data "nutanix_foundation_central_imaged_nodes_list" "cls" {} + ` +} diff --git a/nutanix/data_source_nutanix_foundation_central_list_api_keys_test.go b/nutanix/data_source_nutanix_foundation_central_list_api_keys_test.go new file mode 100644 index 000000000..3cf99a9a6 --- /dev/null +++ b/nutanix/data_source_nutanix_foundation_central_list_api_keys_test.go @@ -0,0 +1,28 @@ +package nutanix + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +func TestAccFCAPIKeysListDataSource_basic(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccAPIKeysListDataSourceConfig(), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.nutanix_foundation_central_list_api_keys.test", "api_keys.#"), + ), + }, + }, + }) +} + +func testAccAPIKeysListDataSourceConfig() string { + return ` + data "nutanix_foundation_central_list_api_keys" "test"{} + ` +} diff --git a/nutanix/main_test.go b/nutanix/main_test.go index 81a813e2e..edf7f0a23 100644 --- a/nutanix/main_test.go +++ b/nutanix/main_test.go @@ -39,6 +39,7 @@ type IPMIConfig struct { IpmiIP string `json:"ipmi_ip"` IpmiMac string `json:"ipmi_mac"` } + type FoundationVars struct { IPv6Addresses []string `json:"ipv6_addresses"` IpmiConfig IPMIConfig `json:"ipmi_config"` @@ -56,13 +57,24 @@ type FoundationVars struct { NodePosition string `json:"node_position"` IPv6Address string `json:"ipv6_address"` CurrentNetworkInterface string `json:"current_network_interface"` + ImagedNodeUUID string `json:"imaged_node_uuid"` + HypervisorType string `json:"hypervisor_type"` } `json:"nodes"` - BlockID string `json:"block_id"` - CvmGateway string `json:"cvm_gateway"` - HypervisorGateway string `json:"hypervisor_gateway"` - CvmNetmask string `json:"cvm_netmask"` - HypervisorNetmask string `json:"hypervisor_netmask"` - IpmiUser string `json:"ipmi_user"` + BlockID string `json:"block_id"` + CvmGateway string `json:"cvm_gateway"` + HypervisorGateway string `json:"hypervisor_gateway"` + CvmNetmask string `json:"cvm_netmask"` + HypervisorNetmask string `json:"hypervisor_netmask"` + IpmiUser string `json:"ipmi_user"` + AosPackageURL string `json:"aos_package_url"` + UseExistingNetworkSettings bool `json:"use_existing_network_settings"` + ImageNow bool `json:"image_now"` + CommonNetworkSettings struct { + CvmDNSServers []string `json:"cvm_dns_servers"` + HypervisorDNSServers []string `json:"hypervisor_dns_servers"` + CvmNtpServers []string `json:"cvm_ntp_servers"` + HypervisorNtpServers []string `json:"hypervisor_ntp_servers"` + } `json:"common_network_settings"` } `json:"blocks"` } diff --git a/nutanix/resource_nutanix_foundation_central_api_keys_test.go b/nutanix/resource_nutanix_foundation_central_api_keys_test.go new file mode 100644 index 000000000..50a124f5f --- /dev/null +++ b/nutanix/resource_nutanix_foundation_central_api_keys_test.go @@ -0,0 +1,34 @@ +package nutanix + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +func TestAccFCAPIKey_basic(t *testing.T) { + name := acctest.RandomWithPrefix("test-key") + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckNutanixAddressGroupDestroy, + Steps: []resource.TestStep{ + { + Config: testAccFCAPIKeyConfig(name), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("nutanix_foundation_central_api_keys.test", "alias", name), + ), + }, + }, + }) +} + +func testAccFCAPIKeyConfig(name string) string { + return fmt.Sprintf(` + resource "nutanix_foundation_central_api_keys" "test"{ + alias = "%s" + } +`, name) +} diff --git a/nutanix/resource_nutanix_foundation_central_image_nodes_test.go b/nutanix/resource_nutanix_foundation_central_image_nodes_test.go new file mode 100644 index 000000000..f8b59cc3e --- /dev/null +++ b/nutanix/resource_nutanix_foundation_central_image_nodes_test.go @@ -0,0 +1,101 @@ +package nutanix + +import ( + "fmt" + "os" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +func TestAccFCImageNodesResource(t *testing.T) { + name := "batch2" + resourcePath := "nutanix_foundation_central_image_cluster." + name + clusterName := "test_cluster" + // get file file path to config having nodes info + path, _ := os.Getwd() + filepath := path + "/../test_foundation_config.json" + + // using block 1 in the test_foundation_config.json for this testcase + blockNum := 1 + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testFCImageNodesResource(filepath, blockNum, name, clusterName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(resourcePath, "cluster_name", clusterName), + ), + }, + }, + }) +} + +func testFCImageNodesResource(filepath string, blockNum int, name, clusterName string) string { + return fmt.Sprintf(` + locals{ + config = (jsondecode(file("%[1]s"))).blocks[%[2]v] + } + + resource "nutanix_foundation_central_image_cluster" "%[3]s" { + aos_package_url = local.config.aos_package_url + + node_list{ + cvm_gateway = local.config.cvm_gateway + cvm_netmask = local.config.cvm_netmask + cvm_ip = local.config.nodes[0].cvm_ip + hypervisor_gateway = local.config.hypervisor_gateway + hypervisor_netmask = local.config.hypervisor_netmask + hypervisor_ip = local.config.nodes[0].hypervisor_ip + hypervisor_hostname = local.config.nodes[0].hypervisor_hostname + imaged_node_uuid = local.config.nodes[0].imaged_node_uuid + use_existing_network_settings = local.config.use_existing_network_settings + ipmi_ip = local.config.nodes[0].ipmi_ip + ipmi_netmask = local.config.nodes[0].ipmi_netmask + ipmi_gateway = local.config.nodes[0].ipmi_gateway + image_now = local.config.image_now + hypervisor_type = local.config.nodes[0].hypervisor_type + } + node_list{ + cvm_gateway = local.config.cvm_gateway + cvm_netmask = local.config.cvm_netmask + cvm_ip = local.config.nodes[1].cvm_ip + hypervisor_gateway = local.config.hypervisor_gateway + hypervisor_netmask = local.config.hypervisor_netmask + hypervisor_ip = local.config.nodes[1].hypervisor_ip + hypervisor_hostname = local.config.nodes[1].hypervisor_hostname + imaged_node_uuid = local.config.nodes[1].imaged_node_uuid + use_existing_network_settings = local.config.use_existing_network_settings + ipmi_ip = local.config.nodes[1].ipmi_ip + ipmi_netmask = local.config.nodes[1].ipmi_netmask + ipmi_gateway = local.config.nodes[1].ipmi_gateway + image_now = local.config.image_now + hypervisor_type = local.config.nodes[1].hypervisor_type + } + node_list{ + cvm_gateway = local.config.cvm_gateway + cvm_netmask = local.config.cvm_netmask + cvm_ip = local.config.nodes[2].cvm_ip + hypervisor_gateway = local.config.hypervisor_gateway + hypervisor_netmask = local.config.hypervisor_netmask + hypervisor_ip = local.config.nodes[2].hypervisor_ip + hypervisor_hostname = local.config.nodes[2].hypervisor_hostname + imaged_node_uuid = local.config.nodes[2].imaged_node_uuid + use_existing_network_settings = local.config.use_existing_network_settings + ipmi_ip = local.config.nodes[2].ipmi_ip + ipmi_netmask = local.config.nodes[2].ipmi_netmask + ipmi_gateway = local.config.nodes[2].ipmi_gateway + image_now = local.config.image_now + hypervisor_type = local.config.nodes[2].hypervisor_type + } + common_network_settings{ + cvm_dns_servers = [local.config.common_network_settings.cvm_dns_servers[0]] + hypervisor_dns_servers = [local.config.common_network_settings.hypervisor_dns_servers[0]] + cvm_ntp_servers = [local.config.common_network_settings.cvm_ntp_servers[0]] + hypervisor_ntp_servers = [local.config.common_network_settings.hypervisor_ntp_servers[0]] + } + redundancy_factor = 2 + cluster_name = "%[4]s" + }`, filepath, blockNum, name, clusterName) +} diff --git a/test_foundation_config.json b/test_foundation_config.json index e918078a1..850923cb5 100644 --- a/test_foundation_config.json +++ b/test_foundation_config.json @@ -74,6 +74,63 @@ } ], "block_id": "" + }, + { + "common_network_settings":{ + "cvm_dns_servers":[ + "" + ], + "hypervisor_dns_servers":[ + "" + ], + "cvm_ntp_servers":[ + "" + ], + "hypervisor_ntp_servers":[ + "" + ] + }, + "cvm_gateway":"", + "cvm_netmask":"", + "hypervisor_gateway":"", + "hypervisor_netmask":"", + "use_existing_network_settings":false, + "image_now":true, + + "nodes": [ + { + "cvm_ip":"", + "hypervisor_ip":"", + "hypervisor_hostname":"", + "imaged_node_uuid":"", + "ipmi_gateway":"", + "ipmi_ip":"", + "ipmi_netmask":"", + "hypervisor_type":"" + }, + { + "cvm_ip":"", + "hypervisor_ip":"", + "hypervisor_hostname":"", + "imaged_node_uuid":"", + "ipmi_gateway":"", + "ipmi_ip":"", + "ipmi_netmask":"", + "hypervisor_type":"" + }, + { + "cvm_ip":"", + "hypervisor_ip":"", + "hypervisor_hostname":"", + "imaged_node_uuid":"", + "ipmi_gateway":"", + "ipmi_ip":"", + "ipmi_netmask":"", + "hypervisor_type":"" + } + + ], + "aos_package_url":"" } ] -} \ No newline at end of file +}