diff --git a/docs/index.md b/docs/index.md index 398d9720..ce5b4bbc 100644 --- a/docs/index.md +++ b/docs/index.md @@ -38,8 +38,7 @@ terraform { provider "spectrocloud" { host = var.sc_host # Spectro Cloud endpoint (defaults to api.spectrocloud.com) - username = var.sc_username # Username of the user (or specify with SPECTROCLOUD_USERNAME env var) - password = var.sc_password # Password (or specify with SPECTROCLOUD_PASSWORD env var) + api_key = var.sc_api_key # API key (or specify with SPECTROCLOUD_APIKEY env var) project_name = var.sc_project_name # Project name (e.g: Default) } ``` @@ -57,7 +56,7 @@ sc_project_name = "{enter Spectro Cloud project Name}" #e.g: Default ``` -> -Be sure to populate the `username`, `password`, and other terraform vars. +Be sure to populate the `sc_host`, `sc_api_key`, and other terraform vars. Copy one of the resource configuration files (e.g: spectrocloud_cluster_profile) from the _Resources_ documentation. Be sure to specify all required parameters. @@ -75,28 +74,14 @@ For an end-to-end example of provisioning Spectro Cloud resources, visit: Credentials and other configurations can be provided through environment variables. The following environment variables are availabe. -- `SPECTROCLOUD_HOST` -- `SPECTROCLOUD_USERNAME` -- `SPECTROCLOUD_PASSWORD` +- `SPECTROCLOUD_HOST` - `SPECTROCLOUD_APIKEY` - `SPECTROCLOUD_TRACE` - `SPECTROCLOUD_RETRY_ATTEMPTS` ## Authentication -You can use the environment variables to authenticate with Spectro Cloud with your username and password. - --> **Note:** The API key takes precendence over the username and password authentication flow. - -```shell -export SPECTROCLOUD_USERNAME=myUserName -export SPECTROCLOUD_PASSWORD=myPassword -``` -```hcl -provider "spectrocloud" {} -``` - -Alternatively, you may use an API key to authenticate with Spectro Cloud. Visit the User Management API Key [documentation](https://docs.spectrocloud.com/user-management/user-authentication/#usingapikey) to learn more about Spectro Cloud API keys. +You can use an API key to authenticate with Spectro Cloud. Visit the User Management API Key [documentation](https://docs.spectrocloud.com/user-management/user-authentication/#usingapikey) to learn more about Spectro Cloud API keys. ```shell export SPECTROCLOUD_APIKEY=5b7aad......... ``` @@ -117,8 +102,8 @@ provider GitHub [discussion board](https://github.com/spectrocloud/terraform-pro - `api_key` (String, Sensitive) The Spectro Cloud API key. Can also be set with the `SPECTROCLOUD_API_KEY` environment variable. - `host` (String) The Spectro Cloud API host url. Can also be set with the `SPECTROCLOUD_HOST` environment variable. Defaults to https://api.spectrocloud.com - `ignore_insecure_tls_error` (Boolean) Ignore insecure TLS errors for Spectro Cloud API endpoints. Defaults to false. -- `password` (String, Sensitive) The Spectro Cloud user password. Can also be set with the `SPECTROCLOUD_PASSWORD` environment variable. +- `password` (String, Sensitive, Deprecated) The Spectro Cloud user password. Can also be set with the `SPECTROCLOUD_PASSWORD` environment variable. - `project_name` (String) The Spectro Cloud project name. - `retry_attempts` (Number) Number of retry attempts. Can also be set with the `SPECTROCLOUD_RETRY_ATTEMPTS` environment variable. Defaults to 10. - `trace` (Boolean) Enable HTTP request tracing. Can also be set with the `SPECTROCLOUD_TRACE` environment variable. To enable Terraform debug logging, set `TF_LOG=DEBUG`. Visit the Terraform documentation to learn more about Terraform [debugging](https://developer.hashicorp.com/terraform/plugin/log/managing). -- `username` (String) The Spectro Cloud username. Can also be set with the `SPECTROCLOUD_USERNAME` environment variable. +- `username` (String, Deprecated) The Spectro Cloud username. Can also be set with the `SPECTROCLOUD_USERNAME` environment variable. diff --git a/docs/resources/cluster_aws.md b/docs/resources/cluster_aws.md index 0abcf44d..f60e4855 100644 --- a/docs/resources/cluster_aws.md +++ b/docs/resources/cluster_aws.md @@ -185,7 +185,10 @@ Optional: - `control_plane` (Boolean) - `control_plane_as_worker` (Boolean) - `disk_size_gb` (Number) +- `max` (Number) Maximum number of nodes in the machine pool. This is used for autoscaling the machine pool. - `max_price` (String) +- `min` (Number) Minimum number of nodes in the machine pool. This is used for autoscaling the machine pool. +- `node_repave_interval` (Number) Minimum number of seconds node should be Ready, before the next node is selected for repave. Default value is `0`, Applicable only for worker pools. - `taints` (Block List) (see [below for nested schema](#nestedblock--machine_pool--taints)) - `update_strategy` (String) diff --git a/docs/resources/cluster_azure.md b/docs/resources/cluster_azure.md index c2920b11..eafee6c4 100644 --- a/docs/resources/cluster_azure.md +++ b/docs/resources/cluster_azure.md @@ -144,6 +144,7 @@ Optional: - `control_plane` (Boolean) - `control_plane_as_worker` (Boolean) - `disk` (Block List, Max: 1) (see [below for nested schema](#nestedblock--machine_pool--disk)) +- `node_repave_interval` (Number) Minimum number of seconds node should be Ready, before the next node is selected for repave. Default value is `0`, Applicable only for worker pools. - `os_type` (String) - `taints` (Block List) (see [below for nested schema](#nestedblock--machine_pool--taints)) - `update_strategy` (String) diff --git a/docs/resources/cluster_gcp.md b/docs/resources/cluster_gcp.md index 9f27beb1..befe0f48 100644 --- a/docs/resources/cluster_gcp.md +++ b/docs/resources/cluster_gcp.md @@ -142,6 +142,7 @@ Optional: - `control_plane` (Boolean) - `control_plane_as_worker` (Boolean) - `disk_size_gb` (Number) +- `node_repave_interval` (Number) Minimum number of seconds node should be Ready, before the next node is selected for repave. Default value is `0`, Applicable only for worker pools. - `taints` (Block List) (see [below for nested schema](#nestedblock--machine_pool--taints)) - `update_strategy` (String) diff --git a/docs/resources/cluster_maas.md b/docs/resources/cluster_maas.md index 93a338ea..9266c75c 100644 --- a/docs/resources/cluster_maas.md +++ b/docs/resources/cluster_maas.md @@ -137,7 +137,7 @@ Required: Required: - `azs` (Set of String) -- `count` (Number) +- `count` (Number) Number of nodes in the machine pool. - `instance_type` (Block List, Min: 1, Max: 1) (see [below for nested schema](#nestedblock--machine_pool--instance_type)) - `name` (String) - `placement` (Block List, Min: 1) (see [below for nested schema](#nestedblock--machine_pool--placement)) @@ -147,6 +147,9 @@ Optional: - `additional_labels` (Map of String) - `control_plane` (Boolean) - `control_plane_as_worker` (Boolean) +- `max` (Number) Maximum number of nodes in the machine pool. This is used for autoscaling the machine pool. +- `min` (Number) Minimum number of nodes in the machine pool. This is used for autoscaling the machine pool. +- `node_repave_interval` (Number) Minimum number of seconds node should be Ready, before the next node is selected for repave. Default value is `0`, Applicable only for worker pools. - `taints` (Block List) (see [below for nested schema](#nestedblock--machine_pool--taints)) - `update_strategy` (String) diff --git a/docs/resources/cluster_openstack.md b/docs/resources/cluster_openstack.md index 9646e2df..194fbf25 100644 --- a/docs/resources/cluster_openstack.md +++ b/docs/resources/cluster_openstack.md @@ -147,6 +147,7 @@ Optional: - `azs` (Set of String) - `control_plane` (Boolean) - `control_plane_as_worker` (Boolean) +- `node_repave_interval` (Number) Minimum number of seconds node should be Ready, before the next node is selected for repave. Default value is `0`, Applicable only for worker pools. - `subnet_id` (String) - `taints` (Block List) (see [below for nested schema](#nestedblock--machine_pool--taints)) - `update_strategy` (String) diff --git a/docs/resources/cluster_vsphere.md b/docs/resources/cluster_vsphere.md index 52e959f3..45aa6f9b 100644 --- a/docs/resources/cluster_vsphere.md +++ b/docs/resources/cluster_vsphere.md @@ -10,7 +10,73 @@ description: |- - +## Example Usage + +```terraform +data "spectrocloud_cluster_profile" "vmware_profile" { + name = "vsphere-picard-2" + version = "1.0.0" + context = "tenant" +} +data "spectrocloud_cloudaccount_vsphere" "vmware_account" { + name = var.shared_vmware_cloud_account_name +} + + +resource "spectrocloud_cluster_vsphere" "cluster" { + name = "vsphere-picard-3" + cloud_account_id = data.spectrocloud_cloudaccount_vsphere.vmware_account.id + cluster_profile { + id = data.spectrocloud_cluster_profile.vmware_profile.id + } + cloud_config { + ssh_key = var.cluster_ssh_public_key + + datacenter = var.vsphere_datacenter + folder = var.vsphere_folder + // For Dynamic DNS (network_type & network_search_domain value should set for DDNS) + network_type = "DDNS" + network_search_domain = var.cluster_network_search + // For Static (By Default static_ip is false, for static provisioning, it is set to be true. Not required to specify network_type & network_search_domain) + # static_ip = true + } + + machine_pool { + control_plane = true + control_plane_as_worker = true + name = "master-pool" + count = 1 + placement { + cluster = var.vsphere_cluster + resource_pool = var.vsphere_resource_pool + datastore = var.vsphere_datastore + network = var.vsphere_network + } + instance_type { + disk_size_gb = 40 + memory_mb = 4096 + cpu = 2 + } + } + + machine_pool { + name = "worker-basic" + count = 1 + node_repave_interval = 30 + placement { + cluster = var.vsphere_cluster + resource_pool = var.vsphere_resource_pool + datastore = var.vsphere_datastore + network = var.vsphere_network + } + instance_type { + disk_size_gb = 40 + memory_mb = 8192 + cpu = 4 + } + } +} +``` ## Schema @@ -79,6 +145,7 @@ Optional: - `additional_labels` (Map of String) - `control_plane` (Boolean) - `control_plane_as_worker` (Boolean) +- `node_repave_interval` (Number) Minimum number of seconds node should be Ready, before the next node is selected for repave. Default value is `0`, Applicable only for worker pools. - `taints` (Block List) (see [below for nested schema](#nestedblock--machine_pool--taints)) - `update_strategy` (String) diff --git a/examples/provider/provider.tf b/examples/provider/provider.tf index b42b036c..34f00f68 100644 --- a/examples/provider/provider.tf +++ b/examples/provider/provider.tf @@ -9,7 +9,6 @@ terraform { provider "spectrocloud" { host = var.sc_host # Spectro Cloud endpoint (defaults to api.spectrocloud.com) - username = var.sc_username # Username of the user (or specify with SPECTROCLOUD_USERNAME env var) - password = var.sc_password # Password (or specify with SPECTROCLOUD_PASSWORD env var) + api_key = var.sc_api_key # API key (or specify with SPECTROCLOUD_APIKEY env var) project_name = var.sc_project_name # Project name (e.g: Default) } diff --git a/examples/resources/spectrocloud_cluster_vsphere/resource.tf b/examples/resources/spectrocloud_cluster_vsphere/resource.tf new file mode 100644 index 00000000..e632c875 --- /dev/null +++ b/examples/resources/spectrocloud_cluster_vsphere/resource.tf @@ -0,0 +1,63 @@ +data "spectrocloud_cluster_profile" "vmware_profile" { + name = "vsphere-picard-2" + version = "1.0.0" + context = "tenant" +} +data "spectrocloud_cloudaccount_vsphere" "vmware_account" { + name = var.shared_vmware_cloud_account_name +} + + +resource "spectrocloud_cluster_vsphere" "cluster" { + name = "vsphere-picard-3" + cloud_account_id = data.spectrocloud_cloudaccount_vsphere.vmware_account.id + cluster_profile { + id = data.spectrocloud_cluster_profile.vmware_profile.id + } + cloud_config { + ssh_key = var.cluster_ssh_public_key + + datacenter = var.vsphere_datacenter + folder = var.vsphere_folder + // For Dynamic DNS (network_type & network_search_domain value should set for DDNS) + network_type = "DDNS" + network_search_domain = var.cluster_network_search + // For Static (By Default static_ip is false, for static provisioning, it is set to be true. Not required to specify network_type & network_search_domain) + # static_ip = true + } + + machine_pool { + control_plane = true + control_plane_as_worker = true + name = "master-pool" + count = 1 + placement { + cluster = var.vsphere_cluster + resource_pool = var.vsphere_resource_pool + datastore = var.vsphere_datastore + network = var.vsphere_network + } + instance_type { + disk_size_gb = 40 + memory_mb = 4096 + cpu = 2 + } + } + + machine_pool { + name = "worker-basic" + count = 1 + node_repave_interval = 30 + placement { + cluster = var.vsphere_cluster + resource_pool = var.vsphere_resource_pool + datastore = var.vsphere_datastore + network = var.vsphere_network + } + instance_type { + disk_size_gb = 40 + memory_mb = 8192 + cpu = 4 + } + } +} \ No newline at end of file diff --git a/go.mod b/go.mod index ca52e25f..0ee443c2 100644 --- a/go.mod +++ b/go.mod @@ -5,12 +5,13 @@ go 1.18 require ( github.com/go-openapi/runtime v0.19.28 github.com/go-openapi/strfmt v0.20.1 + github.com/google/go-cmp v0.5.9 github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 github.com/hashicorp/terraform-plugin-docs v0.13.0 - github.com/hashicorp/terraform-plugin-sdk/v2 v2.24.1 + github.com/hashicorp/terraform-plugin-sdk/v2 v2.29.0 github.com/pkg/errors v0.9.1 github.com/robfig/cron v1.2.0 - github.com/spectrocloud/hapi v1.14.1-0.20230904110035-ed2b1df599dc + github.com/spectrocloud/hapi v1.14.1-0.20230915073348-759e2eb74641 github.com/stretchr/testify v1.7.2 ) @@ -18,13 +19,15 @@ require ( github.com/Masterminds/goutils v1.1.1 // indirect github.com/Masterminds/semver/v3 v3.1.1 // indirect github.com/Masterminds/sprig/v3 v3.2.2 // indirect + github.com/ProtonMail/go-crypto v0.0.0-20230717121422-5aa5874ade95 // indirect github.com/PuerkitoBio/purell v1.1.1 // indirect github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect github.com/agext/levenshtein v1.2.2 // indirect - github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect + github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect github.com/armon/go-radix v1.0.0 // indirect github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef // indirect github.com/bgentry/speakeasy v0.1.0 // indirect + github.com/cloudflare/circl v1.3.3 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/fatih/color v1.13.0 // indirect github.com/go-errors/errors v1.4.0 // indirect @@ -37,35 +40,34 @@ require ( github.com/go-openapi/swag v0.19.14 // indirect github.com/go-openapi/validate v0.20.2 // indirect github.com/go-stack/stack v1.8.0 // indirect - github.com/golang/protobuf v1.5.2 // indirect - github.com/google/go-cmp v0.5.9 // indirect + github.com/golang/protobuf v1.5.3 // indirect github.com/google/uuid v1.3.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-checkpoint v0.5.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect - github.com/hashicorp/go-hclog v1.2.1 // indirect + github.com/hashicorp/go-hclog v1.5.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect - github.com/hashicorp/go-plugin v1.4.6 // indirect + github.com/hashicorp/go-plugin v1.5.1 // indirect github.com/hashicorp/go-uuid v1.0.3 // indirect github.com/hashicorp/go-version v1.6.0 // indirect - github.com/hashicorp/hc-install v0.4.0 // indirect - github.com/hashicorp/hcl/v2 v2.15.0 // indirect + github.com/hashicorp/hc-install v0.6.0 // indirect + github.com/hashicorp/hcl/v2 v2.18.0 // indirect github.com/hashicorp/logutils v1.0.0 // indirect - github.com/hashicorp/terraform-exec v0.17.3 // indirect - github.com/hashicorp/terraform-json v0.14.0 // indirect - github.com/hashicorp/terraform-plugin-go v0.14.1 // indirect - github.com/hashicorp/terraform-plugin-log v0.7.0 // indirect - github.com/hashicorp/terraform-registry-address v0.0.0-20220623143253-7d51757b572c // indirect - github.com/hashicorp/terraform-svchost v0.0.0-20200729002733-f050f53b9734 // indirect + github.com/hashicorp/terraform-exec v0.19.0 // indirect + github.com/hashicorp/terraform-json v0.17.1 // indirect + github.com/hashicorp/terraform-plugin-go v0.19.0 // indirect + github.com/hashicorp/terraform-plugin-log v0.9.0 // indirect + github.com/hashicorp/terraform-registry-address v0.2.2 // indirect + github.com/hashicorp/terraform-svchost v0.1.1 // indirect github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d // indirect github.com/huandu/xstrings v1.3.2 // indirect - github.com/imdario/mergo v0.3.13 // indirect + github.com/imdario/mergo v0.3.15 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/konsorten/go-windows-terminal-sequences v1.0.3 // indirect github.com/mailru/easyjson v0.7.6 // indirect github.com/mattn/go-colorable v0.1.12 // indirect github.com/mattn/go-isatty v0.0.14 // indirect - github.com/mitchellh/cli v1.1.4 // indirect + github.com/mitchellh/cli v1.1.5 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/go-testing-interface v1.14.1 // indirect github.com/mitchellh/go-wordwrap v1.0.0 // indirect @@ -82,18 +84,19 @@ require ( github.com/spectrocloud/gomi v1.14.1-0.20230412095143-b0595c6c6f08 // indirect github.com/spf13/cast v1.5.0 // indirect github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect - github.com/vmihailenco/msgpack/v4 v4.3.12 // indirect - github.com/vmihailenco/tagparser v0.1.1 // indirect - github.com/zclconf/go-cty v1.12.1 // indirect + github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect + github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect + github.com/zclconf/go-cty v1.14.0 // indirect go.mongodb.org/mongo-driver v1.5.1 // indirect - golang.org/x/crypto v0.5.0 // indirect - golang.org/x/net v0.5.0 // indirect - golang.org/x/sys v0.4.0 // indirect - golang.org/x/text v0.6.0 // indirect - google.golang.org/appengine v1.6.6 // indirect - google.golang.org/genproto v0.0.0-20200711021454-869866162049 // indirect - google.golang.org/grpc v1.50.1 // indirect - google.golang.org/protobuf v1.28.1 // indirect + golang.org/x/crypto v0.13.0 // indirect + golang.org/x/mod v0.12.0 // indirect + golang.org/x/net v0.13.0 // indirect + golang.org/x/sys v0.12.0 // indirect + golang.org/x/text v0.13.0 // indirect + google.golang.org/appengine v1.6.7 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19 // indirect + google.golang.org/grpc v1.57.0 // indirect + google.golang.org/protobuf v1.31.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 4c22ea30..c3e130ca 100644 --- a/go.sum +++ b/go.sum @@ -1,40 +1,31 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc= github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= -github.com/Masterminds/sprig/v3 v3.2.0/go.mod h1:tWhwTbUTndesPNeF0C900vKoq283u6zp4APT9vaF3SI= +github.com/Masterminds/sprig/v3 v3.2.1/go.mod h1:UoaO7Yp8KlPnJIYWTFkMaqPUYKTfGFPhxNuwnnxkKlk= github.com/Masterminds/sprig/v3 v3.2.2 h1:17jRggJu518dr3QaafizSXOjKYp94wKfABxUmyxvxX8= github.com/Masterminds/sprig/v3 v3.2.2/go.mod h1:UoaO7Yp8KlPnJIYWTFkMaqPUYKTfGFPhxNuwnnxkKlk= -github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= -github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk= -github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= -github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 h1:YoJbenK9C67SkzkDfmQuVln04ygHj3vjZfd9FL+GmQQ= -github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= +github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= +github.com/ProtonMail/go-crypto v0.0.0-20230717121422-5aa5874ade95 h1:KLq8BE0KwCL+mmXnjLWEAOYO+2l2AE4YMmqG1ZpZHBs= +github.com/ProtonMail/go-crypto v0.0.0-20230717121422-5aa5874ade95/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/acomagu/bufpipe v1.0.3 h1:fxAGrHZTgQ9w5QqVItgzwj235/uYZYgbXitB+dLupOk= -github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4= +github.com/acomagu/bufpipe v1.0.4 h1:e3H4WUzM3npvo5uv95QuJM3cQspFNtFBzvJ2oNjKIDQ= github.com/agext/levenshtein v1.2.2 h1:0S/Yg6LYmFJ5stwQeRp6EeOcCbj7xiqQSdNelsXvaqE= github.com/agext/levenshtein v1.2.2/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= -github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= -github.com/apparentlymart/go-dump v0.0.0-20190214190832-042adf3cf4a0 h1:MzVXffFUye+ZcSR6opIgz9Co7WcDx6ZcY+RjfFHoA0I= -github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/Nj9VFpLOpjS5yuumk= github.com/apparentlymart/go-textseg/v12 v12.0.0/go.mod h1:S/4uRK2UtaQttw1GenVJEynmyUenKwP++x/+DdGV/Ec= -github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw= -github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo= +github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY= +github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg= @@ -44,36 +35,28 @@ github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:W github.com/aws/aws-sdk-go v1.34.28/go.mod h1:H7NKnBqNVzoTJpGfLrQkkD+ytBA93eiDYi/+8rV9s48= github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= +github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= +github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs= +github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg= -github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= -github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= github.com/go-errors/errors v1.4.0 h1:2OA7MFw38+e9na72T1xgkomPb6GzZzzxvJ5U630FoRM= github.com/go-errors/errors v1.4.0/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= -github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4= -github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E= -github.com/go-git/go-billy/v5 v5.2.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= -github.com/go-git/go-billy/v5 v5.3.1 h1:CPiOUAzKtMRvolEKw+bG1PLRpT7D3LIs3/3ey4Aiu34= -github.com/go-git/go-billy/v5 v5.3.1/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= -github.com/go-git/go-git-fixtures/v4 v4.2.1/go.mod h1:K8zd3kDUAykwTdDCr+I0per6Y6vMiRR/nnVTBtavnB0= -github.com/go-git/go-git/v5 v5.4.2 h1:BXyZu9t0VkbiHtqrsvdq39UDhGJTl1h55VW6CSC4aY4= -github.com/go-git/go-git/v5 v5.4.2/go.mod h1:gQ1kArt6d+n+BGd+/B/I74HwRTLhth2+zti4ihgckDc= +github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= +github.com/go-git/go-billy/v5 v5.4.1 h1:Uwp5tDRkPr+l/TnbHOQzp+tmJfLceOlbVucgpTz8ix4= +github.com/go-git/go-git/v5 v5.8.1 h1:Zo79E4p7TRk0xoRgMq0RShiTHGKcKI4+DI6BfJc/Q+A= github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI= github.com/go-openapi/analysis v0.17.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= github.com/go-openapi/analysis v0.18.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= @@ -193,30 +176,18 @@ github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWe github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ= github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0= github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -230,61 +201,55 @@ github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brv github.com/hashicorp/go-checkpoint v0.5.0 h1:MFYpPZCnQqQTE18jFwSII6eUQrD/oxMFp3mlgcqk5mU= github.com/hashicorp/go-checkpoint v0.5.0/go.mod h1:7nfLNL10NsxqO4iWuW6tWW0HjZuDrwkBuEQsVcpCOgg= github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 h1:1/D3zfFHttUKaCaGKZ/dR2roBXv0vKbSCnssIldfQdI= github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320/go.mod h1:EiZBMaudVLy8fmjf9Npq1dq9RalhveqZG5w/yz3mHWs= -github.com/hashicorp/go-hclog v1.2.1 h1:YQsLlGDJgwhXFpucSPyVbCBviQtjlHv3jLTlp8YmtEw= -github.com/hashicorp/go-hclog v1.2.1/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= +github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= -github.com/hashicorp/go-plugin v1.4.6 h1:MDV3UrKQBM3du3G7MApDGvOsMYy3JQJ4exhSoKBAeVA= -github.com/hashicorp/go-plugin v1.4.6/go.mod h1:viDMjcLJuDui6pXb8U4HVfb8AamCWhHGUjr2IrTF67s= +github.com/hashicorp/go-plugin v1.5.1 h1:oGm7cWBaYIp3lJpx1RUEfLWophprE2EV/KUeqBYo+6k= +github.com/hashicorp/go-plugin v1.5.1/go.mod h1:w1sAEES3g3PuV/RzUrgow20W2uErMly84hhD3um1WL4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/go-version v1.5.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/hc-install v0.4.0 h1:cZkRFr1WVa0Ty6x5fTvL1TuO1flul231rWkGH92oYYk= -github.com/hashicorp/hc-install v0.4.0/go.mod h1:5d155H8EC5ewegao9A4PUTMNPZaq+TbOzkJJZ4vrXeI= -github.com/hashicorp/hcl/v2 v2.15.0 h1:CPDXO6+uORPjKflkWCCwoWc9uRp+zSIPcCQ+BrxV7m8= -github.com/hashicorp/hcl/v2 v2.15.0/go.mod h1:JRmR89jycNkrrqnMmvPDMd56n1rQJ2Q6KocSLCMCXng= +github.com/hashicorp/hc-install v0.6.0 h1:fDHnU7JNFNSQebVKYhHZ0va1bC6SrPQ8fpebsvNr2w4= +github.com/hashicorp/hc-install v0.6.0/go.mod h1:10I912u3nntx9Umo1VAeYPUUuehk0aRQJYpMwbX5wQA= +github.com/hashicorp/hcl/v2 v2.18.0 h1:wYnG7Lt31t2zYkcquwgKo6MWXzRUDIeIVU5naZwHLl8= +github.com/hashicorp/hcl/v2 v2.18.0/go.mod h1:ThLC89FV4p9MPW804KVbe/cEXoQ8NZEh+JtMeeGErHE= github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= -github.com/hashicorp/terraform-exec v0.17.3 h1:MX14Kvnka/oWGmIkyuyvL6POx25ZmKrjlaclkx3eErU= -github.com/hashicorp/terraform-exec v0.17.3/go.mod h1:+NELG0EqQekJzhvikkeQsOAZpsw0cv/03rbeQJqscAI= -github.com/hashicorp/terraform-json v0.14.0 h1:sh9iZ1Y8IFJLx+xQiKHGud6/TSUCM0N8e17dKDpqV7s= -github.com/hashicorp/terraform-json v0.14.0/go.mod h1:5A9HIWPkk4e5aeeXIBbkcOvaZbIYnAIkEyqP2pNSckM= +github.com/hashicorp/terraform-exec v0.19.0 h1:FpqZ6n50Tk95mItTSS9BjeOVUb4eg81SpgVtZNNtFSM= +github.com/hashicorp/terraform-exec v0.19.0/go.mod h1:tbxUpe3JKruE9Cuf65mycSIT8KiNPZ0FkuTE3H4urQg= +github.com/hashicorp/terraform-json v0.17.1 h1:eMfvh/uWggKmY7Pmb3T85u86E2EQg6EQHgyRwf3RkyA= +github.com/hashicorp/terraform-json v0.17.1/go.mod h1:Huy6zt6euxaY9knPAFKjUITn8QxUFIe9VuSzb4zn/0o= github.com/hashicorp/terraform-plugin-docs v0.13.0 h1:6e+VIWsVGb6jYJewfzq2ok2smPzZrt1Wlm9koLeKazY= github.com/hashicorp/terraform-plugin-docs v0.13.0/go.mod h1:W0oCmHAjIlTHBbvtppWHe8fLfZ2BznQbuv8+UD8OucQ= -github.com/hashicorp/terraform-plugin-go v0.14.1 h1:cwZzPYla82XwAqpLhSzdVsOMU+6H29tczAwrB0z9Zek= -github.com/hashicorp/terraform-plugin-go v0.14.1/go.mod h1:Bc/K6K26BQ2FHqIELPbpKtt2CzzbQou+0UQF3/0NsCQ= -github.com/hashicorp/terraform-plugin-log v0.7.0 h1:SDxJUyT8TwN4l5b5/VkiTIaQgY6R+Y2BQ0sRZftGKQs= -github.com/hashicorp/terraform-plugin-log v0.7.0/go.mod h1:p4R1jWBXRTvL4odmEkFfDdhUjHf9zcs/BCoNHAc7IK4= -github.com/hashicorp/terraform-plugin-sdk/v2 v2.24.1 h1:zHcMbxY0+rFO9gY99elV/XC/UnQVg7FhRCbj1i5b7vM= -github.com/hashicorp/terraform-plugin-sdk/v2 v2.24.1/go.mod h1:+tNlb0wkfdsDJ7JEiERLz4HzM19HyiuIoGzTsM7rPpw= -github.com/hashicorp/terraform-registry-address v0.0.0-20220623143253-7d51757b572c h1:D8aRO6+mTqHfLsK/BC3j5OAoogv1WLRWzY1AaTo3rBg= -github.com/hashicorp/terraform-registry-address v0.0.0-20220623143253-7d51757b572c/go.mod h1:Wn3Na71knbXc1G8Lh+yu/dQWWJeFQEpDeJMtWMtlmNI= -github.com/hashicorp/terraform-svchost v0.0.0-20200729002733-f050f53b9734 h1:HKLsbzeOsfXmKNpr3GiT18XAblV0BjCbzL8KQAMZGa0= -github.com/hashicorp/terraform-svchost v0.0.0-20200729002733-f050f53b9734/go.mod h1:kNDNcF7sN4DocDLBkQYz73HGKwN1ANB1blq4lIYLYvg= +github.com/hashicorp/terraform-plugin-go v0.19.0 h1:BuZx/6Cp+lkmiG0cOBk6Zps0Cb2tmqQpDM3iAtnhDQU= +github.com/hashicorp/terraform-plugin-go v0.19.0/go.mod h1:EhRSkEPNoylLQntYsk5KrDHTZJh9HQoumZXbOGOXmec= +github.com/hashicorp/terraform-plugin-log v0.9.0 h1:i7hOA+vdAItN1/7UrfBqBwvYPQ9TFvymaRGZED3FCV0= +github.com/hashicorp/terraform-plugin-log v0.9.0/go.mod h1:rKL8egZQ/eXSyDqzLUuwUYLVdlYeamldAHSxjUFADow= +github.com/hashicorp/terraform-plugin-sdk/v2 v2.29.0 h1:wcOKYwPI9IorAJEBLzgclh3xVolO7ZorYd6U1vnok14= +github.com/hashicorp/terraform-plugin-sdk/v2 v2.29.0/go.mod h1:qH/34G25Ugdj5FcM95cSoXzUgIbgfhVLXCcEcYaMwq8= +github.com/hashicorp/terraform-registry-address v0.2.2 h1:lPQBg403El8PPicg/qONZJDC6YlgCVbWDtNmmZKtBno= +github.com/hashicorp/terraform-registry-address v0.2.2/go.mod h1:LtwNbCihUoUZ3RYriyS2wF/lGPB6gF9ICLRtuDk7hSo= +github.com/hashicorp/terraform-svchost v0.1.1 h1:EZZimZ1GxdqFRinZ1tpJwVxxt49xc/S52uzrw4x0jKQ= +github.com/hashicorp/terraform-svchost v0.1.1/go.mod h1:mNsjQfZyf/Jhz35v6/0LWcv26+X7JPS+buii2c9/ctc= github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d h1:kJCB4vdITiW1eC1vq2e6IsrXKrZit1bv/TDYFGMp4BQ= github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw= github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= -github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= +github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM= +github.com/imdario/mergo v0.3.15/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= -github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= -github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= -github.com/jhump/protoreflect v1.6.0 h1:h5jfMVslIg6l29nsMs0D8Wj17RDVdNYti0vDN/PZZoE= +github.com/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= @@ -292,8 +257,7 @@ github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8Hm github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4= github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA= -github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 h1:DowS9hvgyYSX4TO5NpyC606/Z4SxnNYbT+WX27or6Ck= -github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= +github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/klauspost/compress v1.9.5/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -301,14 +265,12 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxv github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= @@ -319,7 +281,6 @@ github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE= github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= -github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= @@ -328,13 +289,11 @@ github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNx github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mitchellh/cli v1.1.4 h1:qj8czE26AU4PbiaPXK5uVmMSM+V5BYsFBiM9HhGRLUA= -github.com/mitchellh/cli v1.1.4/go.mod h1:vTLESy5mRhKOs9KDp0/RATawxP1UqBmdrpVRMnpcvKQ= +github.com/mitchellh/cli v1.1.5 h1:OxRIeJXpAMztws/XHlN2vu6imG5Dpq+j61AzAX5fLng= +github.com/mitchellh/cli v1.1.5/go.mod h1:v8+iFts2sPIKUV1ltktPXMCC8fumSKFItNcD2cLtRR4= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= -github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4= @@ -351,7 +310,6 @@ github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zx github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/nsf/jsondiff v0.0.0-20200515183724-f29ed568f4ce h1:RPclfga2SEJmgMmz2k+Mg7cowZ8yv4Trqw9UsJby758= github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= @@ -361,6 +319,7 @@ github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYr github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.4.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUruD3k1mMwo= github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE= +github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -370,7 +329,6 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/posener/complete v1.2.3 h1:NP0eAhjcjImqslEwo/1hq7gpajME0fTLTezBKDqfXqo= github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/robfig/cron v1.2.0 h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ= github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k= github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= @@ -379,9 +337,7 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww= github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY= -github.com/sebdah/goldie v1.0.0/go.mod h1:jXP4hmWywNEwZzhMuv2ccnqTSFpuq8iyQhtQdkkZBH4= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= -github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= @@ -391,14 +347,11 @@ github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMB github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/skeema/knownhosts v1.2.0 h1:h9r9cf0+u7wSE+M183ZtMGgOJKiL96brpaz5ekfJCpM= github.com/spectrocloud/gomi v1.14.1-0.20230412095143-b0595c6c6f08 h1:AnOC0U+ExlKBeT5yF2Pg8PPfVOfxwOUBS/5deOl1Q4Y= github.com/spectrocloud/gomi v1.14.1-0.20230412095143-b0595c6c6f08/go.mod h1:UnhUDpFEvtYh6m384r3xzj8/+Z6/hMp2O8whEMYVHec= -github.com/spectrocloud/hapi v1.14.1-0.20230521133257-d73b9e4aea65 h1:mz46BzwOQg49P+CEGeMQgD7W6u3s0DmixMT4mudNQeA= -github.com/spectrocloud/hapi v1.14.1-0.20230521133257-d73b9e4aea65/go.mod h1:9lX5c6bShSkAg24223A7XBCyJj4/Kr9w0YFv6Mf5ZlE= -github.com/spectrocloud/hapi v1.14.1-0.20230814141242-394093e7fedb h1:Y/TDXfEZ6GJbYi4bKxFS0HFvmOL6Xs653BoxuZjuKEQ= -github.com/spectrocloud/hapi v1.14.1-0.20230814141242-394093e7fedb/go.mod h1:O/Bkbw92QPSGPNQPqKt7Qlkn+9BKK/a22KTUlk76KHI= -github.com/spectrocloud/hapi v1.14.1-0.20230904110035-ed2b1df599dc h1:3dC4+8RimiF6hlVPdA6fgMeEUIYEbE1Z08ad4f9153Q= -github.com/spectrocloud/hapi v1.14.1-0.20230904110035-ed2b1df599dc/go.mod h1:O/Bkbw92QPSGPNQPqKt7Qlkn+9BKK/a22KTUlk76KHI= +github.com/spectrocloud/hapi v1.14.1-0.20230915073348-759e2eb74641 h1:y25iXyYvWaxOxamKxh3YjPdsbMxMvVP8Z5YuPkV/wBE= +github.com/spectrocloud/hapi v1.14.1-0.20230915073348-759e2eb74641/go.mod h1:O/Bkbw92QPSGPNQPqKt7Qlkn+9BKK/a22KTUlk76KHI= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= @@ -421,24 +374,20 @@ github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaUXK79GlxNBwueZn0xI= github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= -github.com/vmihailenco/msgpack/v4 v4.3.12 h1:07s4sz9IReOgdikxLTKNbBdqDMLsjPKXwvCazn8G65U= -github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4= -github.com/vmihailenco/tagparser v0.1.1 h1:quXMXlA39OCbd2wAdTsGDlK9RkOk6Wuw+x37wVyIuWY= -github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= -github.com/xanzy/ssh-agent v0.3.0 h1:wUMzuKtKilRgBAD1sUb8gOwwRr2FGoBVumcjoOACClI= -github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0= +github.com/vmihailenco/msgpack/v5 v5.3.5 h1:5gO0H1iULLWGhs2H5tbAHIZTV8/cYafcFOr9znI5mJU= +github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc= +github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= +github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= +github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs= github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM= github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I= github.com/xdg/stringprep v0.0.0-20180714160509-73f8eece6fdc/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= -github.com/zclconf/go-cty v1.1.0/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLEih+O3s= -github.com/zclconf/go-cty v1.2.0/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8= -github.com/zclconf/go-cty v1.10.0/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk= -github.com/zclconf/go-cty v1.12.1 h1:PcupnljUm9EIvbgSHQnHhUr3fO6oFmkOrvs2BAFNXXY= -github.com/zclconf/go-cty v1.12.1/go.mod h1:s9IfD1LK5ccNMSWCVFCE2rJfHiZgi7JijgeWIMfhLvA= -github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b/go.mod h1:ZRKQfBXbGkpdV6QMzT3rU1kSTAnfu1dO8dPKjYprgj8= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/zclconf/go-cty v1.14.0 h1:/Xrd39K7DXbHzlisFP9c4pHao4yyf+/Ug9LEz+Y/yhc= +github.com/zclconf/go-cty v1.14.0/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE= go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= go.mongodb.org/mongo-driver v1.3.0/go.mod h1:MSWZXKOynuguX+JSvwP8i+58jYCXxbia8HS3gZBapIE= @@ -449,7 +398,6 @@ go.mongodb.org/mongo-driver v1.4.6/go.mod h1:WcMNYLx/IlOxLe6JRJiv2uXuCz6zBLndR4S go.mongodb.org/mongo-driver v1.5.1 h1:9nOVLGDfOaZ9R0tBumx/BcuqkbFpyTCU2r/Po7A2azI= go.mongodb.org/mongo-driver v1.5.1/go.mod h1:gRXCHX4Jo7J0IJ1oDQyUxF7jfy19UfxniMS4xxMmUqw= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= @@ -460,50 +408,44 @@ golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE= -golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= +golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= +golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck= +golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= +golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190320064053-1272bf9dcd53/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191009170851-d66e71096ffb/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k= -golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw= -golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/net v0.13.0 h1:Nvo8UFsZ8X3BhAC9699Z1j7XQ3rsZnUUm7jfBEk1ueY= +golang.org/x/net v0.13.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190321052220-f7bb7a8bee54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -511,83 +453,73 @@ golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210502180810-71e4cd670f79/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18= -golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k= -golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190329151228-23e29df326fe/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190416151739-9c9e1878f421/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190617190820-da514acc4774/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200711021454-869866162049 h1:YFTFpQhgvrLrmxtiIncJxFXeCyq84ixuKWVCaCAi9Oc= -google.golang.org/genproto v0.0.0-20200711021454-869866162049/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.50.1 h1:DS/BukOZWp8s6p4Dt/tOaJaTQyPyOoCcrjroHuCeLzY= -google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19 h1:0nDDozoAU19Qb2HwhXadU8OcsiO/09cnTqhUtq2MEOM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= +google.golang.org/grpc v1.57.0 h1:kfzNeI/klCGD2YPMUlaGNT3pxvYfga7smW3Vth8Zsiw= +google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= +google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= -gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -599,8 +531,5 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/spectrocloud/cluster_common.go b/spectrocloud/cluster_common.go index 00d09329..37748352 100644 --- a/spectrocloud/cluster_common.go +++ b/spectrocloud/cluster_common.go @@ -2,9 +2,11 @@ package spectrocloud import ( "errors" + "fmt" + "strings" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/spectrocloud/hapi/models" - "strings" ) var ( @@ -67,3 +69,20 @@ func toSSHKeys(cloudConfig map[string]interface{}) ([]string, error) { } return sshKeys, nil } + +func FlattenControlPlaneAndRepaveInterval(isControlPlane *bool, oi map[string]interface{}, nodeRepaveInterval int32) { + if isControlPlane != nil { + oi["control_plane"] = *isControlPlane + if !*isControlPlane { + oi["node_repave_interval"] = int32(nodeRepaveInterval) + } + } +} + +func ValidationNodeRepaveIntervalForControlPlane(nodeRepaveInterval int) error { + if nodeRepaveInterval != 0 { + errMsg := fmt.Sprintf("Validation error: The `node_repave_interval` attribute is not applicable for the control plane. Attempted value: %d.", nodeRepaveInterval) + return errors.New(errMsg) + } + return nil +} diff --git a/spectrocloud/cluster_common_hash.go b/spectrocloud/cluster_common_hash.go index b04a092b..050ed030 100644 --- a/spectrocloud/cluster_common_hash.go +++ b/spectrocloud/cluster_common_hash.go @@ -5,102 +5,122 @@ import ( "fmt" "hash/fnv" "sort" + "strings" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) -func resourceMachinePoolAzureHash(v interface{}) int { +func CommonHash(nodePool map[string]interface{}) *bytes.Buffer { var buf bytes.Buffer - m := v.(map[string]interface{}) - - buf.WriteString(HashStringMap(m["additional_labels"])) - buf.WriteString(HashStringMapList(m["taints"])) - buf.WriteString(fmt.Sprintf("%t-", m["control_plane"].(bool))) - buf.WriteString(fmt.Sprintf("%t-", m["control_plane_as_worker"].(bool))) - buf.WriteString(fmt.Sprintf("%s-", m["name"].(string))) - buf.WriteString(fmt.Sprintf("%d-", m["count"].(int))) - buf.WriteString(fmt.Sprintf("%s-", m["update_strategy"].(string))) + if _, ok := nodePool["additional_labels"]; ok { + buf.WriteString(HashStringMap(nodePool["additional_labels"])) + } + if _, ok := nodePool["taints"]; ok { + buf.WriteString(HashStringMapList(nodePool["taints"])) + } + if val, ok := nodePool["control_plane"]; ok { + buf.WriteString(fmt.Sprintf("%t-", val.(bool))) + } + if val, ok := nodePool["control_plane_as_worker"]; ok { + buf.WriteString(fmt.Sprintf("%t-", val.(bool))) + } + if val, ok := nodePool["name"]; ok { + buf.WriteString(fmt.Sprintf("%s-", val.(string))) + } + if val, ok := nodePool["count"]; ok { + buf.WriteString(fmt.Sprintf("%d-", val.(int))) + } + if val, ok := nodePool["update_strategy"]; ok { + buf.WriteString(fmt.Sprintf("%s-", val.(string))) + } + if val, ok := nodePool["node_repave_interval"]; ok { + buf.WriteString(fmt.Sprintf("%d-", val.(int))) + } + /*if val, ok := nodePool["instance_type"]; ok { + buf.WriteString(fmt.Sprintf("%s-", val.(string))) + } + if val, ok := nodePool["azs"]; ok { + buf.WriteString(fmt.Sprintf("%s-", val.(string))) + }*/ + if val, ok := nodePool["min"]; ok { + buf.WriteString(fmt.Sprintf("%d-", val.(int))) + } + if val, ok := nodePool["max"]; ok { + buf.WriteString(fmt.Sprintf("%d-", val.(int))) + } - buf.WriteString(fmt.Sprintf("%s-", m["instance_type"].(string))) - buf.WriteString(fmt.Sprintf("%t-", m["is_system_node_pool"].(bool))) + return &buf +} - buf.WriteString(fmt.Sprintf("%s-", m["azs"].(*schema.Set).GoString())) +func resourceMachinePoolAzureHash(v interface{}) int { + m := v.(map[string]interface{}) + buf := CommonHash(m) - if m["os_type"] != "" { - buf.WriteString(fmt.Sprintf("%s-", m["os_type"].(string))) + if val, ok := m["instance_type"]; ok { + buf.WriteString(fmt.Sprintf("%s-", val.(string))) + } + if val, ok := m["is_system_node_pool"]; ok { + buf.WriteString(fmt.Sprintf("%t-", val.(bool))) + } + if val, ok := m["os_type"]; ok && val != "" { + buf.WriteString(fmt.Sprintf("%s-", val.(string))) } - - // TODO(saamalik) fix for disk - //buf.WriteString(fmt.Sprintf("%d-", d["size_gb"].(int))) - //buf.WriteString(fmt.Sprintf("%s-", d["type"].(string))) - - //d2 := m["disk"].([]interface{}) - //d := d2[0].(map[string]interface{}) return int(hash(buf.String())) } func resourceMachinePoolAksHash(v interface{}) int { - var buf bytes.Buffer m := v.(map[string]interface{}) + buf := CommonHash(m) - buf.WriteString(HashStringMap(m["additional_labels"])) - buf.WriteString(HashStringMapList(m["taints"])) - - buf.WriteString(fmt.Sprintf("%s-", m["name"].(string))) - buf.WriteString(fmt.Sprintf("%d-", m["count"].(int))) - buf.WriteString(fmt.Sprintf("%s-", m["update_strategy"].(string))) - - if m["min"] != nil { - buf.WriteString(fmt.Sprintf("%d-", m["min"].(int))) + if val, ok := m["instance_type"]; ok { + buf.WriteString(fmt.Sprintf("%s-", val.(string))) } - if m["max"] != nil { - buf.WriteString(fmt.Sprintf("%d-", m["max"].(int))) + if val, ok := m["disk_size_gb"]; ok { + buf.WriteString(fmt.Sprintf("%d-", val.(int))) + } + if val, ok := m["is_system_node_pool"]; ok { + buf.WriteString(fmt.Sprintf("%t-", val.(bool))) + } + if val, ok := m["storage_account_type"]; ok { + buf.WriteString(fmt.Sprintf("%s-", val.(string))) } - buf.WriteString(fmt.Sprintf("%s-", m["instance_type"].(string))) - buf.WriteString(fmt.Sprintf("%d-", m["disk_size_gb"].(int))) - buf.WriteString(fmt.Sprintf("%t-", m["is_system_node_pool"].(bool))) - buf.WriteString(fmt.Sprintf("%s-", m["storage_account_type"].(string))) return int(hash(buf.String())) } func resourceMachinePoolGcpHash(v interface{}) int { - var buf bytes.Buffer m := v.(map[string]interface{}) - - buf.WriteString(HashStringMap(m["additional_labels"])) - buf.WriteString(HashStringMapList(m["taints"])) - - buf.WriteString(fmt.Sprintf("%t-", m["control_plane"].(bool))) - buf.WriteString(fmt.Sprintf("%t-", m["control_plane_as_worker"].(bool))) - buf.WriteString(fmt.Sprintf("%s-", m["name"].(string))) - buf.WriteString(fmt.Sprintf("%d-", m["count"].(int))) - buf.WriteString(fmt.Sprintf("%s-", m["update_strategy"].(string))) - - buf.WriteString(fmt.Sprintf("%s-", m["instance_type"].(string))) - buf.WriteString(fmt.Sprintf("%s-", m["azs"].(*schema.Set).GoString())) + buf := CommonHash(m) return int(hash(buf.String())) } func resourceMachinePoolAwsHash(v interface{}) int { - var buf bytes.Buffer m := v.(map[string]interface{}) + buf := CommonHash(m) - buf.WriteString(HashStringMap(m["additional_labels"])) - buf.WriteString(HashStringMapList(m["taints"])) - - buf.WriteString(fmt.Sprintf("%t-", m["control_plane"].(bool))) - buf.WriteString(fmt.Sprintf("%t-", m["control_plane_as_worker"].(bool))) - buf.WriteString(fmt.Sprintf("%s-", m["name"].(string))) - buf.WriteString(fmt.Sprintf("%d-", m["count"].(int))) - buf.WriteString(fmt.Sprintf("%s-", m["update_strategy"].(string))) - + if m["min"] != nil { + buf.WriteString(fmt.Sprintf("%d-", m["min"].(int))) + } + if m["max"] != nil { + buf.WriteString(fmt.Sprintf("%d-", m["max"].(int))) + } buf.WriteString(fmt.Sprintf("%s-", m["instance_type"].(string))) buf.WriteString(fmt.Sprintf("%s-", m["capacity_type"].(string))) buf.WriteString(fmt.Sprintf("%s-", m["max_price"].(string))) + if m["azs"] != nil { + azsSet := m["azs"].(*schema.Set) + azsList := azsSet.List() + azsListStr := make([]string, len(azsList)) + for i, v := range azsList { + azsListStr[i] = v.(string) + } + sort.Strings(azsListStr) + azsStr := strings.Join(azsListStr, "-") + buf.WriteString(fmt.Sprintf("%s-", azsStr)) + } buf.WriteString(fmt.Sprintf("%s-", m["azs"].(*schema.Set).GoString())) buf.WriteString(HashStringMap(m["az_subnets"])) @@ -108,17 +128,10 @@ func resourceMachinePoolAwsHash(v interface{}) int { } func resourceMachinePoolEksHash(v interface{}) int { - var buf bytes.Buffer m := v.(map[string]interface{}) + buf := CommonHash(m) - buf.WriteString(HashStringMap(m["additional_labels"])) - buf.WriteString(HashStringMapList(m["taints"])) - - buf.WriteString(fmt.Sprintf("%s-", m["name"].(string))) buf.WriteString(fmt.Sprintf("%d-", m["disk_size_gb"].(int))) - buf.WriteString(fmt.Sprintf("%d-", m["count"].(int))) - buf.WriteString(fmt.Sprintf("%s-", m["update_strategy"].(string))) - if m["min"] != nil { buf.WriteString(fmt.Sprintf("%d-", m["min"].(int))) } @@ -133,30 +146,50 @@ func resourceMachinePoolEksHash(v interface{}) int { buf.WriteString(fmt.Sprintf("%s-%s", i, j.(string))) } + if m["eks_launch_template"] != nil { + buf.WriteString(eksLaunchTemplate(m["eks_launch_template"])) + } + return int(hash(buf.String())) } -func resourceMachinePoolTkeHash(v interface{}) int { +func eksLaunchTemplate(v interface{}) string { var buf bytes.Buffer - m := v.(map[string]interface{}) + if len(v.([]interface{})) > 0 { + m := v.([]interface{})[0].(map[string]interface{}) - buf.WriteString(HashStringMap(m["additional_labels"])) - buf.WriteString(HashStringMapList(m["taints"])) + if m["ami_id"] != nil { + buf.WriteString(fmt.Sprintf("%s-", m["ami_id"].(string))) + } + if m["root_volume_type"] != nil { + buf.WriteString(fmt.Sprintf("%s-", m["root_volume_type"].(string))) + } + if m["root_volume_iops"] != nil { + buf.WriteString(fmt.Sprintf("%d-", m["root_volume_iops"].(int))) + } + if m["root_volume_throughput"] != nil { + buf.WriteString(fmt.Sprintf("%d-", m["root_volume_throughput"].(int))) + } + if m["additional_security_groups"] != nil { + for _, sg := range m["additional_security_groups"].(*schema.Set).List() { + buf.WriteString(fmt.Sprintf("%s-", sg.(string))) + } + } + } - buf.WriteString(fmt.Sprintf("%s-", m["name"].(string))) - buf.WriteString(fmt.Sprintf("%d-", m["disk_size_gb"].(int))) - buf.WriteString(fmt.Sprintf("%d-", m["count"].(int))) - buf.WriteString(fmt.Sprintf("%s-", m["update_strategy"].(string))) + return buf.String() +} - if m["min"] != nil { - buf.WriteString(fmt.Sprintf("%d-", m["min"].(int))) - } - if m["max"] != nil { - buf.WriteString(fmt.Sprintf("%d-", m["max"].(int))) - } - buf.WriteString(fmt.Sprintf("%s-", m["instance_type"].(string))) - buf.WriteString(fmt.Sprintf("%s-", m["capacity_type"].(string))) - buf.WriteString(fmt.Sprintf("%s-", m["max_price"].(string))) +func resourceMachinePoolCoxEdgeHash(v interface{}) int { + m := v.(map[string]interface{}) + buf := CommonHash(m) + + return int(hash(buf.String())) +} + +func resourceMachinePoolTkeHash(v interface{}) int { + m := v.(map[string]interface{}) + buf := CommonHash(m) for i, j := range m["az_subnets"].(map[string]interface{}) { buf.WriteString(fmt.Sprintf("%s-%s", i, j.(string))) @@ -166,18 +199,8 @@ func resourceMachinePoolTkeHash(v interface{}) int { } func resourceMachinePoolVsphereHash(v interface{}) int { - var buf bytes.Buffer m := v.(map[string]interface{}) - - buf.WriteString(HashStringMap(m["additional_labels"])) - buf.WriteString(HashStringMapList(m["taints"])) - - //d := m["disk"].([]interface{})[0].(map[string]interface{}) - buf.WriteString(fmt.Sprintf("%t-", m["control_plane"].(bool))) - buf.WriteString(fmt.Sprintf("%t-", m["control_plane_as_worker"].(bool))) - buf.WriteString(fmt.Sprintf("%s-", m["name"].(string))) - buf.WriteString(fmt.Sprintf("%d-", m["count"].(int))) - buf.WriteString(fmt.Sprintf("%s-", m["update_strategy"].(string))) + buf := CommonHash(m) if v, found := m["instance_type"]; found { if len(v.([]interface{})) > 0 { @@ -188,21 +211,22 @@ func resourceMachinePoolVsphereHash(v interface{}) int { } } + if placements, found := m["placement"]; found { + for _, p := range placements.([]interface{}) { + place := p.(map[string]interface{}) + buf.WriteString(fmt.Sprintf("%s-", place["cluster"].(string))) + buf.WriteString(fmt.Sprintf("%s-", place["resource_pool"].(string))) + buf.WriteString(fmt.Sprintf("%s-", place["datastore"].(string))) + buf.WriteString(fmt.Sprintf("%s-", place["network"].(string))) + buf.WriteString(fmt.Sprintf("%s-", place["static_ip_pool_id"].(string))) + } + } return int(hash(buf.String())) } func resourceMachinePoolOpenStackHash(v interface{}) int { - var buf bytes.Buffer m := v.(map[string]interface{}) - - buf.WriteString(HashStringMap(m["additional_labels"])) - buf.WriteString(HashStringMapList(m["taints"])) - - buf.WriteString(fmt.Sprintf("%t-", m["control_plane"].(bool))) - buf.WriteString(fmt.Sprintf("%t-", m["control_plane_as_worker"].(bool))) - buf.WriteString(fmt.Sprintf("%s-", m["name"].(string))) - buf.WriteString(fmt.Sprintf("%d-", m["count"].(int))) - buf.WriteString(fmt.Sprintf("%s-", m["update_strategy"].(string))) + buf := CommonHash(m) buf.WriteString(fmt.Sprintf("%s-", m["instance_type"].(string))) buf.WriteString(fmt.Sprintf("%s-", m["subnet_id"].(string))) @@ -213,33 +237,15 @@ func resourceMachinePoolOpenStackHash(v interface{}) int { } func resourceMachinePoolVirtualHash(v interface{}) int { - var buf bytes.Buffer m := v.(map[string]interface{}) - - buf.WriteString(HashStringMap(m["additional_labels"])) - buf.WriteString(HashStringMapList(m["taints"])) - - buf.WriteString(fmt.Sprintf("%t-", m["control_plane"].(bool))) - buf.WriteString(fmt.Sprintf("%t-", m["control_plane_as_worker"].(bool))) - buf.WriteString(fmt.Sprintf("%s-", m["name"].(string))) - buf.WriteString(fmt.Sprintf("%d-", m["count"].(int))) - buf.WriteString(fmt.Sprintf("%s-", m["update_strategy"].(string))) + buf := CommonHash(m) return int(hash(buf.String())) } func resourceMachinePoolMaasHash(v interface{}) int { - var buf bytes.Buffer m := v.(map[string]interface{}) - - buf.WriteString(HashStringMap(m["additional_labels"])) - buf.WriteString(HashStringMapList(m["taints"])) - - buf.WriteString(fmt.Sprintf("%t-", m["control_plane"].(bool))) - buf.WriteString(fmt.Sprintf("%t-", m["control_plane_as_worker"].(bool))) - buf.WriteString(fmt.Sprintf("%s-", m["name"].(string))) - buf.WriteString(fmt.Sprintf("%d-", m["count"].(int))) - buf.WriteString(fmt.Sprintf("%s-", m["update_strategy"].(string))) + buf := CommonHash(m) if v, found := m["instance_type"]; found { if len(v.([]interface{})) > 0 { @@ -254,18 +260,8 @@ func resourceMachinePoolMaasHash(v interface{}) int { } func resourceMachinePoolLibvirtHash(v interface{}) int { - var buf bytes.Buffer m := v.(map[string]interface{}) - - buf.WriteString(HashStringMap(m["additional_labels"])) - buf.WriteString(HashStringMapList(m["taints"])) - - //d := m["disk"].([]interface{})[0].(map[string]interface{}) - buf.WriteString(fmt.Sprintf("%t-", m["control_plane"].(bool))) - buf.WriteString(fmt.Sprintf("%t-", m["control_plane_as_worker"].(bool))) - buf.WriteString(fmt.Sprintf("%s-", m["name"].(string))) - buf.WriteString(fmt.Sprintf("%d-", m["count"].(int))) - buf.WriteString(fmt.Sprintf("%s-", m["update_strategy"].(string))) + buf := CommonHash(m) if v, found := m["xsl_template"]; found { buf.WriteString(fmt.Sprintf("%s-", v.(string))) @@ -274,73 +270,61 @@ func resourceMachinePoolLibvirtHash(v interface{}) int { if v, found := m["instance_type"]; found { if len(v.([]interface{})) > 0 { ins := v.([]interface{})[0].(map[string]interface{}) - buf.WriteString(fmt.Sprintf("%d-", ins["cpu"].(int))) - buf.WriteString(fmt.Sprintf("%d-", ins["disk_size_gb"].(int))) - buf.WriteString(fmt.Sprintf("%d-", ins["memory_mb"].(int))) - buf.WriteString(fmt.Sprintf("%s-", ins["cpus_sets"].(string))) - if ins["cache_passthrough"] != nil { - buf.WriteString(fmt.Sprintf("%s-%t", "cache_passthrough", ins["cache_passthrough"].(bool))) - } - if ins["gpu_config"] != nil { - config, _ := ins["gpu_config"].(map[string]interface{}) - if config != nil { - buf.WriteString(fmt.Sprintf("%d-", config["num_gpus"].(int))) - buf.WriteString(fmt.Sprintf("%s-", config["device_model"].(string))) - buf.WriteString(fmt.Sprintf("%s-", config["vendor"].(string))) - buf.WriteString(HashStringMap(config["addresses"])) - } - } - - if ins["attached_disks"] != nil { - for _, disk := range ins["attached_disks"].([]interface{}) { - diskMap := disk.(map[string]interface{}) - if diskMap["managed"] != nil { - buf.WriteString(fmt.Sprintf("%s-%t", "managed", diskMap["managed"].(bool))) - } - if diskMap["size_in_gb"] != nil { - buf.WriteString(fmt.Sprintf("%s-%d", "size_in_gb", diskMap["size_in_gb"].(int))) - } - } - } + buf.WriteString(InstanceTypeHash(ins)) } } return int(hash(buf.String())) } -func resourceMachinePoolEdgeNativeHash(v interface{}) int { +func InstanceTypeHash(ins map[string]interface{}) string { var buf bytes.Buffer - m := v.(map[string]interface{}) - - buf.WriteString(HashStringMap(m["additional_labels"])) - buf.WriteString(HashStringMapList(m["taints"])) - - buf.WriteString(fmt.Sprintf("%t-", m["control_plane"].(bool))) - buf.WriteString(fmt.Sprintf("%t-", m["control_plane_as_worker"].(bool))) - buf.WriteString(fmt.Sprintf("%s-", m["name"].(string))) - buf.WriteString(fmt.Sprintf("%s-", m["update_strategy"].(string))) - - if _, found := m["host_uids"]; found { - for _, host := range m["host_uids"].([]interface{}) { - buf.WriteString(fmt.Sprintf("%s-", host.(string))) + buf.WriteString(fmt.Sprintf("%d-", ins["cpu"].(int))) + buf.WriteString(fmt.Sprintf("%d-", ins["disk_size_gb"].(int))) + buf.WriteString(fmt.Sprintf("%d-", ins["memory_mb"].(int))) + buf.WriteString(fmt.Sprintf("%s-", ins["cpus_sets"].(string))) + if ins["cache_passthrough"] != nil { + buf.WriteString(fmt.Sprintf("%s-%t", "cache_passthrough", ins["cache_passthrough"].(bool))) + } + if ins["gpu_config"] != nil { + config, _ := ins["gpu_config"].(map[string]interface{}) + if config != nil { + buf.WriteString(GpuConfigHash(config)) } } - return int(hash(buf.String())) + if ins["attached_disks"] != nil { + for _, disk := range ins["attached_disks"].([]interface{}) { + diskMap := disk.(map[string]interface{}) + if diskMap["managed"] != nil { + buf.WriteString(fmt.Sprintf("%s-%t", "managed", diskMap["managed"].(bool))) + } + if diskMap["size_in_gb"] != nil { + buf.WriteString(fmt.Sprintf("%s-%d", "size_in_gb", diskMap["size_in_gb"].(int))) + } + } + } + return buf.String() } -func resourceMachinePoolEdgeHash(v interface{}) int { +func GpuConfigHash(config map[string]interface{}) string { var buf bytes.Buffer - m := v.(map[string]interface{}) + buf.WriteString(fmt.Sprintf("%d-", config["num_gpus"].(int))) + buf.WriteString(fmt.Sprintf("%s-", config["device_model"].(string))) + buf.WriteString(fmt.Sprintf("%s-", config["vendor"].(string))) + buf.WriteString(HashStringMap(config["addresses"])) + return buf.String() +} - buf.WriteString(HashStringMap(m["additional_labels"])) - buf.WriteString(HashStringMapList(m["taints"])) +func resourceMachinePoolEdgeNativeHash(v interface{}) int { + m := v.(map[string]interface{}) + buf := CommonHash(m) - buf.WriteString(fmt.Sprintf("%t-", m["control_plane"].(bool))) - buf.WriteString(fmt.Sprintf("%t-", m["control_plane_as_worker"].(bool))) - buf.WriteString(fmt.Sprintf("%s-", m["name"].(string))) - buf.WriteString(fmt.Sprintf("%d-", m["count"].(int))) - buf.WriteString(fmt.Sprintf("%s-", m["update_strategy"].(string))) + if _, found := m["host_uids"]; found { + for _, host := range m["host_uids"].([]interface{}) { + buf.WriteString(fmt.Sprintf("%s-", host.(string))) + } + } return int(hash(buf.String())) } @@ -368,7 +352,7 @@ func HashStringMapList(v interface{}) string { hashes = append(hashes, HashStringMap(i)) } - sortedHashes := make([]string, len(hashes), len(hashes)) + sortedHashes := make([]string, len(hashes)) copy(sortedHashes, hashes) sort.Strings(sortedHashes) @@ -392,7 +376,7 @@ func HashStringMap(v interface{}) string { keys = append(keys, k) } - sortedKeys := make([]string, len(keys), len(keys)) + sortedKeys := make([]string, len(keys)) copy(sortedKeys, keys) sort.Strings(sortedKeys) diff --git a/spectrocloud/cluster_common_hash_test.go b/spectrocloud/cluster_common_hash_test.go new file mode 100644 index 00000000..9c33241f --- /dev/null +++ b/spectrocloud/cluster_common_hash_test.go @@ -0,0 +1,652 @@ +package spectrocloud + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/stretchr/testify/assert" +) + +func commonNodePool() map[string]interface{} { + nodePool := map[string]interface{}{ + "additional_labels": map[string]interface{}{ + "label1": "value1", + }, + "taints": []interface{}{ + map[string]interface{}{ + "key": "taint1", + "value": "true", + "effect": "NoSchedule", + }, + }, + "control_plane": true, + "control_plane_as_worker": false, + "name": "test-pool", + "count": 3, + "update_strategy": "RollingUpdate", + "node_repave_interval": 10, + } + return nodePool +} + +func TestCommonHash(t *testing.T) { + + expectedHash := "label1-value1effect-NoSchedulekey-taint1value-truetrue-false-test-pool-3-RollingUpdate-10-" + hash := CommonHash(commonNodePool()).String() + + assert.Equal(t, expectedHash, hash) +} + +func TestResourceMachinePoolAzureHash(t *testing.T) { + nodePool := map[string]interface{}{ + "additional_labels": map[string]interface{}{ + "label1": "value1", + }, + "taints": []interface{}{ + map[string]interface{}{ + "key": "taint1", + "value": "true", + "effect": "NoSchedule", + }, + }, + "control_plane": true, + "control_plane_as_worker": false, + "name": "test-pool", + "count": 3, + "update_strategy": "RollingUpdate", + "node_repave_interval": 10, + "instance_type": "Standard_D2_v3", + "is_system_node_pool": true, + "os_type": "Linux", + } + + expectedHash := 3495386805 + + hash := resourceMachinePoolAzureHash(nodePool) + + assert.Equal(t, expectedHash, hash) +} + +func TestResourceClusterHash(t *testing.T) { + clusterData := map[string]interface{}{ + "uid": "abc123", + } + + expectedHash := 1764273400 + + hash := resourceClusterHash(clusterData) + + assert.Equal(t, expectedHash, hash) +} + +func TestHashStringMapList(t *testing.T) { + stringMapList := []interface{}{ + map[string]interface{}{"key1": "value1", "key2": "value2"}, + map[string]interface{}{"key3": "value3"}, + } + + expectedHash := "key1-value1key2-value2key3-value3" + hash := HashStringMapList(stringMapList) + + assert.Equal(t, expectedHash, hash) +} + +func TestHashStringMapListlength(t *testing.T) { + stringMapList := []interface{}{} + + expectedHash := "" + hash := HashStringMapList(stringMapList) + + assert.Equal(t, expectedHash, hash) +} + +func TestResourceMachinePoolAksHash(t *testing.T) { + testCases := []struct { + name string + input interface{} + expected int + }{ + { + name: "Test Valid ResourceMachinePoolAksHash", + input: map[string]interface{}{ + "instance_type": "Standard_D2s_v3", + "disk_size_gb": 100, + "is_system_node_pool": true, + "storage_account_type": "Premium_LRS", + }, + expected: 380130606, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + result := resourceMachinePoolAksHash(tc.input) + assert.Equal(t, tc.expected, result) + }) + } +} + +func TestResourceMachinePoolGcpHash(t *testing.T) { + testCases := []struct { + input interface{} + expected int + }{ + { + input: map[string]interface{}{ + "instance_type": "n1-standard-4", + "min": 1, + "max": 3, + "capacity_type": "ON_DEMAND", + "max_price": "0.12", + "azs": []string{"us-central1-a", "us-central1-b"}, + "az_subnets": map[string]interface{}{ + "us-central1-a": "subnet-1", + "us-central1-b": "subnet-2", + }, + }, + expected: 1198721703, + }, + } + for _, tc := range testCases { + actual := resourceMachinePoolGcpHash(tc.input) + if actual != tc.expected { + t.Errorf("Expected hash %d, but got %d for input %+v", tc.expected, actual, tc.input) + } + } +} + +func TestResourceMachinePoolAwsHash(t *testing.T) { + testCases := []struct { + input interface{} + expected int + }{ + { + input: map[string]interface{}{ + "min": 1, + "max": 5, + "instance_type": "t2.micro", + "capacity_type": "ON_DEMAND", + "max_price": "0.03", + "azs": schema.NewSet(schema.HashString, []interface{}{ + "us-east-1a", + "us-east-1b", + }), + + "az_subnets": map[string]interface{}{ + "us-east-1a": "subnet-1", + "us-east-1b": "subnet-2", + }, + }, + expected: 1929542909, + }, + } + + for _, tc := range testCases { + actual := resourceMachinePoolAwsHash(tc.input) + if actual != tc.expected { + t.Errorf("Expected hash %d, but got %d for input %+v", tc.expected, actual, tc.input) + } + } +} + +func TestResourceMachinePoolEksHash(t *testing.T) { + + testCases := []struct { + input interface{} + expected int + }{ + { + input: map[string]interface{}{ + "disk_size_gb": 100, + "min": 2, + "max": 5, + "instance_type": "t2.micro", + "capacity_type": "on-demand", + "max_price": "0.05", + "az_subnets": map[string]interface{}{ + "subnet1": "subnet-123", + "subnet2": "subnet-456", + }, + "eks_launch_template": []interface{}{ + map[string]interface{}{ + "ami_id": "ami-123", + "root_volume_type": "gp2", + }, + }, + }, + expected: 456946481, + }, + } + + for _, tc := range testCases { + t.Run(fmt.Sprintf("Input: %v", tc.input), func(t *testing.T) { + // Call the function with the test input + result := resourceMachinePoolEksHash(tc.input) + + // Check if the result matches the expected output + if result != tc.expected { + t.Errorf("Expected: %d, Got: %d", tc.expected, result) + } + }) + } +} + +func TestEksLaunchTemplate(t *testing.T) { + + testCases := []struct { + input interface{} + expected string + }{ + { + + input: []interface{}{ + map[string]interface{}{ + "ami_id": "ami-123", + "root_volume_type": "gp2", + "root_volume_iops": 100, + "root_volume_throughput": 200, + "additional_security_groups": schema.NewSet(schema.HashString, []interface{}{"sg-123", "sg-456"}), + }, + }, + expected: "ami-123-gp2-100-200-sg-456-sg-123-", + }, + { + // Test case with invalid input type (slice of non-map) + input: []interface{}{}, + expected: "", + }, + } + + for _, tc := range testCases { + t.Run(fmt.Sprintf("Input: %v", tc.input), func(t *testing.T) { + // Call the function with the test input + result := eksLaunchTemplate(tc.input) + + // Check if the result matches the expected output + if result != tc.expected { + t.Errorf("Expected: %s, Got: %s", tc.expected, result) + } + }) + } +} + +func TestResourceMachinePoolCoxEdgeHash(t *testing.T) { + + testCases := []struct { + input map[string]interface{} + expected int + }{ + { + + input: commonNodePool(), + expected: 513591628, + }, + { + // Test case with empty input + input: nil, + expected: 2166136261, + }, + } + + for _, tc := range testCases { + t.Run("", func(t *testing.T) { + // Call the function with the test input + result := resourceMachinePoolCoxEdgeHash(tc.input) + + // Check if the result matches the expected output + if result != tc.expected { + t.Errorf("Expected: %d, Got: %d", tc.expected, result) + } + }) + } +} + +func TestResourceMachinePoolTkeHash(t *testing.T) { + testCases := []struct { + input map[string]interface{} + expected int + }{ + { + + input: map[string]interface{}{ + "az_subnets": map[string]interface{}{ + "subnet1": "10.0.0.1", + "subnet2": "10.0.0.2", + }, + }, + expected: 3634270287, + }, + } + + for _, tc := range testCases { + t.Run("", func(t *testing.T) { + // Call the function with the test input + result := resourceMachinePoolTkeHash(tc.input) + + // Check if the result matches the expected output + if result != tc.expected { + t.Errorf("Expected: %d, Got: %d", tc.expected, result) + } + }) + } +} + +func TestResourceMachinePoolVsphereHash(t *testing.T) { + + testCases := []struct { + input interface{} + expected int + }{ + { + input: map[string]interface{}{ + "instance_type": []interface{}{ + map[string]interface{}{ + "cpu": 2, + "disk_size_gb": 50, + "memory_mb": 4096, + }, + }, + "placement": []interface{}{ + map[string]interface{}{ + "cluster": "cluster1", + "resource_pool": "resource_pool1", + "datastore": "datastore1", + "network": "network1", + "static_ip_pool_id": "static_pool1", + }, + }, + }, + expected: 556255137, + }, + { + // Test case with missing instance_type + input: map[string]interface{}{ + "placement": []interface{}{ + map[string]interface{}{ + "cluster": "cluster2", + "resource_pool": "resource_pool2", + "datastore": "datastore2", + "network": "network2", + "static_ip_pool_id": "static_pool2", + }, + }, + }, + expected: 3826670463, + }, + } + + for _, tc := range testCases { + t.Run("", func(t *testing.T) { + // Call the function with the test input + result := resourceMachinePoolVsphereHash(tc.input) + + // Check if the result matches the expected output + if result != tc.expected { + t.Errorf("Expected: %d, Got: %d", tc.expected, result) + } + }) + } +} + +func TestResourceMachinePoolEdgeNativeHash(t *testing.T) { + + testCases := []struct { + input interface{} + expected int + }{ + { + input: map[string]interface{}{ + "host_uids": []interface{}{"host1", "host2", "host3"}, + }, + expected: 456992116, + }, + { + input: map[string]interface{}{}, + expected: 2166136261, + }, + } + + for _, tc := range testCases { + t.Run("", func(t *testing.T) { + result := resourceMachinePoolEdgeNativeHash(tc.input) + + if result != tc.expected { + t.Errorf("Expected: %d, Got: %d", tc.expected, result) + } + }) + } +} + +func TestGpuConfigHash(t *testing.T) { + + testCases := []struct { + input map[string]interface{} + expected string + }{ + { + + input: map[string]interface{}{ + "num_gpus": 2, + "device_model": "model1", + "vendor": "vendor1", + "addresses": map[string]interface{}{ + "address1": "value1", + "address2": "value2", + }, + }, + expected: "2-model1-vendor1-address1-value1address2-value2", + }, + { + // Test case with missing "addresses" key + input: map[string]interface{}{ + "num_gpus": 1, + "device_model": "model2", + "vendor": "vendor2", + }, + expected: "1-model2-vendor2-", + }, + } + + for _, tc := range testCases { + t.Run("", func(t *testing.T) { + result := GpuConfigHash(tc.input) + + if result != tc.expected { + t.Errorf("Expected: %s, Got: %s", tc.expected, result) + } + }) + } +} + +func TestInstanceTypeHash(t *testing.T) { + testCases := []struct { + name string + input map[string]interface{} + expectedHash string + }{ + { + name: "Valid InstanceTypeHash", + input: map[string]interface{}{ + "cpu": 4, + "disk_size_gb": 100, + "memory_mb": 8192, + "cpus_sets": "0-3", + "cache_passthrough": true, + "gpu_config": map[string]interface{}{ + "num_gpus": 2, + "device_model": "Tesla T4", + "vendor": "NVIDIA", + "addresses": map[string]interface{}{ + "gpu-address-1": "10.0.0.1", + "gpu-address-2": "10.0.0.2", + }, + }, + "attached_disks": []interface{}{ + map[string]interface{}{ + "managed": true, + "size_in_gb": 500, + }, + }, + }, + expectedHash: "4-100-8192-0-3-cache_passthrough-true2-Tesla T4-NVIDIA-gpu-address-1-10.0.0.1gpu-address-2-10.0.0.2managed-truesize_in_gb-500", + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + hash := InstanceTypeHash(tc.input) + assert.Equal(t, tc.expectedHash, hash) + }) + } +} + +func TestResourceMachinePoolLibvirtHash(t *testing.T) { + testCases := []struct { + name string + input interface{} + expectedHash int + }{ + { + name: "Valid MachinePoolLibvirtHash", + input: map[string]interface{}{ + "xsl_template": "xsl-template-1", + "instance_type": []interface{}{ + map[string]interface{}{ + "cpu": 4, + "disk_size_gb": 100, + "memory_mb": 8192, + "cpus_sets": "0-3", + "cache_passthrough": true, + "gpu_config": map[string]interface{}{ + "num_gpus": 2, + "device_model": "Tesla T4", + "vendor": "NVIDIA", + "addresses": map[string]interface{}{ + "gpu-address-1": "10.0.0.1", + "gpu-address-2": "10.0.0.2", + }, + }, + "attached_disks": []interface{}{ + map[string]interface{}{ + "managed": true, + "size_in_gb": 500, + }, + }, + }, + }, + }, + expectedHash: 3451728783, + }, + { + name: "Test Case 2", + input: map[string]interface{}{}, + expectedHash: 2166136261, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + hash := resourceMachinePoolLibvirtHash(tc.input) + assert.Equal(t, tc.expectedHash, hash) + }) + } +} + +func TestResourceMachinePoolMaasHash(t *testing.T) { + testCases := []struct { + name string + input interface{} + expectedHash int + }{ + { + name: "Valid MachinePoolMaasHash", + input: map[string]interface{}{ + "instance_type": []interface{}{ + map[string]interface{}{ + "min_cpu": 2, + "min_memory_mb": 4096, + }, + }, + "azs": schema.NewSet(schema.HashString, []interface{}{"az1", "az2"}), + }, + expectedHash: 3363048657, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + hash := resourceMachinePoolMaasHash(tc.input) + assert.Equal(t, tc.expectedHash, hash) + }) + } +} + +func TestResourceMachinePoolVirtualHash(t *testing.T) { + testCases := []struct { + name string + input interface{} + expectedHash int + }{ + { + name: "Valid MachinePoolVirtualHash", + input: map[string]interface{}{ + "key1": "value1", + "key2": 123, + }, + expectedHash: 2166136261, + }, + { + name: "Test Case 2", + input: map[string]interface{}{ + "key3": "value3", + "key4": true, + }, + expectedHash: 2166136261, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + hash := resourceMachinePoolVirtualHash(tc.input) + assert.Equal(t, tc.expectedHash, hash) + }) + } +} + +func TestResourceMachinePoolOpenStackHash(t *testing.T) { + testCases := []struct { + name string + input interface{} + expectedHash int + }{ + { + name: "Valid MachinePoolOpenStackHash", + input: map[string]interface{}{ + "instance_type": "flavor1", + "subnet_id": "subnet123", + "update_strategy": "RollingUpdate", + "azs": schema.NewSet(schema.HashString, []interface{}{"az1", "az2"}), + }, + expectedHash: 3148662768, + }, + { + name: "Valid MachinePoolOpenStackHash 2", + input: map[string]interface{}{ + "instance_type": "flavor2", + "subnet_id": "subnet456", + "update_strategy": "Recreate", + "azs": schema.NewSet(schema.HashString, []interface{}{"az3"}), + }, + expectedHash: 4045757255, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + hash := resourceMachinePoolOpenStackHash(tc.input) + assert.Equal(t, tc.expectedHash, hash) + }) + } +} diff --git a/spectrocloud/cluster_common_taints.go b/spectrocloud/cluster_common_taints.go index 2901af21..da09ed9b 100644 --- a/spectrocloud/cluster_common_taints.go +++ b/spectrocloud/cluster_common_taints.go @@ -47,8 +47,8 @@ func flattenClusterTaints(items []*models.V1Taint) []interface{} { return result } -func SetAdditionalLabelsAndTaints(labels map[string]string, intaints []*models.V1Taint, oi map[string]interface{}) { - if labels == nil || len(labels) == 0 { +func FlattenAdditionalLabelsAndTaints(labels map[string]string, intaints []*models.V1Taint, oi map[string]interface{}) { + if len(labels) == 0 { oi["additional_labels"] = make(map[string]interface{}) } else { oi["additional_labels"] = labels diff --git a/spectrocloud/cluster_node_common.go b/spectrocloud/cluster_node_common.go new file mode 100644 index 00000000..356a6a95 --- /dev/null +++ b/spectrocloud/cluster_node_common.go @@ -0,0 +1,16 @@ +package spectrocloud + +import ( + "github.com/spectrocloud/hapi/models" +) + +var NodeMaintenanceLifecycleStates = []string{ + "Completed", + "InProgress", + "Initiated", + "Failed", +} + +type GetMaintenanceStatus func(string, string, string, string) (*models.V1MachineMaintenanceStatus, error) + +type GetNodeStatusMap func(string, string, string) (map[string]models.V1CloudMachineStatus, error) diff --git a/spectrocloud/provider.go b/spectrocloud/provider.go index 58231e6f..0c35ecc6 100644 --- a/spectrocloud/provider.go +++ b/spectrocloud/provider.go @@ -24,6 +24,7 @@ func New(_ string) func() *schema.Provider { "username": { Type: schema.TypeString, Optional: true, + Deprecated: "Deprecated since 0.15.0 use `api_key` instead.", Description: "The Spectro Cloud username. Can also be set with the `SPECTROCLOUD_USERNAME` environment variable.", DefaultFunc: schema.EnvDefaultFunc("SPECTROCLOUD_USERNAME", nil), }, @@ -31,6 +32,7 @@ func New(_ string) func() *schema.Provider { Type: schema.TypeString, Optional: true, Sensitive: true, + Deprecated: "Deprecated since 0.15.0 use `api_key` instead.", Description: "The Spectro Cloud user password. Can also be set with the `SPECTROCLOUD_PASSWORD` environment variable.", DefaultFunc: schema.EnvDefaultFunc("SPECTROCLOUD_PASSWORD", nil), }, diff --git a/spectrocloud/resource_cluster_aks.go b/spectrocloud/resource_cluster_aks.go index a7af33e1..32ee7b3d 100644 --- a/spectrocloud/resource_cluster_aks.go +++ b/spectrocloud/resource_cluster_aks.go @@ -491,7 +491,7 @@ func flattenMachinePoolConfigsAks(machinePools []*models.V1AzureMachinePoolConfi for _, machinePool := range machinePools { oi := make(map[string]interface{}) - SetAdditionalLabelsAndTaints(machinePool.AdditionalLabels, machinePool.Taints, oi) + FlattenAdditionalLabelsAndTaints(machinePool.AdditionalLabels, machinePool.Taints, oi) if *machinePool.IsControlPlane { continue diff --git a/spectrocloud/resource_cluster_aws.go b/spectrocloud/resource_cluster_aws.go index bfde3d5b..7f4696b4 100644 --- a/spectrocloud/resource_cluster_aws.go +++ b/spectrocloud/resource_cluster_aws.go @@ -2,16 +2,19 @@ package spectrocloud import ( "context" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" - "github.com/spectrocloud/terraform-provider-spectrocloud/spectrocloud/schemas" - "github.com/spectrocloud/terraform-provider-spectrocloud/types" "log" "strings" "time" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" + + "github.com/spectrocloud/terraform-provider-spectrocloud/spectrocloud/schemas" + "github.com/spectrocloud/terraform-provider-spectrocloud/types" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/spectrocloud/hapi/models" + "github.com/spectrocloud/terraform-provider-spectrocloud/pkg/client" ) @@ -245,6 +248,22 @@ func resourceClusterAws() *schema.Resource { Type: schema.TypeString, Required: true, }, + "min": { + Type: schema.TypeInt, + Optional: true, + Description: "Minimum number of nodes in the machine pool. This is used for autoscaling the machine pool.", + }, + "max": { + Type: schema.TypeInt, + Optional: true, + Description: "Maximum number of nodes in the machine pool. This is used for autoscaling the machine pool.", + }, + "node_repave_interval": { + Type: schema.TypeInt, + Optional: true, + Default: 0, + Description: "Minimum number of seconds node should be Ready, before the next node is selected for repave. Default value is `0`, Applicable only for worker pools.", + }, "capacity_type": { Type: schema.TypeString, Default: "on-demand", @@ -499,7 +518,8 @@ func flattenMachinePoolConfigsAws(machinePools []*models.V1AwsMachinePoolConfig) for i, machinePool := range machinePools { oi := make(map[string]interface{}) - SetAdditionalLabelsAndTaints(machinePool.AdditionalLabels, machinePool.Taints, oi) + FlattenAdditionalLabelsAndTaints(machinePool.AdditionalLabels, machinePool.Taints, oi) + FlattenControlPlaneAndRepaveInterval(machinePool.IsControlPlane, oi, machinePool.NodeRepaveInterval) oi["control_plane"] = machinePool.IsControlPlane oi["control_plane_as_worker"] = machinePool.UseControlPlaneAsWorker @@ -554,23 +574,33 @@ func resourceClusterAwsUpdate(ctx context.Context, d *schema.ResourceData, m int for _, mp := range ns.List() { machinePoolResource := mp.(map[string]interface{}) - name := machinePoolResource["name"].(string) - if name != "" { - hash := resourceMachinePoolAwsHash(machinePoolResource) - vpcId := d.Get("cloud_config").([]interface{})[0].(map[string]interface{})["vpc_id"] - machinePool := toMachinePoolAws(machinePoolResource, vpcId.(string)) - - var err error - if oldMachinePool, ok := osMap[name]; !ok { - log.Printf("Create machine pool %s", name) - err = c.CreateMachinePoolAws(cloudConfigId, machinePool) - } else if hash != resourceMachinePoolAwsHash(oldMachinePool) { - log.Printf("Change in machine pool %s", name) - err = c.UpdateMachinePoolAws(cloudConfigId, machinePool) - } - - if err != nil { - return diag.FromErr(err) + // since known issue in TF SDK: https://github.com/hashicorp/terraform-plugin-sdk/issues/588 + if machinePoolResource["name"].(string) != "" { + name := machinePoolResource["name"].(string) + if name != "" { + hash := resourceMachinePoolAwsHash(machinePoolResource) + vpcId := d.Get("cloud_config").([]interface{})[0].(map[string]interface{})["vpc_id"] + + var err error + machinePool, err := toMachinePoolAws(machinePoolResource, vpcId.(string)) + if err != nil { + return diag.FromErr(err) + } + + if oldMachinePool, ok := osMap[name]; !ok { + log.Printf("Create machine pool %s", name) + err = c.CreateMachinePoolAws(cloudConfigId, machinePool) + } else if hash != resourceMachinePoolAwsHash(oldMachinePool) { + log.Printf("Change in machine pool %s", name) + err = c.UpdateMachinePoolAws(cloudConfigId, machinePool) + } + + if err != nil { + return diag.FromErr(err) + } + + // Processed (if exists) + delete(osMap, name) } // Processed (if exists) @@ -628,7 +658,10 @@ func toAwsCluster(c *client.V1Client, d *schema.ResourceData) *models.V1SpectroA //for _, machinePool := range d.Get("machine_pool").([]interface{}) { machinePoolConfigs := make([]*models.V1AwsMachinePoolConfigEntity, 0) for _, machinePool := range d.Get("machine_pool").(*schema.Set).List() { - mp := toMachinePoolAws(machinePool, cluster.Spec.CloudConfig.VpcID) + mp, err := toMachinePoolAws(machinePool, cluster.Spec.CloudConfig.VpcID) + if err != nil { + return nil + } machinePoolConfigs = append(machinePoolConfigs, mp) } @@ -638,7 +671,7 @@ func toAwsCluster(c *client.V1Client, d *schema.ResourceData) *models.V1SpectroA return cluster } -func toMachinePoolAws(machinePool interface{}, vpcId string) *models.V1AwsMachinePoolConfigEntity { +func toMachinePoolAws(machinePool interface{}, vpcId string) (*models.V1AwsMachinePoolConfigEntity, error) { m := machinePool.(map[string]interface{}) labels := make([]string, 0) @@ -668,6 +701,17 @@ func toMachinePoolAws(machinePool interface{}, vpcId string) *models.V1AwsMachin azs = append(azs, az.(string)) } } + min := int32(m["count"].(int)) + max := int32(m["count"].(int)) + + if m["min"] != nil { + min = int32(m["min"].(int)) + } + + if m["max"] != nil { + max = int32(m["max"].(int)) + } + mp := &models.V1AwsMachinePoolConfigEntity{ CloudConfig: &models.V1AwsMachinePoolCloudConfigEntity{ Azs: azs, @@ -686,10 +730,26 @@ func toMachinePoolAws(machinePool interface{}, vpcId string) *models.V1AwsMachin UpdateStrategy: &models.V1UpdateStrategy{ Type: getUpdateStrategy(m), }, + MinSize: min, + MaxSize: max, UseControlPlaneAsWorker: controlPlaneAsWorker, }, } + if !controlPlane { + nodeRepaveInterval := 0 + if m["node_repave_interval"] != nil { + nodeRepaveInterval = m["node_repave_interval"].(int) + } + mp.PoolConfig.NodeRepaveInterval = int32(nodeRepaveInterval) + } else { + err := ValidationNodeRepaveIntervalForControlPlane(m["node_repave_interval"].(int)) + if err != nil { + return mp, err + } + + } + if capacityType == "spot" { maxPrice := "0.0" // default value if m["max_price"] != nil && len(m["max_price"].(string)) > 0 { @@ -700,5 +760,10 @@ func toMachinePoolAws(machinePool interface{}, vpcId string) *models.V1AwsMachin MaxPrice: maxPrice, } } - return mp + + if m["additional_security_groups"] != nil { + mp.CloudConfig.AdditionalSecurityGroups = setAdditionalSecurityGroups(m) + } + + return mp, nil } diff --git a/spectrocloud/resource_cluster_aws_expand_test.go b/spectrocloud/resource_cluster_aws_expand_test.go new file mode 100644 index 00000000..3352a7f1 --- /dev/null +++ b/spectrocloud/resource_cluster_aws_expand_test.go @@ -0,0 +1,79 @@ +package spectrocloud + +import ( + "reflect" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/spectrocloud/hapi/models" + + "github.com/spectrocloud/terraform-provider-spectrocloud/types" +) + +func TestToMachinePoolAws(t *testing.T) { + testCases := []struct { + name string + input map[string]interface{} + vpcId string + expected *models.V1AwsMachinePoolConfigEntity + }{ + { + name: "Test 1: Basic test case", + input: map[string]interface{}{ + "control_plane": false, + "control_plane_as_worker": false, + "name": "testPool", + "count": 3, + "instance_type": "t2.micro", + "min": 1, + "max": 5, + "capacity_type": "on-demand", + "update_strategy": "RollingUpdateScaleOut", + "disk_size_gb": 65, + "azs": schema.NewSet(schema.HashString, []interface{}{"us-west-1a", "us-west-1b"}), + "additional_security_groups": schema.NewSet(schema.HashString, []interface{}{"sg-12345", "sg-67890"}), + }, + vpcId: "vpc-12345", + expected: &models.V1AwsMachinePoolConfigEntity{ + CloudConfig: &models.V1AwsMachinePoolCloudConfigEntity{ + Azs: []string{"us-west-1a", "us-west-1b"}, + InstanceType: types.Ptr("t2.micro"), + CapacityType: types.Ptr("on-demand"), + RootDeviceSize: int64(65), + Subnets: []*models.V1AwsSubnetEntity{}, // assuming no az_subnets provided + AdditionalSecurityGroups: []*models.V1AwsResourceReference{ + { + ID: "sg-12345", + }, + { + ID: "sg-67890", + }, + }, + }, + PoolConfig: &models.V1MachinePoolConfigEntity{ + AdditionalLabels: map[string]string{}, + IsControlPlane: false, + Labels: []string{}, + Name: types.Ptr("testPool"), + Size: types.Ptr(int32(3)), + UpdateStrategy: &models.V1UpdateStrategy{ + Type: "RollingUpdateScaleOut", + }, + MinSize: int32(1), + MaxSize: int32(5), + UseControlPlaneAsWorker: false, + }, + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + result, _ := toMachinePoolAws(tc.input, tc.vpcId) + if !reflect.DeepEqual(result, tc.expected) { + t.Errorf("Unexpected result (-want +got):\n%s", cmp.Diff(tc.expected, result)) + } + }) + } +} diff --git a/spectrocloud/resource_cluster_azure.go b/spectrocloud/resource_cluster_azure.go index f5d4ff00..5d44401e 100644 --- a/spectrocloud/resource_cluster_azure.go +++ b/spectrocloud/resource_cluster_azure.go @@ -2,15 +2,17 @@ package spectrocloud import ( "context" - "github.com/spectrocloud/terraform-provider-spectrocloud/spectrocloud/schemas" - "github.com/spectrocloud/terraform-provider-spectrocloud/types" "log" "strings" "time" + "github.com/spectrocloud/terraform-provider-spectrocloud/spectrocloud/schemas" + "github.com/spectrocloud/terraform-provider-spectrocloud/types" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/spectrocloud/hapi/models" + "github.com/spectrocloud/terraform-provider-spectrocloud/pkg/client" ) @@ -240,6 +242,12 @@ func resourceClusterAzure() *schema.Resource { Type: schema.TypeInt, Required: true, }, + "node_repave_interval": { + Type: schema.TypeInt, + Optional: true, + Default: 0, + Description: "Minimum number of seconds node should be Ready, before the next node is selected for repave. Default value is `0`, Applicable only for worker pools.", + }, "instance_type": { Type: schema.TypeString, Required: true, @@ -520,9 +528,9 @@ func flattenMachinePoolConfigsAzure(machinePools []*models.V1AzureMachinePoolCon for i, machinePool := range machinePools { oi := make(map[string]interface{}) - SetAdditionalLabelsAndTaints(machinePool.AdditionalLabels, machinePool.Taints, oi) + FlattenAdditionalLabelsAndTaints(machinePool.AdditionalLabels, machinePool.Taints, oi) + FlattenControlPlaneAndRepaveInterval(machinePool.IsControlPlane, oi, machinePool.NodeRepaveInterval) - oi["control_plane"] = machinePool.IsControlPlane oi["control_plane_as_worker"] = machinePool.UseControlPlaneAsWorker oi["name"] = machinePool.Name oi["count"] = machinePool.Size @@ -575,26 +583,32 @@ func resourceClusterAzureUpdate(ctx context.Context, d *schema.ResourceData, m i for _, mp := range ns.List() { machinePoolResource := mp.(map[string]interface{}) - name := machinePoolResource["name"].(string) - hash := resourceMachinePoolAzureHash(machinePoolResource) - - machinePool := toMachinePoolAzure(machinePoolResource) - - var err error - if oldMachinePool, ok := osMap[name]; !ok { - log.Printf("Create machine pool %s", name) - err = c.CreateMachinePoolAzure(cloudConfigId, machinePool) - } else if hash != resourceMachinePoolAzureHash(oldMachinePool) { - log.Printf("Change in machine pool %s", name) - err = c.UpdateMachinePoolAzure(cloudConfigId, machinePool) + // since known issue in TF SDK: https://github.com/hashicorp/terraform-plugin-sdk/issues/588 + if machinePoolResource["name"].(string) != "" { + name := machinePoolResource["name"].(string) + hash := resourceMachinePoolAzureHash(machinePoolResource) + var err error + machinePool, err := toMachinePoolAzure(machinePoolResource) + if err != nil { + diag.FromErr(err) + } + + if oldMachinePool, ok := osMap[name]; !ok { + log.Printf("Create machine pool %s", name) + err = c.CreateMachinePoolAzure(cloudConfigId, machinePool) + } else if hash != resourceMachinePoolAzureHash(oldMachinePool) { + log.Printf("Change in machine pool %s", name) + err = c.UpdateMachinePoolAzure(cloudConfigId, machinePool) + } + + if err != nil { + return diag.FromErr(err) + } + + // Processed (if exists) + delete(osMap, name) } - if err != nil { - return diag.FromErr(err) - } - - // Processed (if exists) - delete(osMap, name) } // Deleted old machine pools @@ -649,7 +663,10 @@ func toAzureCluster(c *client.V1Client, d *schema.ResourceData) *models.V1Spectr //for _, machinePool := range d.Get("machine_pool").([]interface{}) { machinePoolConfigs := make([]*models.V1AzureMachinePoolConfigEntity, 0) for _, machinePool := range d.Get("machine_pool").(*schema.Set).List() { - mp := toMachinePoolAzure(machinePool) + mp, err := toMachinePoolAzure(machinePool) + if err != nil { + return nil + } machinePoolConfigs = append(machinePoolConfigs, mp) } @@ -659,7 +676,7 @@ func toAzureCluster(c *client.V1Client, d *schema.ResourceData) *models.V1Spectr return cluster } -func toMachinePoolAzure(machinePool interface{}) *models.V1AzureMachinePoolConfigEntity { +func toMachinePoolAzure(machinePool interface{}) (*models.V1AzureMachinePoolConfigEntity, error) { m := machinePool.(map[string]interface{}) labels := make([]string, 0) @@ -720,5 +737,19 @@ func toMachinePoolAzure(machinePool interface{}) *models.V1AzureMachinePoolConfi UseControlPlaneAsWorker: controlPlaneAsWorker, }, } - return mp + + if !controlPlane { + nodeRepaveInterval := 0 + if m["node_repave_interval"] != nil { + nodeRepaveInterval = m["node_repave_interval"].(int) + } + mp.PoolConfig.NodeRepaveInterval = int32(nodeRepaveInterval) + } else { + err := ValidationNodeRepaveIntervalForControlPlane(m["node_repave_interval"].(int)) + if err != nil { + return mp, err + } + } + + return mp, nil } diff --git a/spectrocloud/resource_cluster_edge.go b/spectrocloud/resource_cluster_edge.go index 3665e532..30573fd3 100644 --- a/spectrocloud/resource_cluster_edge.go +++ b/spectrocloud/resource_cluster_edge.go @@ -2,16 +2,18 @@ package spectrocloud import ( "context" - "github.com/spectrocloud/terraform-provider-spectrocloud/spectrocloud/schemas" - "github.com/spectrocloud/terraform-provider-spectrocloud/types" "log" "sort" "strings" "time" + "github.com/spectrocloud/terraform-provider-spectrocloud/spectrocloud/schemas" + "github.com/spectrocloud/terraform-provider-spectrocloud/types" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/spectrocloud/hapi/models" + "github.com/spectrocloud/terraform-provider-spectrocloud/pkg/client" ) @@ -176,7 +178,7 @@ func resourceClusterEdge() *schema.Resource { "machine_pool": { Type: schema.TypeSet, Required: true, - Set: resourceMachinePoolEdgeHash, + Set: resourceMachinePoolEdgeNativeHash, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "name": { @@ -211,6 +213,12 @@ func resourceClusterEdge() *schema.Resource { }, }, }, + "node_repave_interval": { + Type: schema.TypeInt, + Optional: true, + Default: 0, + Description: "Minimum number of seconds node should be Ready, before the next node is selected for repave. Default value is `0`, Applicable only for worker pools.", + }, "control_plane": { Type: schema.TypeBool, Optional: true, @@ -391,7 +399,10 @@ func resourceClusterEdgeCreate(ctx context.Context, d *schema.ResourceData, m in // Warning or errors can be collected in a slice type var diags diag.Diagnostics - cluster := toEdgeCluster(c, d) + cluster, err := toEdgeCluster(c, d) + if err != nil { + return diag.FromErr(err) + } uid, err := c.CreateClusterEdge(cluster) if err != nil { @@ -457,8 +468,8 @@ func flattenMachinePoolConfigsEdge(machinePools []*models.V1EdgeMachinePoolConfi for _, machinePool := range machinePools { oi := make(map[string]interface{}) - SetAdditionalLabelsAndTaints(machinePool.AdditionalLabels, machinePool.Taints, oi) - + FlattenAdditionalLabelsAndTaints(machinePool.AdditionalLabels, machinePool.Taints, oi) + FlattenControlPlaneAndRepaveInterval(&machinePool.IsControlPlane, oi, machinePool.NodeRepaveInterval) oi["control_plane"] = machinePool.IsControlPlane oi["control_plane_as_worker"] = machinePool.UseControlPlaneAsWorker oi["name"] = machinePool.Name @@ -511,15 +522,19 @@ func resourceClusterEdgeUpdate(ctx context.Context, d *schema.ResourceData, m in if name == "" { continue } - hash := resourceMachinePoolEdgeHash(machinePoolResource) - - machinePool := toMachinePoolEdge(machinePoolResource) + hash := resourceMachinePoolEdgeNativeHash(machinePoolResource) var err error + + machinePool, err := toMachinePoolEdge(machinePoolResource) + if err != nil { + return diag.FromErr(err) + } + if oldMachinePool, ok := osMap[name]; !ok { log.Printf("Create machine pool %s", name) err = c.CreateMachinePoolEdge(cloudConfigId, machinePool) - } else if hash != resourceMachinePoolEdgeHash(oldMachinePool) { + } else if hash != resourceMachinePoolEdgeNativeHash(oldMachinePool) { log.Printf("Change in machine pool %s", name) err = c.UpdateMachinePoolEdge(cloudConfigId, machinePool) } @@ -553,7 +568,7 @@ func resourceClusterEdgeUpdate(ctx context.Context, d *schema.ResourceData, m in return diags } -func toEdgeCluster(c *client.V1Client, d *schema.ResourceData) *models.V1SpectroEdgeClusterEntity { +func toEdgeCluster(c *client.V1Client, d *schema.ResourceData) (*models.V1SpectroEdgeClusterEntity, error) { cloudConfig := d.Get("cloud_config").([]interface{})[0].(map[string]interface{}) cluster := &models.V1SpectroEdgeClusterEntity{ @@ -573,7 +588,10 @@ func toEdgeCluster(c *client.V1Client, d *schema.ResourceData) *models.V1Spectro machinePoolConfigs := make([]*models.V1EdgeMachinePoolConfigEntity, 0) for _, machinePool := range d.Get("machine_pool").(*schema.Set).List() { - mp := toMachinePoolEdge(machinePool) + mp, err := toMachinePoolEdge(machinePool) + if err != nil { + return nil, err + } machinePoolConfigs = append(machinePoolConfigs, mp) } @@ -585,10 +603,10 @@ func toEdgeCluster(c *client.V1Client, d *schema.ResourceData) *models.V1Spectro cluster.Spec.Machinepoolconfig = machinePoolConfigs cluster.Spec.ClusterConfig = toClusterConfig(d) - return cluster + return cluster, nil } -func toMachinePoolEdge(machinePool interface{}) *models.V1EdgeMachinePoolConfigEntity { +func toMachinePoolEdge(machinePool interface{}) (*models.V1EdgeMachinePoolConfigEntity, error) { m := machinePool.(map[string]interface{}) labels := make([]string, 0) @@ -625,5 +643,18 @@ func toMachinePoolEdge(machinePool interface{}) *models.V1EdgeMachinePoolConfigE UseControlPlaneAsWorker: controlPlaneAsWorker, }, } - return mp + if !controlPlane { + nodeRepaveInterval := 0 + if m["node_repave_interval"] != nil { + nodeRepaveInterval = m["node_repave_interval"].(int) + } + mp.PoolConfig.NodeRepaveInterval = int32(nodeRepaveInterval) + } else { + err := ValidationNodeRepaveIntervalForControlPlane(m["node_repave_interval"].(int)) + if err != nil { + return mp, err + } + } + + return mp, nil } diff --git a/spectrocloud/resource_cluster_edge_native.go b/spectrocloud/resource_cluster_edge_native.go index 5112582b..1eddcb7f 100644 --- a/spectrocloud/resource_cluster_edge_native.go +++ b/spectrocloud/resource_cluster_edge_native.go @@ -2,15 +2,17 @@ package spectrocloud import ( "context" - schemas "github.com/spectrocloud/terraform-provider-spectrocloud/spectrocloud/schemas" - "github.com/spectrocloud/terraform-provider-spectrocloud/types" "log" "strings" "time" + schemas "github.com/spectrocloud/terraform-provider-spectrocloud/spectrocloud/schemas" + "github.com/spectrocloud/terraform-provider-spectrocloud/types" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/spectrocloud/hapi/models" + "github.com/spectrocloud/terraform-provider-spectrocloud/pkg/client" ) @@ -240,6 +242,12 @@ func resourceClusterEdgeNative() *schema.Resource { }, }, }, + "node_repave_interval": { + Type: schema.TypeInt, + Optional: true, + Default: 0, + Description: "Minimum number of seconds node should be Ready, before the next node is selected for repave. Default value is `0`, Applicable only for worker pools.", + }, "control_plane": { Type: schema.TypeBool, Optional: true, @@ -484,8 +492,8 @@ func flattenMachinePoolConfigsEdgeNative(machinePools []*models.V1EdgeNativeMach for _, machinePool := range machinePools { oi := make(map[string]interface{}) - SetAdditionalLabelsAndTaints(machinePool.AdditionalLabels, machinePool.Taints, oi) - + FlattenAdditionalLabelsAndTaints(machinePool.AdditionalLabels, machinePool.Taints, oi) + FlattenControlPlaneAndRepaveInterval(&machinePool.IsControlPlane, oi, machinePool.NodeRepaveInterval) oi["control_plane"] = machinePool.IsControlPlane oi["control_plane_as_worker"] = machinePool.UseControlPlaneAsWorker oi["name"] = machinePool.Name @@ -536,9 +544,12 @@ func resourceClusterEdgeNativeUpdate(ctx context.Context, d *schema.ResourceData } hash := resourceMachinePoolEdgeNativeHash(machinePoolResource) - machinePool := toMachinePoolEdgeNative(machinePoolResource) - var err error + machinePool, err := toMachinePoolEdgeNative(machinePoolResource) + if err != nil { + return diag.FromErr(err) + } + if oldMachinePool, ok := osMap[name]; !ok { log.Printf("Create machine pool %s", name) err = c.CreateMachinePoolEdgeNative(cloudConfigId, machinePool) @@ -608,7 +619,10 @@ func toEdgeNativeCluster(c *client.V1Client, d *schema.ResourceData) (*models.V1 machinePoolConfigs := make([]*models.V1EdgeNativeMachinePoolConfigEntity, 0) for _, machinePool := range d.Get("machine_pool").(*schema.Set).List() { - mp := toMachinePoolEdgeNative(machinePool) + mp, err := toMachinePoolEdgeNative(machinePool) + if err != nil { + return nil, err + } machinePoolConfigs = append(machinePoolConfigs, mp) } cluster.Spec.Machinepoolconfig = machinePoolConfigs @@ -617,7 +631,7 @@ func toEdgeNativeCluster(c *client.V1Client, d *schema.ResourceData) (*models.V1 return cluster, nil } -func toMachinePoolEdgeNative(machinePool interface{}) *models.V1EdgeNativeMachinePoolConfigEntity { +func toMachinePoolEdgeNative(machinePool interface{}) (*models.V1EdgeNativeMachinePoolConfigEntity, error) { m := machinePool.(map[string]interface{}) labels := make([]string, 0) @@ -640,7 +654,19 @@ func toMachinePoolEdgeNative(machinePool interface{}) *models.V1EdgeNativeMachin UseControlPlaneAsWorker: controlPlaneAsWorker, }, } - return mp + if !controlPlane { + nodeRepaveInterval := 0 + if m["node_repave_interval"] != nil { + nodeRepaveInterval = m["node_repave_interval"].(int) + } + mp.PoolConfig.NodeRepaveInterval = int32(nodeRepaveInterval) + } else { + err := ValidationNodeRepaveIntervalForControlPlane(m["node_repave_interval"].(int)) + if err != nil { + return mp, err + } + } + return mp, nil } func toEdgeHosts(m map[string]interface{}) *models.V1EdgeNativeMachinePoolCloudConfigEntity { diff --git a/spectrocloud/resource_cluster_edge_vsphere.go b/spectrocloud/resource_cluster_edge_vsphere.go index 82011779..cbd29ab1 100644 --- a/spectrocloud/resource_cluster_edge_vsphere.go +++ b/spectrocloud/resource_cluster_edge_vsphere.go @@ -2,15 +2,17 @@ package spectrocloud import ( "context" - "github.com/spectrocloud/terraform-provider-spectrocloud/spectrocloud/schemas" - "github.com/spectrocloud/terraform-provider-spectrocloud/types" "log" "strings" "time" + "github.com/spectrocloud/terraform-provider-spectrocloud/spectrocloud/schemas" + "github.com/spectrocloud/terraform-provider-spectrocloud/types" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/spectrocloud/hapi/models" + "github.com/spectrocloud/terraform-provider-spectrocloud/pkg/client" ) @@ -224,7 +226,7 @@ func resourceClusterEdgeVsphere() *schema.Resource { Type: schema.TypeList, Required: true, // disable hash to preserve machine pool order PE-255 - //Set: resourceMachinePoolVsphereHash, + // Set: resourceMachinePoolVsphereHash, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "name": { @@ -272,6 +274,12 @@ func resourceClusterEdgeVsphere() *schema.Resource { Type: schema.TypeInt, Required: true, }, + "node_repave_interval": { + Type: schema.TypeInt, + Optional: true, + Default: 0, + Description: "Minimum number of seconds node should be Ready, before the next node is selected for repave. Default value is `0`, Applicable only for worker pools.", + }, "update_strategy": { Type: schema.TypeString, Optional: true, @@ -541,9 +549,9 @@ func flattenMachinePoolConfigsEdgeVsphere(machinePools []*models.V1VsphereMachin for _, machinePool := range machinePools { oi := make(map[string]interface{}) - SetAdditionalLabelsAndTaints(machinePool.AdditionalLabels, machinePool.Taints, oi) + FlattenAdditionalLabelsAndTaints(machinePool.AdditionalLabels, machinePool.Taints, oi) + FlattenControlPlaneAndRepaveInterval(machinePool.IsControlPlane, oi, machinePool.NodeRepaveInterval) - oi["control_plane"] = machinePool.IsControlPlane oi["control_plane_as_worker"] = machinePool.UseControlPlaneAsWorker oi["name"] = machinePool.Name oi["count"] = machinePool.Size @@ -589,7 +597,10 @@ func resourceClusterEdgeVsphereUpdate(ctx context.Context, d *schema.ResourceDat var diags diag.Diagnostics cloudConfigId := d.Get("cloud_config_id").(string) - + _, err := c.GetCloudConfigEdgeVsphere(cloudConfigId) + if err != nil { + return diag.FromErr(err) + } if d.HasChange("machine_pool") { oraw, nraw := d.GetChange("machine_pool") if oraw == nil { @@ -608,36 +619,44 @@ func resourceClusterEdgeVsphereUpdate(ctx context.Context, d *schema.ResourceDat osMap[machinePool["name"].(string)] = machinePool } + nsMap := make(map[string]interface{}) + for _, mp := range ns { machinePoolResource := mp.(map[string]interface{}) - name := machinePoolResource["name"].(string) - hash := resourceMachinePoolVsphereHash(machinePoolResource) - - machinePool := toMachinePoolEdgeVsphere(machinePoolResource) - - var err error - if oldMachinePool, ok := osMap[name]; !ok { - log.Printf("Create machine pool %s", name) - err = c.CreateMachinePoolVsphere(cloudConfigId, machinePool) - } else if hash != resourceMachinePoolVsphereHash(oldMachinePool) { - log.Printf("Change in machine pool %s", name) - oldMachinePool := toMachinePoolEdgeVsphere(oldMachinePool) - oldPlacements := oldMachinePool.CloudConfig.Placements - - for i, p := range machinePool.CloudConfig.Placements { - if len(oldPlacements) > i { - p.UID = oldPlacements[i].UID + nsMap[machinePoolResource["name"].(string)] = machinePoolResource + // since known issue in TF SDK: https://github.com/hashicorp/terraform-plugin-sdk/issues/588 + if machinePoolResource["name"].(string) != "" { + name := machinePoolResource["name"].(string) + hash := resourceMachinePoolVsphereHash(machinePoolResource) + var err error + machinePool, err := toMachinePoolEdgeVsphere(machinePoolResource) + if err != nil { + return diag.FromErr(err) + } + + if oldMachinePool, ok := osMap[name]; !ok { + log.Printf("Create machine pool %s", name) + err = c.CreateMachinePoolVsphere(cloudConfigId, machinePool) + } else if hash != resourceMachinePoolVsphereHash(oldMachinePool) { + log.Printf("Change in machine pool %s", name) + oldMachinePool, _ := toMachinePoolEdgeVsphere(oldMachinePool) + oldPlacements := oldMachinePool.CloudConfig.Placements + + for i, p := range machinePool.CloudConfig.Placements { + if len(oldPlacements) > i { + p.UID = oldPlacements[i].UID + } } + + err = c.UpdateMachinePoolVsphere(cloudConfigId, machinePool) } - err = c.UpdateMachinePoolVsphere(cloudConfigId, machinePool) - } + if err != nil { + return diag.FromErr(err) + } - if err != nil { - return diag.FromErr(err) + delete(osMap, name) } - - delete(osMap, name) } for _, mp := range osMap { @@ -689,7 +708,10 @@ func toEdgeVsphereCluster(c *client.V1Client, d *schema.ResourceData) *models.V1 machinePoolConfigs := make([]*models.V1VsphereMachinePoolConfigEntity, 0) for _, machinePool := range d.Get("machine_pool").([]interface{}) { - mp := toMachinePoolEdgeVsphere(machinePool) + mp, err := toMachinePoolEdgeVsphere(machinePool) + if err != nil { + return nil + } machinePoolConfigs = append(machinePoolConfigs, mp) } @@ -736,7 +758,7 @@ func getClusterConfigEntity(cloudConfig map[string]interface{}) *models.V1Vspher return clusterConfigEntity } -func toMachinePoolEdgeVsphere(machinePool interface{}) *models.V1VsphereMachinePoolConfigEntity { +func toMachinePoolEdgeVsphere(machinePool interface{}) (*models.V1VsphereMachinePoolConfigEntity, error) { m := machinePool.(map[string]interface{}) labels := make([]string, 0) @@ -794,5 +816,20 @@ func toMachinePoolEdgeVsphere(machinePool interface{}) *models.V1VsphereMachineP UseControlPlaneAsWorker: controlPlaneAsWorker, }, } - return mp + + if !controlPlane { + nodeRepaveInterval := 0 + if m["node_repave_interval"] != nil { + nodeRepaveInterval = m["node_repave_interval"].(int) + } + mp.PoolConfig.NodeRepaveInterval = int32(nodeRepaveInterval) + } else { + err := ValidationNodeRepaveIntervalForControlPlane(m["node_repave_interval"].(int)) + if err != nil { + return mp, err + } + + } + + return mp, nil } diff --git a/spectrocloud/resource_cluster_eks.go b/spectrocloud/resource_cluster_eks.go index 89a781e6..76c012e0 100644 --- a/spectrocloud/resource_cluster_eks.go +++ b/spectrocloud/resource_cluster_eks.go @@ -2,16 +2,18 @@ package spectrocloud import ( "context" - "github.com/spectrocloud/terraform-provider-spectrocloud/spectrocloud/schemas" - "github.com/spectrocloud/terraform-provider-spectrocloud/types" "log" "strings" "time" + "github.com/spectrocloud/terraform-provider-spectrocloud/spectrocloud/schemas" + "github.com/spectrocloud/terraform-provider-spectrocloud/types" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/spectrocloud/hapi/models" + "github.com/spectrocloud/terraform-provider-spectrocloud/pkg/client" ) @@ -643,7 +645,7 @@ func flattenMachinePoolConfigsEks(machinePools []*models.V1EksMachinePoolConfig) for _, machinePool := range machinePools { oi := make(map[string]interface{}) - SetAdditionalLabelsAndTaints(machinePool.AdditionalLabels, machinePool.Taints, oi) + FlattenAdditionalLabelsAndTaints(machinePool.AdditionalLabels, machinePool.Taints, oi) if *machinePool.IsControlPlane { continue @@ -1045,3 +1047,18 @@ func toFargateProfileEks(fargateProfile interface{}) *models.V1FargateProfile { return f } + +func setAdditionalSecurityGroups(eksLaunchTemplate map[string]interface{}) []*models.V1AwsResourceReference { + if eksLaunchTemplate["additional_security_groups"] != nil { + securityGroups := expandStringList(eksLaunchTemplate["additional_security_groups"].(*schema.Set).List()) + additionalSecurityGroups := make([]*models.V1AwsResourceReference, 0) + for _, securityGroup := range securityGroups { + additionalSecurityGroups = append(additionalSecurityGroups, &models.V1AwsResourceReference{ + ID: securityGroup, + }) + } + return additionalSecurityGroups + } + + return nil +} diff --git a/spectrocloud/resource_cluster_gcp.go b/spectrocloud/resource_cluster_gcp.go index a154713f..ff32a59b 100644 --- a/spectrocloud/resource_cluster_gcp.go +++ b/spectrocloud/resource_cluster_gcp.go @@ -2,15 +2,17 @@ package spectrocloud import ( "context" - "github.com/spectrocloud/terraform-provider-spectrocloud/spectrocloud/schemas" - "github.com/spectrocloud/terraform-provider-spectrocloud/types" "log" "strings" "time" + "github.com/spectrocloud/terraform-provider-spectrocloud/spectrocloud/schemas" + "github.com/spectrocloud/terraform-provider-spectrocloud/types" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/spectrocloud/hapi/models" + "github.com/spectrocloud/terraform-provider-spectrocloud/pkg/client" ) @@ -236,6 +238,12 @@ func resourceClusterGcp() *schema.Resource { Type: schema.TypeInt, Required: true, }, + "node_repave_interval": { + Type: schema.TypeInt, + Optional: true, + Default: 0, + Description: "Minimum number of seconds node should be Ready, before the next node is selected for repave. Default value is `0`, Applicable only for worker pools.", + }, "instance_type": { Type: schema.TypeString, Required: true, @@ -473,9 +481,9 @@ func flattenMachinePoolConfigsGcp(machinePools []*models.V1GcpMachinePoolConfig) for i, machinePool := range machinePools { oi := make(map[string]interface{}) - SetAdditionalLabelsAndTaints(machinePool.AdditionalLabels, machinePool.Taints, oi) + FlattenAdditionalLabelsAndTaints(machinePool.AdditionalLabels, machinePool.Taints, oi) + FlattenControlPlaneAndRepaveInterval(machinePool.IsControlPlane, oi, machinePool.NodeRepaveInterval) - oi["control_plane"] = machinePool.IsControlPlane oi["control_plane_as_worker"] = machinePool.UseControlPlaneAsWorker oi["name"] = machinePool.Name oi["count"] = int(machinePool.Size) @@ -486,7 +494,6 @@ func flattenMachinePoolConfigsGcp(machinePools []*models.V1GcpMachinePoolConfig) oi["disk_size_gb"] = int(machinePool.RootDeviceSize) oi["azs"] = machinePool.Azs - ois[i] = oi } @@ -521,26 +528,32 @@ func resourceClusterGcpUpdate(ctx context.Context, d *schema.ResourceData, m int for _, mp := range ns.List() { machinePoolResource := mp.(map[string]interface{}) - name := machinePoolResource["name"].(string) - hash := resourceMachinePoolGcpHash(machinePoolResource) - - machinePool := toMachinePoolGcp(machinePoolResource) - - var err error - if oldMachinePool, ok := osMap[name]; !ok { - log.Printf("Create machine pool %s", name) - err = c.CreateMachinePoolGcp(cloudConfigId, machinePool) - } else if hash != resourceMachinePoolGcpHash(oldMachinePool) { - log.Printf("Change in machine pool %s", name) - err = c.UpdateMachinePoolGcp(cloudConfigId, machinePool) - } - - if err != nil { - return diag.FromErr(err) + // since known issue in TF SDK: https://github.com/hashicorp/terraform-plugin-sdk/issues/588 + if machinePoolResource["name"].(string) != "" { + name := machinePoolResource["name"].(string) + hash := resourceMachinePoolGcpHash(machinePoolResource) + var err error + machinePool, err := toMachinePoolGcp(machinePoolResource) + if err != nil { + return diag.FromErr(err) + } + + if oldMachinePool, ok := osMap[name]; !ok { + log.Printf("Create machine pool %s", name) + err = c.CreateMachinePoolGcp(cloudConfigId, machinePool) + } else if hash != resourceMachinePoolGcpHash(oldMachinePool) { + log.Printf("Change in machine pool %s", name) + err = c.UpdateMachinePoolGcp(cloudConfigId, machinePool) + } + + if err != nil { + return diag.FromErr(err) + } + + // Processed (if exists) + delete(osMap, name) } - // Processed (if exists) - delete(osMap, name) } // Deleted old machine pools @@ -593,7 +606,10 @@ func toGcpCluster(c *client.V1Client, d *schema.ResourceData) *models.V1SpectroG machinePoolConfigs := make([]*models.V1GcpMachinePoolConfigEntity, 0) for _, machinePool := range d.Get("machine_pool").(*schema.Set).List() { - mp := toMachinePoolGcp(machinePool) + mp, err := toMachinePoolGcp(machinePool) + if err != nil { + return nil + } machinePoolConfigs = append(machinePoolConfigs, mp) } @@ -603,7 +619,7 @@ func toGcpCluster(c *client.V1Client, d *schema.ResourceData) *models.V1SpectroG return cluster } -func toMachinePoolGcp(machinePool interface{}) *models.V1GcpMachinePoolConfigEntity { +func toMachinePoolGcp(machinePool interface{}) (*models.V1GcpMachinePoolConfigEntity, error) { m := machinePool.(map[string]interface{}) labels := make([]string, 0) @@ -637,5 +653,19 @@ func toMachinePoolGcp(machinePool interface{}) *models.V1GcpMachinePoolConfigEnt UseControlPlaneAsWorker: controlPlaneAsWorker, }, } - return mp + + if !controlPlane { + nodeRepaveInterval := 0 + if m["node_repave_interval"] != nil { + nodeRepaveInterval = m["node_repave_interval"].(int) + } + mp.PoolConfig.NodeRepaveInterval = int32(nodeRepaveInterval) + } else { + err := ValidationNodeRepaveIntervalForControlPlane(m["node_repave_interval"].(int)) + if err != nil { + return mp, err + } + } + + return mp, nil } diff --git a/spectrocloud/resource_cluster_libvirt.go b/spectrocloud/resource_cluster_libvirt.go index 3933df96..04c60fc8 100644 --- a/spectrocloud/resource_cluster_libvirt.go +++ b/spectrocloud/resource_cluster_libvirt.go @@ -279,6 +279,12 @@ func resourceClusterLibvirt() *schema.Resource { Type: schema.TypeInt, Required: true, }, + "node_repave_interval": { + Type: schema.TypeInt, + Optional: true, + Default: 0, + Description: "Minimum number of seconds node should be Ready, before the next node is selected for repave. Default value is `0`, Applicable only for worker pools.", + }, "update_strategy": { Type: schema.TypeString, Optional: true, @@ -642,9 +648,9 @@ func flattenMachinePoolConfigsLibvirt(machinePools []*models.V1LibvirtMachinePoo for _, machinePool := range machinePools { oi := make(map[string]interface{}) - SetAdditionalLabelsAndTaints(machinePool.AdditionalLabels, machinePool.Taints, oi) + FlattenAdditionalLabelsAndTaints(machinePool.AdditionalLabels, machinePool.Taints, oi) + FlattenControlPlaneAndRepaveInterval(&machinePool.IsControlPlane, oi, machinePool.NodeRepaveInterval) - oi["control_plane"] = machinePool.IsControlPlane oi["control_plane_as_worker"] = machinePool.UseControlPlaneAsWorker oi["name"] = machinePool.Name oi["count"] = machinePool.Size @@ -954,6 +960,21 @@ func toMachinePoolLibvirt(machinePool interface{}) (*models.V1LibvirtMachinePool UseControlPlaneAsWorker: controlPlaneAsWorker, }, } + + if !controlPlane { + nodeRepaveInterval := 0 + if m["node_repave_interval"] != nil { + nodeRepaveInterval = m["node_repave_interval"].(int) + } + mp.PoolConfig.NodeRepaveInterval = int32(nodeRepaveInterval) + } else { + err := ValidationNodeRepaveIntervalForControlPlane(m["node_repave_interval"].(int)) + if err != nil { + return mp, err + } + + } + return mp, nil } diff --git a/spectrocloud/resource_cluster_maas.go b/spectrocloud/resource_cluster_maas.go index 597efec3..99f55011 100644 --- a/spectrocloud/resource_cluster_maas.go +++ b/spectrocloud/resource_cluster_maas.go @@ -2,15 +2,17 @@ package spectrocloud import ( "context" - "github.com/spectrocloud/terraform-provider-spectrocloud/spectrocloud/schemas" - "github.com/spectrocloud/terraform-provider-spectrocloud/types" "log" "strings" "time" + "github.com/spectrocloud/terraform-provider-spectrocloud/spectrocloud/schemas" + "github.com/spectrocloud/terraform-provider-spectrocloud/types" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/spectrocloud/hapi/models" + "github.com/spectrocloud/terraform-provider-spectrocloud/pkg/client" ) @@ -224,8 +226,25 @@ func resourceClusterMaas() *schema.Resource { //ForceNew: true, }, "count": { - Type: schema.TypeInt, - Required: true, + Type: schema.TypeInt, + Required: true, + Description: "Number of nodes in the machine pool.", + }, + "node_repave_interval": { + Type: schema.TypeInt, + Optional: true, + Default: 0, + Description: "Minimum number of seconds node should be Ready, before the next node is selected for repave. Default value is `0`, Applicable only for worker pools.", + }, + "min": { + Type: schema.TypeInt, + Optional: true, + Description: "Minimum number of nodes in the machine pool. This is used for autoscaling the machine pool.", + }, + "max": { + Type: schema.TypeInt, + Optional: true, + Description: "Maximum number of nodes in the machine pool. This is used for autoscaling the machine pool.", }, "instance_type": { Type: schema.TypeList, @@ -489,9 +508,9 @@ func flattenMachinePoolConfigsMaas(machinePools []*models.V1MaasMachinePoolConfi for i, machinePool := range machinePools { oi := make(map[string]interface{}) - SetAdditionalLabelsAndTaints(machinePool.AdditionalLabels, machinePool.Taints, oi) + FlattenAdditionalLabelsAndTaints(machinePool.AdditionalLabels, machinePool.Taints, oi) + FlattenControlPlaneAndRepaveInterval(&machinePool.IsControlPlane, oi, machinePool.NodeRepaveInterval) - oi["control_plane"] = machinePool.IsControlPlane oi["control_plane_as_worker"] = machinePool.UseControlPlaneAsWorker oi["name"] = machinePool.Name oi["count"] = int(machinePool.Size) @@ -522,7 +541,10 @@ func resourceClusterMaasUpdate(ctx context.Context, d *schema.ResourceData, m in var diags diag.Diagnostics cloudConfigId := d.Get("cloud_config_id").(string) - + _, err := c.GetCloudConfigMaas(cloudConfigId) + if err != nil { + return diag.FromErr(err) + } if d.HasChange("machine_pool") { oraw, nraw := d.GetChange("machine_pool") if oraw == nil { @@ -541,28 +563,38 @@ func resourceClusterMaasUpdate(ctx context.Context, d *schema.ResourceData, m in osMap[machinePool["name"].(string)] = machinePool } + nsMap := make(map[string]interface{}) + for _, mp := range ns.List() { machinePoolResource := mp.(map[string]interface{}) - name := machinePoolResource["name"].(string) - hash := resourceMachinePoolMaasHash(machinePoolResource) - - machinePool := toMachinePoolMaas(machinePoolResource) - - var err error - if oldMachinePool, ok := osMap[name]; !ok { - log.Printf("Create machine pool %s", name) - err = c.CreateMachinePoolMaas(cloudConfigId, machinePool) - } else if hash != resourceMachinePoolMaasHash(oldMachinePool) { - log.Printf("Change in machine pool %s", name) - err = c.UpdateMachinePoolMaas(cloudConfigId, machinePool) - } - - if err != nil { - return diag.FromErr(err) + nsMap[machinePoolResource["name"].(string)] = machinePoolResource + // since known issue in TF SDK: https://github.com/hashicorp/terraform-plugin-sdk/issues/588 + if machinePoolResource["name"].(string) != "" { + name := machinePoolResource["name"].(string) + hash := resourceMachinePoolMaasHash(machinePoolResource) + + var err error + machinePool, err := toMachinePoolMaas(machinePoolResource) + if err != nil { + return diag.FromErr(err) + } + + if oldMachinePool, ok := osMap[name]; !ok { + log.Printf("Create machine pool %s", name) + err = c.CreateMachinePoolMaas(cloudConfigId, machinePool) + } else if hash != resourceMachinePoolMaasHash(oldMachinePool) { + log.Printf("Change in machine pool %s", name) + err = c.UpdateMachinePoolMaas(cloudConfigId, machinePool) + } + + if err != nil { + return diag.FromErr(err) + } + + // Processed (if exists) + delete(osMap, name) } - // Processed (if exists) - delete(osMap, name) } // Deleted old machine pools @@ -575,10 +607,6 @@ func resourceClusterMaasUpdate(ctx context.Context, d *schema.ResourceData, m in } } } - //TODO(saamalik) update for cluster as well - //if err := waitForClusterU(ctx, c, d.Id(), d.Timeout(schema.TimeoutDelete)); err != nil { - // return diag.FromErr(err) - //} diagnostics, done := updateCommonFields(d, c) if done { @@ -614,7 +642,10 @@ func toMaasCluster(c *client.V1Client, d *schema.ResourceData) *models.V1Spectro //for _, machinePool := range d.Get("machine_pool").([]interface{}) { machinePoolConfigs := make([]*models.V1MaasMachinePoolConfigEntity, 0) for _, machinePool := range d.Get("machine_pool").(*schema.Set).List() { - mp := toMachinePoolMaas(machinePool) + mp, err := toMachinePoolMaas(machinePool) + if err != nil { + return nil + } machinePoolConfigs = append(machinePoolConfigs, mp) } @@ -624,7 +655,7 @@ func toMaasCluster(c *client.V1Client, d *schema.ResourceData) *models.V1Spectro return cluster } -func toMachinePoolMaas(machinePool interface{}) *models.V1MaasMachinePoolConfigEntity { +func toMachinePoolMaas(machinePool interface{}) (*models.V1MaasMachinePoolConfigEntity, error) { m := machinePool.(map[string]interface{}) labels := make([]string, 0) @@ -664,5 +695,19 @@ func toMachinePoolMaas(machinePool interface{}) *models.V1MaasMachinePoolConfigE UseControlPlaneAsWorker: controlPlaneAsWorker, }, } - return mp + + if !controlPlane { + nodeRepaveInterval := 0 + if m["node_repave_interval"] != nil { + nodeRepaveInterval = m["node_repave_interval"].(int) + } + mp.PoolConfig.NodeRepaveInterval = int32(nodeRepaveInterval) + } else { + err := ValidationNodeRepaveIntervalForControlPlane(m["node_repave_interval"].(int)) + if err != nil { + return mp, err + } + } + + return mp, nil } diff --git a/spectrocloud/resource_cluster_openstack.go b/spectrocloud/resource_cluster_openstack.go index f4db3313..4348daf8 100644 --- a/spectrocloud/resource_cluster_openstack.go +++ b/spectrocloud/resource_cluster_openstack.go @@ -2,16 +2,18 @@ package spectrocloud import ( "context" - "github.com/spectrocloud/terraform-provider-spectrocloud/spectrocloud/schemas" - "github.com/spectrocloud/terraform-provider-spectrocloud/types" "log" "sort" "strings" "time" + "github.com/spectrocloud/terraform-provider-spectrocloud/spectrocloud/schemas" + "github.com/spectrocloud/terraform-provider-spectrocloud/types" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/spectrocloud/hapi/models" + "github.com/spectrocloud/terraform-provider-spectrocloud/pkg/client" ) @@ -256,6 +258,12 @@ func resourceClusterOpenStack() *schema.Resource { Type: schema.TypeInt, Required: true, }, + "node_repave_interval": { + Type: schema.TypeInt, + Optional: true, + Default: 0, + Description: "Minimum number of seconds node should be Ready, before the next node is selected for repave. Default value is `0`, Applicable only for worker pools.", + }, "update_strategy": { Type: schema.TypeString, Optional: true, @@ -485,7 +493,10 @@ func toOpenStackCluster(c *client.V1Client, d *schema.ResourceData) *models.V1Sp machinePoolConfigs := make([]*models.V1OpenStackMachinePoolConfigEntity, 0) for _, machinePool := range d.Get("machine_pool").([]interface{}) { - mp := toMachinePoolOpenStack(machinePool) + mp, err := toMachinePoolOpenStack(machinePool) + if err != nil { + return nil + } machinePoolConfigs = append(machinePoolConfigs, mp) } @@ -549,9 +560,9 @@ func flattenMachinePoolConfigsOpenStack(machinePools []*models.V1OpenStackMachin for _, machinePool := range machinePools { oi := make(map[string]interface{}) - SetAdditionalLabelsAndTaints(machinePool.AdditionalLabels, machinePool.Taints, oi) + FlattenAdditionalLabelsAndTaints(machinePool.AdditionalLabels, machinePool.Taints, oi) + FlattenControlPlaneAndRepaveInterval(&machinePool.IsControlPlane, oi, machinePool.NodeRepaveInterval) - oi["control_plane"] = machinePool.IsControlPlane oi["control_plane_as_worker"] = machinePool.UseControlPlaneAsWorker oi["name"] = machinePool.Name oi["count"] = int(machinePool.Size) @@ -574,7 +585,10 @@ func resourceClusterOpenStackUpdate(ctx context.Context, d *schema.ResourceData, var diags diag.Diagnostics cloudConfigId := d.Get("cloud_config_id").(string) - + _, err := c.GetCloudConfigOpenStack(cloudConfigId) + if err != nil { + return diag.FromErr(err) + } if d.HasChange("machine_pool") { oraw, nraw := d.GetChange("machine_pool") if oraw == nil { @@ -592,29 +606,36 @@ func resourceClusterOpenStackUpdate(ctx context.Context, d *schema.ResourceData, machinePool := mp.(map[string]interface{}) osMap[machinePool["name"].(string)] = machinePool } - + nsMap := make(map[string]interface{}) for _, mp := range ns { machinePoolResource := mp.(map[string]interface{}) - name := machinePoolResource["name"].(string) - hash := resourceMachinePoolOpenStackHash(machinePoolResource) - - machinePool := toMachinePoolOpenStack(machinePoolResource) - - var err error - if oldMachinePool, ok := osMap[name]; !ok { - log.Printf("Create machine pool %s", name) - err = c.CreateMachinePoolOpenStack(cloudConfigId, machinePool) - } else if hash != resourceMachinePoolOpenStackHash(oldMachinePool) { - log.Printf("Change in machine pool %s", name) - err = c.UpdateMachinePoolOpenStack(cloudConfigId, machinePool) - } - - if err != nil { - return diag.FromErr(err) + nsMap[machinePoolResource["name"].(string)] = machinePoolResource + // since known issue in TF SDK: https://github.com/hashicorp/terraform-plugin-sdk/issues/588 + if machinePoolResource["name"].(string) != "" { + name := machinePoolResource["name"].(string) + hash := resourceMachinePoolOpenStackHash(machinePoolResource) + + var err error + machinePool, err := toMachinePoolOpenStack(machinePoolResource) + if err != nil { + return diag.FromErr(err) + } + + if oldMachinePool, ok := osMap[name]; !ok { + log.Printf("Create machine pool %s", name) + err = c.CreateMachinePoolOpenStack(cloudConfigId, machinePool) + } else if hash != resourceMachinePoolOpenStackHash(oldMachinePool) { + log.Printf("Change in machine pool %s", name) + err = c.UpdateMachinePoolOpenStack(cloudConfigId, machinePool) + } + + if err != nil { + return diag.FromErr(err) + } + + // Processed (if exists) + delete(osMap, name) } - - // Processed (if exists) - delete(osMap, name) } // Deleted old machine pools @@ -638,7 +659,7 @@ func resourceClusterOpenStackUpdate(ctx context.Context, d *schema.ResourceData, return diags } -func toMachinePoolOpenStack(machinePool interface{}) *models.V1OpenStackMachinePoolConfigEntity { +func toMachinePoolOpenStack(machinePool interface{}) (*models.V1OpenStackMachinePoolConfigEntity, error) { m := machinePool.(map[string]interface{}) labels := make([]string, 0) @@ -676,5 +697,19 @@ func toMachinePoolOpenStack(machinePool interface{}) *models.V1OpenStackMachineP UseControlPlaneAsWorker: controlPlaneAsWorker, }, } - return mp + + if !controlPlane { + nodeRepaveInterval := 0 + if m["node_repave_interval"] != nil { + nodeRepaveInterval = m["node_repave_interval"].(int) + } + mp.PoolConfig.NodeRepaveInterval = int32(nodeRepaveInterval) + } else { + err := ValidationNodeRepaveIntervalForControlPlane(m["node_repave_interval"].(int)) + if err != nil { + return mp, err + } + } + + return mp, nil } diff --git a/spectrocloud/resource_cluster_tke.go b/spectrocloud/resource_cluster_tke.go index 9c81eb4b..38e34010 100644 --- a/spectrocloud/resource_cluster_tke.go +++ b/spectrocloud/resource_cluster_tke.go @@ -494,7 +494,7 @@ func flattenMachinePoolConfigsTke(machinePools []*models.V1TencentMachinePoolCon for _, machinePool := range machinePools { oi := make(map[string]interface{}) - SetAdditionalLabelsAndTaints(machinePool.AdditionalLabels, machinePool.Taints, oi) + FlattenAdditionalLabelsAndTaints(machinePool.AdditionalLabels, machinePool.Taints, oi) if machinePool.IsControlPlane { continue diff --git a/spectrocloud/resource_cluster_vsphere.go b/spectrocloud/resource_cluster_vsphere.go index e4fc15a6..06818fee 100644 --- a/spectrocloud/resource_cluster_vsphere.go +++ b/spectrocloud/resource_cluster_vsphere.go @@ -2,16 +2,18 @@ package spectrocloud import ( "context" - "github.com/spectrocloud/terraform-provider-spectrocloud/spectrocloud/schemas" - "github.com/spectrocloud/terraform-provider-spectrocloud/types" "log" "sort" "strings" "time" + "github.com/spectrocloud/terraform-provider-spectrocloud/spectrocloud/schemas" + "github.com/spectrocloud/terraform-provider-spectrocloud/types" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/spectrocloud/hapi/models" + "github.com/spectrocloud/terraform-provider-spectrocloud/pkg/client" ) @@ -258,6 +260,12 @@ func resourceClusterVsphere() *schema.Resource { //ForceNew: true, }, + "node_repave_interval": { + Type: schema.TypeInt, + Optional: true, + Default: 0, + Description: "Minimum number of seconds node should be Ready, before the next node is selected for repave. Default value is `0`, Applicable only for worker pools.", + }, "count": { Type: schema.TypeInt, Required: true, @@ -584,9 +592,9 @@ func flattenMachinePoolConfigsVsphere(machinePools []*models.V1VsphereMachinePoo for i, machinePool := range machinePools { oi := make(map[string]interface{}) - SetAdditionalLabelsAndTaints(machinePool.AdditionalLabels, machinePool.Taints, oi) + FlattenAdditionalLabelsAndTaints(machinePool.AdditionalLabels, machinePool.Taints, oi) + FlattenControlPlaneAndRepaveInterval(machinePool.IsControlPlane, oi, machinePool.NodeRepaveInterval) - oi["control_plane"] = machinePool.IsControlPlane oi["control_plane_as_worker"] = machinePool.UseControlPlaneAsWorker oi["name"] = machinePool.Name oi["count"] = machinePool.Size @@ -661,16 +669,18 @@ func resourceClusterVsphereUpdate(ctx context.Context, d *schema.ResourceData, m machinePoolResource := mp.(map[string]interface{}) name := machinePoolResource["name"].(string) hash := resourceMachinePoolVsphereHash(machinePoolResource) - - machinePool := toMachinePoolVsphere(machinePoolResource) - var err error + machinePool, err := toMachinePoolVsphere(machinePoolResource) + if err != nil { + return diag.FromErr(err) + } + if oldMachinePool, ok := osMap[name]; !ok { log.Printf("Create machine pool %s", name) err = c.CreateMachinePoolVsphere(cloudConfigId, machinePool) } else if hash != resourceMachinePoolVsphereHash(oldMachinePool) { log.Printf("Change in machine pool %s", name) - oldMachinePool := toMachinePoolVsphere(oldMachinePool) + oldMachinePool, _ := toMachinePoolVsphere(oldMachinePool) oldPlacements := oldMachinePool.CloudConfig.Placements // set the placement ids @@ -737,7 +747,10 @@ func toVsphereCluster(c *client.V1Client, d *schema.ResourceData) *models.V1Spec machinePoolConfigs := make([]*models.V1VsphereMachinePoolConfigEntity, 0) for _, machinePool := range d.Get("machine_pool").(*schema.Set).List() { - mp := toMachinePoolVsphere(machinePool) + mp, err := toMachinePoolVsphere(machinePool) + if err != nil { + return nil + } machinePoolConfigs = append(machinePoolConfigs, mp) } @@ -773,7 +786,7 @@ func toCloudConfigUpdate(cloudConfig map[string]interface{}) *models.V1VsphereCl } } -func toMachinePoolVsphere(machinePool interface{}) *models.V1VsphereMachinePoolConfigEntity { +func toMachinePoolVsphere(machinePool interface{}) (*models.V1VsphereMachinePoolConfigEntity, error) { m := machinePool.(map[string]interface{}) labels := make([]string, 0) @@ -831,5 +844,19 @@ func toMachinePoolVsphere(machinePool interface{}) *models.V1VsphereMachinePoolC UseControlPlaneAsWorker: controlPlaneAsWorker, }, } - return mp + + if !controlPlane { + nodeRepaveInterval := 0 + if m["node_repave_interval"] != nil { + nodeRepaveInterval = m["node_repave_interval"].(int) + } + mp.PoolConfig.NodeRepaveInterval = int32(nodeRepaveInterval) + } else { + err := ValidationNodeRepaveIntervalForControlPlane(m["node_repave_interval"].(int)) + if err != nil { + return mp, err + } + } + + return mp, nil } diff --git a/templates/index.md.tmpl b/templates/index.md.tmpl index 56c4df61..0f544b85 100644 --- a/templates/index.md.tmpl +++ b/templates/index.md.tmpl @@ -33,7 +33,7 @@ Copy `terraform.template.tfvars` file to a `terraform.tfvars` file and modify it {{tffile "examples/provider/terraform.template.tfvars"}} -> -Be sure to populate the `username`, `password`, and other terraform vars. +Be sure to populate the `sc_host`, `sc_api_key`, and other terraform vars. Copy one of the resource configuration files (e.g: spectrocloud_cluster_profile) from the _Resources_ documentation. Be sure to specify all required parameters. @@ -51,28 +51,14 @@ For an end-to-end example of provisioning Spectro Cloud resources, visit: Credentials and other configurations can be provided through environment variables. The following environment variables are availabe. -- `SPECTROCLOUD_HOST` -- `SPECTROCLOUD_USERNAME` -- `SPECTROCLOUD_PASSWORD` +- `SPECTROCLOUD_HOST` - `SPECTROCLOUD_APIKEY` - `SPECTROCLOUD_TRACE` - `SPECTROCLOUD_RETRY_ATTEMPTS` ## Authentication -You can use the environment variables to authenticate with Spectro Cloud with your username and password. - --> **Note:** The API key takes precendence over the username and password authentication flow. - -```shell -export SPECTROCLOUD_USERNAME=myUserName -export SPECTROCLOUD_PASSWORD=myPassword -``` -```hcl -provider "spectrocloud" {} -``` - -Alternatively, you may use an API key to authenticate with Spectro Cloud. Visit the User Management API Key [documentation](https://docs.spectrocloud.com/user-management/user-authentication/#usingapikey) to learn more about Spectro Cloud API keys. +You can use an API key to authenticate with Spectro Cloud. Visit the User Management API Key [documentation](https://docs.spectrocloud.com/user-management/user-authentication/#usingapikey) to learn more about Spectro Cloud API keys. ```shell export SPECTROCLOUD_APIKEY=5b7aad......... ```