Skip to content

Commit

Permalink
kubernetes clusters pagination support
Browse files Browse the repository at this point in the history
  • Loading branch information
jschoombee committed May 11, 2023
1 parent 9eaea47 commit 0b4170c
Show file tree
Hide file tree
Showing 4 changed files with 163 additions and 33 deletions.
6 changes: 4 additions & 2 deletions docs/data-sources/kubernetes_clusters.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ data "wiz_kubernetes_clusters" "myclusters" {
- OpenShift
- Kubernetes
- `external_ids` (List of String) The ID(s) to search by. i.e `Azure Subscription ID` or `AWS account number`.
- `first` (Number) How many matches to return.
- `first` (Number) How many matches to return, maximum is `500` per page.
- Defaults to `50`.
- `kind` (List of String) Query Kubernetes Cluster of specific kind(s) or cloud provider(s).
- Allowed values:
Expand All @@ -51,7 +51,9 @@ data "wiz_kubernetes_clusters" "myclusters" {
- OKE
- OPEN_SHIFT
- SELF_HOSTED
- `search` (String) Free text search.
- `max_pages` (Number) How many pages to return. 0 means all pages.
- Defaults to `0`.
- `search` (String) Free text search. Specify empty string to return all kubernetes clusters

### Read-Only

Expand Down
84 changes: 84 additions & 0 deletions internal/acceptance/data_source_kubernetes_clusters_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package acceptance

import (
"fmt"
"regexp"
"testing"

"github.com/hashicorp/terraform-plugin-testing/helper/resource"
)

// TestAccDatasourceWizKubernetesClusters_basic tests the basic functionality of the datasource
// wiz_kubernetes_clusters. The assumption is that at least two clusters exist in the Wiz tenant in order
// to validate pagination functionality
func TestAccDatasourceWizKubernetesClusters_basic(t *testing.T) {
resource.UnitTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProviderFactories: providerFactories,
Steps: []resource.TestStep{
{
Config: testAccDatasourceWizKubernetesClustersBasic(1),
Check: resource.ComposeTestCheckFunc(
resource.TestMatchResourceAttr(
// check first kubernetes cluster has an id that matches the UUID regex
"data.wiz_kubernetes_clusters.foo",
"kubernetes_clusters.0.id",
regexp.MustCompile(UUIDPattern),
),
resource.TestMatchResourceAttr(
// check first kubernetes cluster has a name that is set to a non-empty string
"data.wiz_kubernetes_clusters.foo",
"kubernetes_clusters.0.name",
regexp.MustCompile(`\w`),
),
resource.TestMatchResourceAttr(
// check cloud_account_block has id that matches the UUID regex
"data.wiz_kubernetes_clusters.foo",
"kubernetes_clusters.0.cloud_account.0.id",
regexp.MustCompile(UUIDPattern),
),
resource.TestMatchResourceAttr(
// check cloud_account_block has external_id set to a non-empty string, different cloud providers have different formats
"data.wiz_kubernetes_clusters.foo",
"kubernetes_clusters.0.cloud_account.0.external_id",
regexp.MustCompile(`\w`),
),
resource.TestMatchResourceAttr(
// check cloud_account_block has name set to a non-empty string
"data.wiz_kubernetes_clusters.foo",
"kubernetes_clusters.0.cloud_account.0.name",
regexp.MustCompile(`\w`),
),
resource.TestMatchResourceAttr(
// check cloud_account_block has cloud_provider set to a non-empty string
"data.wiz_kubernetes_clusters.foo",
"kubernetes_clusters.0.cloud_account.0.cloud_provider",
regexp.MustCompile(`\w`),
),
),
},
{
Config: testAccDatasourceWizKubernetesClustersBasic(2),
Check: resource.ComposeTestCheckFunc(
resource.TestMatchResourceAttr(
// check that the second kubernetes cluster has an id that matches the UUID regex
"data.wiz_kubernetes_clusters.foo",
"kubernetes_clusters.1.id",
regexp.MustCompile(`\w`),
),
),
},
},
})
}

func testAccDatasourceWizKubernetesClustersBasic(maxPages int) string {
return fmt.Sprintf(`
data "wiz_kubernetes_clusters" "foo" {
first = 1
max_pages = %d
search = ""
}
`, maxPages)
}
54 changes: 35 additions & 19 deletions internal/provider/data_source_kubernetes_clusters.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,18 @@ func dataSourceWizKubernetesClusters() *schema.Resource {
Type: schema.TypeInt,
Optional: true,
Default: 50,
Description: "How many matches to return.",
Description: "How many matches to return, maximum is `500` per page.",
},
"max_pages": {
Type: schema.TypeInt,
Optional: true,
Default: 0,
Description: "How many pages to return. 0 means all pages.",
},
"search": {
Type: schema.TypeString,
Optional: true,
Description: "Free text search.",
Description: "Free text search. Specify empty string to return all kubernetes clusters",
},
"external_ids": {
Type: schema.TypeList,
Expand Down Expand Up @@ -164,6 +170,10 @@ func dataSourceWizKubernetesClustersRead(ctx context.Context, d *schema.Resource
if b {
identifier.WriteString(utils.PrettyPrint(a))
}
maxPages, b := d.GetOk("max_pages")
if b {
identifier.WriteString(utils.PrettyPrint(maxPages))
}
h := sha1.New()
h.Write([]byte(identifier.String()))
hashID := hex.EncodeToString(h.Sum(nil))
Expand Down Expand Up @@ -240,14 +250,15 @@ func dataSourceWizKubernetesClustersRead(ctx context.Context, d *schema.Resource

// process the request
data := &ReadKubernetesClusters{}
requestDiags := client.ProcessRequest(ctx, m, vars, data, query, "kubernetesClusters", "read")
requestDiags, allData := client.ProcessPagedRequest(ctx, m, vars, data, query, "kubernetesClusters", "read", maxPages.(int))
tflog.Debug(ctx, fmt.Sprintf("allData: %s", utils.PrettyPrint(allData)))

diags = append(diags, requestDiags...)
if len(diags) > 0 {
return diags
}

clusters := flattenClusters(ctx, &data.KubernetesClusters.Nodes)
clusters := flattenClusters(ctx, allData)

if err := d.Set("kubernetes_clusters", clusters); err != nil {
return append(diags, diag.FromErr(err)...)
Expand All @@ -257,28 +268,33 @@ func dataSourceWizKubernetesClustersRead(ctx context.Context, d *schema.Resource

}

func flattenClusters(ctx context.Context, clusters *[]*wiz.KubernetesCluster) []interface{} {
func flattenClusters(ctx context.Context, clusters []interface{}) []interface{} {
tflog.Info(ctx, "flattenClusters called...")
tflog.Debug(ctx, fmt.Sprintf("Clusters: %s", utils.PrettyPrint(clusters)))

// walk the slice and construct the list
var output = make([]interface{}, 0, 0)
for _, b := range *clusters {
clusterMap := make(map[string]interface{})
clusterMap["id"] = b.ID
clusterMap["name"] = b.Name
var output = make([]interface{}, 0)
for _, b := range clusters {
readClusters := b.(*ReadKubernetesClusters)
for _, cluster := range readClusters.KubernetesClusters.Nodes {
tflog.Debug(ctx, fmt.Sprintf("cluster: %s", utils.PrettyPrint(cluster)))
rootMap := make(map[string]interface{})
rootMap["id"] = cluster.ID
rootMap["name"] = cluster.Name

clusterMap := make(map[string]interface{})
clusterMap["cloud_provider"] = cluster.CloudAccount.CloudProvider
clusterMap["external_id"] = cluster.CloudAccount.ExternalID
clusterMap["id"] = cluster.CloudAccount.ID
clusterMap["name"] = cluster.CloudAccount.Name

accMap := make(map[string]interface{})
accMap["cloud_provider"] = b.CloudAccount.CloudProvider
accMap["external_id"] = b.CloudAccount.ExternalID
accMap["id"] = b.CloudAccount.ID
accMap["name"] = b.CloudAccount.Name
cloudAccountMap := make([]interface{}, 0)
cloudAccountMap = append(cloudAccountMap, clusterMap)
rootMap["cloud_account"] = cloudAccountMap

cloudAccountMap := make([]interface{}, 0, 0)
cloudAccountMap = append(cloudAccountMap, accMap)
clusterMap["cloud_account"] = cloudAccountMap
output = append(output, rootMap)

output = append(output, clusterMap)
}
}

tflog.Debug(ctx, fmt.Sprintf("flattenClusters output: %s", utils.PrettyPrint(output)))
Expand Down
52 changes: 40 additions & 12 deletions internal/provider/data_source_kubernetes_clusters_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,25 +19,53 @@ func TestFlattenKubernetesClusters(t *testing.T) {
"cloud_provider": "AWS",
"external_id": "151668690081",
"id": "31e5304c-baca-54fa-bff3-aaf493eaeae0",
"name": "MYK8S_TENANT_STAGE",
"name": "AWS",
},
},
},
}

var clusterLinks = &[]*wiz.KubernetesCluster{
{
ID: "8f137cbc-0810-55ff-acd6-f7574eb0d071",
Name: "24x7-dev",
CloudAccount: *&wiz.CloudAccount{
ID: "31e5304c-baca-54fa-bff3-aaf493eaeae0",
ExternalID: "151668690081",
CloudProvider: "AWS",
Name: "MYK8S_TENANT_STAGE",
map[string]interface{}{
"id": "8f137cbc-0810-55ff-acd6-f7574eb0d072",
"name": "24x7-prod",
"cloud_account": []interface{}{
map[string]interface{}{
"cloud_provider": "AZURE",
"external_id": "31e5304c-baca-54fa-bff3-aaf493eaeae2",
"id": "31e5304c-baca-54fa-bff3-aaf493eaeae0",
"name": "AZURE",
},
},
},
}

clusters := &ReadKubernetesClusters{
KubernetesClusters: wiz.KubernetesClusterConnection{
Nodes: []*wiz.KubernetesCluster{
{
ID: "8f137cbc-0810-55ff-acd6-f7574eb0d071",
Name: "24x7-dev",
CloudAccount: wiz.CloudAccount{
ID: "31e5304c-baca-54fa-bff3-aaf493eaeae0",
ExternalID: "151668690081",
CloudProvider: "AWS",
Name: "AWS",
},
},
{
ID: "8f137cbc-0810-55ff-acd6-f7574eb0d072",
Name: "24x7-prod",
CloudAccount: wiz.CloudAccount{
ID: "31e5304c-baca-54fa-bff3-aaf493eaeae0",
ExternalID: "31e5304c-baca-54fa-bff3-aaf493eaeae2",
CloudProvider: "AZURE",
Name: "AZURE",
},
},
},
}}

clusterLinks := make([]interface{}, 0)
clusterLinks = append(clusterLinks, clusters)

flattened := flattenClusters(ctx, clusterLinks)

if !reflect.DeepEqual(flattened, expected) {
Expand Down

0 comments on commit 0b4170c

Please sign in to comment.