From 4086375236ee3a1f4fb29f03b7143051d9b09161 Mon Sep 17 00:00:00 2001 From: Daniel Isen <54864769+daniel-yb@users.noreply.github.com> Date: Mon, 9 Dec 2024 19:16:40 -0500 Subject: [PATCH] [CLOUDGA-25006] Deprecate root node info (#143) --- .gitignore | 4 + docs/data-sources/cluster.md | 2 +- docs/resources/cluster.md | 25 ++- go.mod | 60 +++++- go.sum | 130 +++++++++++++ managed/data_source_cluster_name.go | 1 + managed/models.go | 2 +- managed/resource_cluster.go | 286 ++++++++++++++++------------ samples/cluster-multi-region.tf | 7 +- samples/cluster-single-region.tf | 40 ++-- 10 files changed, 379 insertions(+), 178 deletions(-) diff --git a/.gitignore b/.gitignore index a4bc69a..57c7733 100644 --- a/.gitignore +++ b/.gitignore @@ -66,3 +66,7 @@ terraform # Ignore Intellij files. .idea/ + +terraform-provider-ybm + +samples/.terraform.lock.hcl diff --git a/docs/data-sources/cluster.md b/docs/data-sources/cluster.md index 9729cd1..ac3c403 100644 --- a/docs/data-sources/cluster.md +++ b/docs/data-sources/cluster.md @@ -47,7 +47,7 @@ data "ybm_cluster" "example_cluster" { - `desired_state` (String) The desired state of the database, Active or Paused. This parameter can be used to pause/resume a cluster. - `endpoints` (Attributes List) The endpoints used to connect to the cluster. (see [below for nested schema](#nestedatt--endpoints)) - `fault_tolerance` (String) The fault tolerance of the cluster. -- `node_config` (Attributes) (see [below for nested schema](#nestedatt--node_config)) +- `node_config` (Attributes, Deprecated) (see [below for nested schema](#nestedatt--node_config)) - `num_faults_to_tolerate` (Number) The number of domain faults the cluster can tolerate. - `project_id` (String) The ID of the project this cluster belongs to. - `restore_backup_id` (String) The ID of the backup to be restored to the cluster. diff --git a/docs/resources/cluster.md b/docs/resources/cluster.md index 18d86b2..5c6e7ba 100644 --- a/docs/resources/cluster.md +++ b/docs/resources/cluster.md @@ -608,7 +608,6 @@ resource "ybm_private_service_endpoint" "npsenonok-region" { - `credentials` (Attributes) Credentials to be used by the database. Please provide 'username' and 'password' (which would be used in common for both YSQL and YCQL) OR all of 'ysql_username', 'ysql_password', 'ycql_username' and 'ycql_password' but not a mix of both. (see [below for nested schema](#nestedatt--credentials)) -- `node_config` (Attributes) (see [below for nested schema](#nestedatt--node_config)) ### Optional @@ -619,6 +618,7 @@ resource "ybm_private_service_endpoint" "npsenonok-region" { - `database_track` (String) The track of the database. Production or Innovation or Preview. - `desired_state` (String) The desired state of the database, Active or Paused. This parameter can be used to pause/resume a cluster. - `fault_tolerance` (String) The fault tolerance of the cluster. NONE, NODE, ZONE or REGION. +- `node_config` (Attributes, Deprecated) (see [below for nested schema](#nestedatt--node_config)) - `num_faults_to_tolerate` (Number) The number of domain faults the cluster can tolerate. 0 for NONE, 1 for ZONE and [1-3] for NODE and REGION - `restore_backup_id` (String) The ID of the backup to be restored to the cluster. @@ -666,19 +666,6 @@ Optional: - `ysql_username` (String) YSQL username for the database. - -### Nested Schema for `node_config` - -Required: - -- `num_cores` (Number) Number of CPU cores in the node. - -Optional: - -- `disk_iops` (Number) Disk IOPS of the node. -- `disk_size_gb` (Number) Disk size of the node. - - ### Nested Schema for `backup_schedules` @@ -763,6 +750,16 @@ Optional: + +### Nested Schema for `node_config` + +Optional: + +- `disk_iops` (Number) Disk IOPS of the node. +- `disk_size_gb` (Number) Disk size of the node. +- `num_cores` (Number) Number of CPU cores in the node. + + ### Nested Schema for `cluster_info` diff --git a/go.mod b/go.mod index ca3e4e7..21715fd 100644 --- a/go.mod +++ b/go.mod @@ -12,29 +12,71 @@ require ( ) require ( - github.com/fatih/color v1.13.0 // indirect + github.com/BurntSushi/toml v1.2.1 // indirect + github.com/Kunde21/markdownfmt/v3 v3.1.0 // indirect + github.com/Masterminds/goutils v1.1.1 // indirect + github.com/Masterminds/semver/v3 v3.2.0 // indirect + github.com/Masterminds/sprig/v3 v3.2.3 // indirect + github.com/ProtonMail/go-crypto v1.1.0-alpha.2 // indirect + github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect + github.com/armon/go-radix v1.0.0 // indirect + github.com/bgentry/speakeasy v0.1.0 // indirect + github.com/bmatcuk/doublestar/v4 v4.7.1 // indirect + github.com/cloudflare/circl v1.3.7 // indirect + github.com/google/uuid v1.3.0 // indirect + github.com/hashicorp/cli v1.1.6 // 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-multierror v1.1.1 // indirect + github.com/hashicorp/go-retryablehttp v0.7.7 // indirect + github.com/hashicorp/go-version v1.7.0 // indirect + github.com/hashicorp/hc-install v0.9.0 // indirect + github.com/hashicorp/terraform-exec v0.21.0 // indirect + github.com/hashicorp/terraform-json v0.23.0 // indirect + github.com/hashicorp/terraform-plugin-docs v0.20.1 // indirect + github.com/huandu/xstrings v1.3.3 // indirect + github.com/imdario/mergo v0.3.15 // indirect + github.com/mattn/go-runewidth v0.0.9 // indirect + github.com/mitchellh/copystructure v1.2.0 // indirect + github.com/mitchellh/reflectwalk v1.0.2 // indirect + github.com/posener/complete v1.2.3 // indirect + github.com/shopspring/decimal v1.3.1 // indirect + github.com/spf13/cast v1.5.0 // indirect + github.com/yuin/goldmark v1.7.7 // indirect + github.com/yuin/goldmark-meta v1.1.0 // indirect + github.com/zclconf/go-cty v1.15.0 // indirect + go.abhg.dev/goldmark/frontmatter v0.2.0 // indirect + golang.org/x/crypto v0.21.0 // indirect + golang.org/x/mod v0.21.0 // indirect + gopkg.in/yaml.v2 v2.3.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) + +require ( + github.com/fatih/color v1.16.0 // indirect github.com/golang/protobuf v1.5.3 // indirect - github.com/google/go-cmp v0.5.9 // indirect - github.com/hashicorp/go-hclog v1.5.0 // indirect + github.com/google/go-cmp v0.6.0 // indirect + github.com/hashicorp/go-hclog v1.6.3 // indirect github.com/hashicorp/go-plugin v1.4.10 // indirect github.com/hashicorp/go-uuid v1.0.3 // indirect github.com/hashicorp/terraform-plugin-go v0.18.0 // indirect github.com/hashicorp/terraform-registry-address v0.2.1 // indirect github.com/hashicorp/terraform-svchost v0.1.1 // indirect github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb // indirect - github.com/mattn/go-colorable v0.1.12 // indirect - github.com/mattn/go-isatty v0.0.14 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect github.com/mitchellh/go-testing-interface v1.14.1 // indirect github.com/oklog/run v1.0.0 // indirect github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect golang.org/x/exp v0.0.0-20230905200255-921286631fa9 - golang.org/x/net v0.17.0 // indirect + golang.org/x/net v0.23.0 // indirect golang.org/x/oauth2 v0.7.0 // indirect - golang.org/x/sys v0.13.0 // indirect - golang.org/x/text v0.13.0 // indirect + golang.org/x/sys v0.21.0 // indirect + golang.org/x/text v0.20.0 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect google.golang.org/grpc v1.56.3 // indirect - google.golang.org/protobuf v1.31.0 // indirect + google.golang.org/protobuf v1.33.0 // indirect ) diff --git a/go.sum b/go.sum index 777f590..6daac86 100644 --- a/go.sum +++ b/go.sum @@ -32,12 +32,34 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak= +github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/Kunde21/markdownfmt/v3 v3.1.0 h1:KiZu9LKs+wFFBQKhrZJrFZwtLnCCWJahL+S+E/3VnM0= +github.com/Kunde21/markdownfmt/v3 v3.1.0/go.mod h1:tPXN1RTyOzJwhfHoon9wUr4HGYmWgVxSQN6VBJDkrVc= +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.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g= +github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= +github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA= +github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM= +github.com/ProtonMail/go-crypto v1.1.0-alpha.2 h1:bkyFVUP+ROOARdgCiJzNQo2V2kiB97LyUpzH9P6Hrlg= +github.com/ProtonMail/go-crypto v1.1.0-alpha.2/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE= +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 v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI= +github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bmatcuk/doublestar/v4 v4.7.1 h1:fdDeAqgT47acgwd9bd9HxJRDmc9UAmPpc+2m0CXv75Q= +github.com/bmatcuk/doublestar/v4 v4.7.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU= +github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= 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= @@ -48,6 +70,8 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= +github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -92,6 +116,8 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 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/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= @@ -102,16 +128,47 @@ github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/hashicorp/cli v1.1.6 h1:CMOV+/LJfL1tXCOKrgAX0uRKnzjj/mpmqNXloRSy2K8= +github.com/hashicorp/cli v1.1.6/go.mod h1:MPon5QYlgjjo0BSoAiN0ESeT5fRzDjVRp+uioJ0piz4= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= +github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +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.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= +github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= 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-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= +github.com/hashicorp/go-hclog v1.6.3/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.10 h1:xUbmA4jC6Dq163/fWcp8P3JuHilrHHMLNRxzGQJ9hNk= github.com/hashicorp/go-plugin v1.4.10/go.mod h1:6/1TEzT0eQznvI/gV2CM29DLSkAK/e58mUWKVsPaph0= +github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU= +github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk= +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.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= +github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/hc-install v0.9.0 h1:2dIk8LcvANwtv3QZLckxcjyF5w8KVtiMxu6G6eLhghE= +github.com/hashicorp/hc-install v0.9.0/go.mod h1:+6vOP+mf3tuGgMApVYtmsnDoKWMDcFXeTxCACYZ8SFg= +github.com/hashicorp/terraform-exec v0.21.0 h1:uNkLAe95ey5Uux6KJdua6+cv8asgILFVWkd/RG0D2XQ= +github.com/hashicorp/terraform-exec v0.21.0/go.mod h1:1PPeMYou+KDUSSeRE9szMZ/oHf4fYUmB923Wzbq1ICg= +github.com/hashicorp/terraform-json v0.23.0 h1:sniCkExU4iKtTADReHzACkk8fnpQXrdD2xoR+lppBkI= +github.com/hashicorp/terraform-json v0.23.0/go.mod h1:MHdXbBAbSg0GvzuWazEGKAn/cyNfIB7mN6y7KJN6y2c= +github.com/hashicorp/terraform-plugin-docs v0.20.1 h1:Fq7E/HrU8kuZu3hNliZGwloFWSYfWEOWnylFhYQIoys= +github.com/hashicorp/terraform-plugin-docs v0.20.1/go.mod h1:Yz6HoK7/EgzSrHPB9J/lWFzwl9/xep2OPnc5jaJDV90= github.com/hashicorp/terraform-plugin-framework v0.10.0 h1:LGYcnvNdVaZA1ZHe53BHLVjaaGs7HTiq6+9Js29stL4= github.com/hashicorp/terraform-plugin-framework v0.10.0/go.mod h1:CK7Opzukfu/2CPJs+HzUdfHrFlp+ZIQeSxjF0x8k464= github.com/hashicorp/terraform-plugin-framework-validators v0.4.0 h1:GVX4gDFdtFZi/E4DjvPmRDf5zBLFAHi8M7Qzehgov+Q= @@ -126,7 +183,12 @@ github.com/hashicorp/terraform-svchost v0.1.1 h1:EZZimZ1GxdqFRinZ1tpJwVxxt49xc/S github.com/hashicorp/terraform-svchost v0.1.1/go.mod h1:mNsjQfZyf/Jhz35v6/0LWcv26+X7JPS+buii2c9/ctc= github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb h1:b5rjCoWHc7eqmAS4/qyk21ZsHyb6Mxv/jykxvNTkU4M= github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= +github.com/huandu/xstrings v1.3.3 h1:/Gcsuc1x8JVbJ9/rlye4xZnVAbEkGauT8lbebqcQws4= +github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +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/jhump/protoreflect v1.6.0 h1:h5jfMVslIg6l29nsMs0D8Wj17RDVdNYti0vDN/PZZoE= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= @@ -137,21 +199,44 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 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= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= 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/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +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-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= +github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= +github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +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/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/sethvargo/go-retry v0.2.3 h1:oYlgvIvsju3jNbottWABtbnoLC+GDtLdBHxKWxQm/iU= github.com/sethvargo/go-retry v0.2.3/go.mod h1:1afjQuvh7s4gflMObvjLPaWgluLLyhA1wmVZ6KLpICw= +github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= +github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= +github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= +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= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= @@ -165,6 +250,15 @@ github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/yuin/goldmark v1.7.7 h1:5m9rrB1sW3JUMToKFQfb+FGt1U7r57IHu5GrYrG2nqU= +github.com/yuin/goldmark v1.7.7/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= +github.com/yuin/goldmark-meta v1.1.0 h1:pWw+JLHGZe8Rk0EGsMVssiNb/AaPMHfSRszZeUeiOUc= +github.com/yuin/goldmark-meta v1.1.0/go.mod h1:U4spWENafuA7Zyg+Lj5RqK/MF+ovMYtBvXi1lBb2VP0= +github.com/zclconf/go-cty v1.15.0 h1:tTCRWxsexYUmtt/wVxgDClUe+uQusuI443uL6e+5sXQ= +github.com/zclconf/go-cty v1.15.0/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE= +go.abhg.dev/goldmark/frontmatter v0.2.0 h1:P8kPG0YkL12+aYk2yU3xHv4tcXzeVnN+gU0tJ5JnxRw= +go.abhg.dev/goldmark/frontmatter v0.2.0/go.mod h1:XqrEkZuM57djk7zrlRUB02x8I5J0px76YjkOzhB4YlU= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -175,6 +269,10 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= +golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -208,6 +306,9 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= +golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -234,9 +335,14 @@ golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +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.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= +golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -254,6 +360,7 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/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-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -283,19 +390,37 @@ golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +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.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.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= +golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 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/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/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.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.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= +golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -340,6 +465,7 @@ golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -427,10 +553,14 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 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/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/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= diff --git a/managed/data_source_cluster_name.go b/managed/data_source_cluster_name.go index b895362..5832fd8 100644 --- a/managed/data_source_cluster_name.go +++ b/managed/data_source_cluster_name.go @@ -336,6 +336,7 @@ func (r dataClusterNameType) GetSchema(_ context.Context) (tfsdk.Schema, diag.Di Computed: true, }, }), + DeprecationMessage: "Remove reliance on the attribute as it will be removed in the next major version of the provider. Please use cluster_region_info to read node config instead.", }, "credentials": { Computed: true, diff --git a/managed/models.go b/managed/models.go index 1c2fe79..d54a0d4 100644 --- a/managed/models.go +++ b/managed/models.go @@ -25,7 +25,7 @@ type Cluster struct { ClusterTier types.String `tfsdk:"cluster_tier"` ClusterAllowListIDs []types.String `tfsdk:"cluster_allow_list_ids"` RestoreBackupID types.String `tfsdk:"restore_backup_id"` - NodeConfig NodeConfig `tfsdk:"node_config"` + NodeConfig *NodeConfig `tfsdk:"node_config"` Credentials Credentials `tfsdk:"credentials"` ClusterInfo ClusterInfo `tfsdk:"cluster_info"` ClusterVersion types.String `tfsdk:"cluster_version"` diff --git a/managed/resource_cluster.go b/managed/resource_cluster.go index 2c2f5df..fc92389 100644 --- a/managed/resource_cluster.go +++ b/managed/resource_cluster.go @@ -24,7 +24,7 @@ import ( "github.com/hashicorp/terraform-plugin-framework/tfsdk" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-plugin-log/tflog" - retry "github.com/sethvargo/go-retry" + "github.com/sethvargo/go-retry" "github.com/yugabyte/terraform-provider-ybm/managed/fflags" "github.com/yugabyte/terraform-provider-ybm/managed/util" openapiclient "github.com/yugabyte/yugabytedb-managed-go-client-internal" @@ -63,6 +63,9 @@ func (r resourceClusterType) GetSchema(_ context.Context) (tfsdk.Schema, diag.Di Description: "The type of the cluster. SYNCHRONOUS or GEO_PARTITIONED", Type: types.StringType, Required: true, + Validators: []tfsdk.AttributeValidator{ + stringvalidator.OneOf("SYNCHRONOUS", "GEO_PARTITIONED"), + }, }, "cloud_type": { Description: "The cloud provider where the cluster is deployed: AWS, AZURE or GCP.", @@ -87,18 +90,34 @@ func (r resourceClusterType) GetSchema(_ context.Context) (tfsdk.Schema, diag.Di Type: types.Int64Type, Optional: true, Computed: true, + Validators: []tfsdk.AttributeValidator{ + schemavalidator.ExactlyOneOf( + path.MatchRelative().AtParent().AtParent().AtParent().AtName("node_config").AtName("num_cores"), + path.MatchRelative(), + ), + }, }, "disk_size_gb": { Description: "Disk size of the nodes of the region.", Type: types.Int64Type, Optional: true, Computed: true, + Validators: []tfsdk.AttributeValidator{ + schemavalidator.ConflictsWith( + path.MatchRelative().AtParent().AtParent().AtParent().AtName("node_config").AtName("disk_size_gb"), + ), + }, }, "disk_iops": { Description: "Disk IOPS of the nodes of the region.", Type: types.Int64Type, Optional: true, Computed: true, + Validators: []tfsdk.AttributeValidator{ + schemavalidator.ConflictsWith( + path.MatchRelative().AtParent().AtParent().AtParent().AtName("node_config").AtName("disk_iops"), + ), + }, }, "vpc_id": { Type: types.StringType, @@ -373,26 +392,39 @@ func (r resourceClusterType) GetSchema(_ context.Context) (tfsdk.Schema, diag.Di Optional: true, }, "node_config": { - Required: true, + Optional: true, + Computed: true, Attributes: tfsdk.SingleNestedAttributes(map[string]tfsdk.Attribute{ "num_cores": { Description: "Number of CPU cores in the node.", Type: types.Int64Type, - Required: true, + Optional: true, + Computed: true, }, "disk_size_gb": { Description: "Disk size of the node.", Type: types.Int64Type, Computed: true, Optional: true, + Validators: []tfsdk.AttributeValidator{ + schemavalidator.ConflictsWith( + path.MatchRelative().AtParent().AtParent().AtName("cluster_region_info").AtAnyListIndex().AtName("disk_size_gb"), + ), + }, }, "disk_iops": { Description: "Disk IOPS of the node.", Type: types.Int64Type, Computed: true, Optional: true, + Validators: []tfsdk.AttributeValidator{ + schemavalidator.ConflictsWith( + path.MatchRelative().AtParent().AtParent().AtName("cluster_region_info").AtAnyListIndex().AtName("disk_iops"), + ), + }, }, }), + DeprecationMessage: "Remove this attribute's configuration as it's no longer in use and the attribute will be removed in the next major version of the provider. Please use cluster_region_info to specify node config instead.", }, "credentials": { Description: `Credentials to be used by the database. Please provide 'username' and 'password' @@ -577,7 +609,7 @@ func editBackupScheduleV2(ctx context.Context, backupScheduleStruct BackupSchedu backupScheduleSpec.UnsetTimeIntervalInDays() } if backupScheduleStruct.TimeIntervalInDays.Value != 0 && backupScheduleStruct.CronExpression.Value != "" { - return errors.New("Unable to create custom backup schedule. You can't pass both the cron expression and time interval in days.") + return errors.New("unable to create custom backup schedule. You can't pass both the cron expression and time interval in days") } _, res, err := apiClient.BackupApi.ModifyBackupScheduleV2(ctx, accountId, projectId, clusterId, scheduleId).ScheduleSpecV2(backupScheduleSpec).Execute() @@ -611,7 +643,7 @@ func createClusterSpec(ctx context.Context, apiClient *openapiclient.APIClient, softwareInfo.SetTrackId(trackId) } - clusterRegionInfo := []openapiclient.ClusterRegionInfo{} + var clusterRegionInfo []openapiclient.ClusterRegionInfo totalNodes := 0 clusterType := plan.ClusterType.Value isDefaultSet := false @@ -633,41 +665,50 @@ func createClusterSpec(ctx context.Context, apiClient *openapiclient.APIClient, regionInfo.VPCID.Value = vpcData.Info.Id } - if !regionInfo.NumCores.IsUnknown() && !regionInfo.NumCores.IsNull() { - cloud := plan.CloudType.Value - tier := plan.ClusterTier.Value - region := regionInfo.Region.Value - numCores := int32(regionInfo.NumCores.Value) - memoryMb, memoryOK, message = getMemoryFromInstanceType(ctx, apiClient, accountId, cloud, tier, region, numCores) - if !memoryOK { - return nil, false, message - } + cloud := plan.CloudType.Value + tier := plan.ClusterTier.Value + region := regionInfo.Region.Value + var numCores int32 + // If regionInfo numCores is null, then it must be coming from the root level node info. + if regionInfo.NumCores.IsNull() || regionInfo.NumCores.IsUnknown() { + numCores = int32(plan.NodeConfig.NumCores.Value) + } else { + numCores = int32(regionInfo.NumCores.Value) + } - if !regionInfo.DiskSizeGb.IsUnknown() && !regionInfo.DiskSizeGb.IsNull() { - diskSizeGb = int32(regionInfo.DiskSizeGb.Value) - } else { - diskSizeGb, diskSizeOK, message = getDiskSizeFromInstanceType(ctx, apiClient, accountId, cloud, tier, region, numCores) - if !diskSizeOK { - return nil, false, message - } - } + memoryMb, memoryOK, message = getMemoryFromInstanceType(ctx, apiClient, accountId, cloud, tier, region, numCores) + if !memoryOK { + return nil, false, message + } - nodeInfo := *openapiclient.NewOptionalClusterNodeInfo(numCores, memoryMb, diskSizeGb) - if !regionInfo.DiskIops.IsUnknown() && !regionInfo.DiskIops.IsNull() { - nodeInfo.SetDiskIops(int32(regionInfo.DiskIops.Value)) + if !regionInfo.DiskSizeGb.IsUnknown() && !regionInfo.DiskSizeGb.IsNull() { + diskSizeGb = int32(regionInfo.DiskSizeGb.Value) + } else if plan.NodeConfig != nil && !plan.NodeConfig.DiskSizeGb.IsUnknown() && !plan.NodeConfig.DiskSizeGb.IsNull() { + diskSizeGb = int32(plan.NodeConfig.DiskSizeGb.Value) + } else { + diskSizeGb, diskSizeOK, message = getDiskSizeFromInstanceType(ctx, apiClient, accountId, cloud, tier, region, numCores) + if !diskSizeOK { + return nil, false, message } + } - info.SetNodeInfo(nodeInfo) + nodeInfo := *openapiclient.NewOptionalClusterNodeInfo(numCores, memoryMb, diskSizeGb) + if !regionInfo.DiskIops.IsUnknown() && !regionInfo.DiskIops.IsNull() && int32(regionInfo.DiskIops.Value) > 0 { + nodeInfo.SetDiskIops(int32(regionInfo.DiskIops.Value)) + } else if plan.NodeConfig != nil && !plan.NodeConfig.DiskIops.IsNull() && !plan.NodeConfig.DiskIops.IsNull() && int32(plan.NodeConfig.DiskIops.Value) > 0 { + nodeInfo.SetDiskIops(int32(plan.NodeConfig.DiskIops.Value)) } else { - info.UnsetNodeInfo() + nodeInfo.UnsetDiskIops() } + info.SetNodeInfo(nodeInfo) + // Create an array of AccessibilityType and populate it according to // the following logic: // if the cluster is in a private VPC, it MUST always have PRIVATE. // if the cluster is NOT in a private VPC, it MUST always have PUBLIC. // if the cluster is in a private VPC and customer wants public access, it MUST have PRIVATE and PUBLIC. - accessibilityTypes := []openapiclient.AccessibilityType{} + var accessibilityTypes []openapiclient.AccessibilityType if vpcID := regionInfo.VPCID.Value; vpcID != "" { info.PlacementInfo.SetVpcId(vpcID) @@ -679,7 +720,7 @@ func createClusterSpec(ctx context.Context, apiClient *openapiclient.APIClient, } else { accessibilityTypes = append(accessibilityTypes, openapiclient.ACCESSIBILITYTYPE_PUBLIC) - // If the value is specified and it is false, then it is an error because the user + // If the value is specified, and it is false, then it is an error because the user // wants disabled public access on a non-dedicated VPC cluster. if !regionInfo.PublicAccess.IsUnknown() && !regionInfo.PublicAccess.Value { tflog.Debug(ctx, fmt.Sprintf("Cluster %v is in a public VPC and public access is disabled. ", plan.ClusterName.Value)) @@ -709,31 +750,9 @@ func createClusterSpec(ctx context.Context, apiClient *openapiclient.APIClient, } // This is to pass in the region information to fetch memory and disk size - region := "" regionCount := len(clusterRegionInfo) - if regionCount > 0 { - region = clusterRegionInfo[0].PlacementInfo.CloudInfo.Region - if regionCount == 1 { - clusterRegionInfo[0].SetIsDefault(true) - } - } - - cloud := plan.CloudType.Value - tier := plan.ClusterTier.Value - numCores := int32(plan.NodeConfig.NumCores.Value) - memoryMb, memoryOK, message = getMemoryFromInstanceType(ctx, apiClient, accountId, cloud, tier, region, numCores) - if !memoryOK { - return nil, false, message - } - - // Computing the default disk size if it is not provided - if !plan.NodeConfig.DiskSizeGb.IsUnknown() { - diskSizeGb = int32(plan.NodeConfig.DiskSizeGb.Value) - } else { - diskSizeGb, diskSizeOK, message = getDiskSizeFromInstanceType(ctx, apiClient, accountId, cloud, tier, region, numCores) - if !diskSizeOK { - return nil, false, message - } + if regionCount == 1 { + clusterRegionInfo[0].SetIsDefault(true) } // This is to support a redundant value in the API. @@ -744,18 +763,13 @@ func createClusterSpec(ctx context.Context, apiClient *openapiclient.APIClient, } clusterInfo := *openapiclient.NewClusterInfo( - openapiclient.ClusterTier(tier), + openapiclient.ClusterTier(plan.ClusterTier.Value), int32(totalNodes), openapiclient.ClusterFaultTolerance(plan.FaultTolerance.Value), isProduction, ) - nodeInfo := *openapiclient.NewClusterNodeInfo(numCores, memoryMb, diskSizeGb) - if !plan.NodeConfig.DiskIops.IsUnknown() { - nodeInfo.SetDiskIops(int32(plan.NodeConfig.DiskIops.Value)) - } - - clusterInfo.SetNodeInfo(nodeInfo) + clusterInfo.UnsetNodeInfo() if !plan.NumFaultsToTolerate.IsUnknown() { clusterInfo.SetNumFaultsToTolerate(int32(plan.NumFaultsToTolerate.Value)) @@ -763,8 +777,8 @@ func createClusterSpec(ctx context.Context, apiClient *openapiclient.APIClient, clusterInfo.SetClusterType(openapiclient.ClusterType(clusterType)) if clusterExists { - cluster_version, _ := strconv.Atoi(plan.ClusterVersion.Value) - clusterInfo.SetVersion(int32(cluster_version)) + clusterVersion, _ := strconv.Atoi(plan.ClusterVersion.Value) + clusterInfo.SetVersion(int32(clusterVersion)) } clusterSpec = openapiclient.NewClusterSpec( @@ -799,7 +813,13 @@ func getPlan(ctx context.Context, plan tfsdk.Plan, cluster *Cluster) diag.Diagno if fflags.IsFeatureFlagEnabled(fflags.CONNECTION_POOLING) { diags.Append(plan.GetAttribute(ctx, path.Root("desired_connection_pooling_state"), &cluster.DesiredConnectionPoolingState)...) } - diags.Append(plan.GetAttribute(ctx, path.Root("node_config"), &cluster.NodeConfig)...) + + var nodeConfig *NodeConfig + plan.GetAttribute(ctx, path.Root("node_config"), &nodeConfig) + if nodeConfig != nil { + diags.Append(plan.GetAttribute(ctx, path.Root("node_config"), &cluster.NodeConfig)...) + } + diags.Append(plan.GetAttribute(ctx, path.Root("credentials"), &cluster.Credentials)...) diags.Append(plan.GetAttribute(ctx, path.Root("backup_schedules"), &cluster.BackupSchedules)...) diags.Append(plan.GetAttribute(ctx, path.Root("cmk_spec"), &cluster.CMKSpec)...) @@ -860,7 +880,7 @@ func setClusterState(ctx context.Context, state *tfsdk.State, cluster *Cluster) ClusterTier types.String `tfsdk:"cluster_tier"` ClusterAllowListIDs []types.String `tfsdk:"cluster_allow_list_ids"` RestoreBackupID types.String `tfsdk:"restore_backup_id"` - NodeConfig NodeConfig `tfsdk:"node_config"` + NodeConfig *NodeConfig `tfsdk:"node_config"` Credentials Credentials `tfsdk:"credentials"` ClusterInfo ClusterInfo `tfsdk:"cluster_info"` ClusterVersion types.String `tfsdk:"cluster_version"` @@ -912,7 +932,7 @@ func validateOnlyOneCMKSpec(plan *Cluster) error { } if count != 1 { - return errors.New("Invalid input. Only one CMK Provider out of AWS, GCP, or AZURE must be present.") + return errors.New("invalid input. Only one CMK Provider out of AWS, GCP, or AZURE must be present") } return nil @@ -929,7 +949,7 @@ func createCmkSpec(plan Cluster) (*openapiclient.CMKSpec, error) { switch cmkProvider { case "GCP": if plan.CMKSpec.GCPCMKSpec == nil { - return nil, errors.New("Provider type is GCP but GCP CMK spec is missing.") + return nil, errors.New("provider type is GCP but GCP CMK spec is missing") } gcpKeyRingName := plan.CMKSpec.GCPCMKSpec.KeyRingName.Value gcpKeyName := plan.CMKSpec.GCPCMKSpec.KeyName.Value @@ -959,7 +979,7 @@ func createCmkSpec(plan Cluster) (*openapiclient.CMKSpec, error) { cmkSpec.SetGcpCmkSpec(*gcpCmkSpec) case "AWS": if plan.CMKSpec.AWSCMKSpec == nil { - return nil, errors.New("Provider type is AWS but AWS CMK spec is missing.") + return nil, errors.New("provider type is AWS but AWS CMK spec is missing") } awsSecretKey := plan.CMKSpec.AWSCMKSpec.SecretKey.Value awsAccessKey := plan.CMKSpec.AWSCMKSpec.AccessKey.Value @@ -973,7 +993,7 @@ func createCmkSpec(plan Cluster) (*openapiclient.CMKSpec, error) { cmkSpec.SetAwsCmkSpec(*awsCmkSpec) case "AZURE": if plan.CMKSpec.AzureCMKSpec == nil { - return nil, errors.New("Provider type is AZURE but AZURE CMK spec is missing.") + return nil, errors.New("provider type is AZURE but AZURE CMK spec is missing") } azureClientId := plan.CMKSpec.AzureCMKSpec.ClientID.Value azureClientSecret := plan.CMKSpec.AzureCMKSpec.ClientSecret.Value @@ -1015,12 +1035,12 @@ func (r resourceCluster) Create(ctx context.Context, req tfsdk.CreateResourceReq return } - if !plan.NodeConfig.DiskSizeGb.IsUnknown() && !util.IsDiskSizeValid(plan.ClusterTier.Value, plan.NodeConfig.DiskSizeGb.Value) { + if plan.NodeConfig != nil && !plan.NodeConfig.DiskSizeGb.IsNull() && !plan.NodeConfig.DiskSizeGb.IsUnknown() && !util.IsDiskSizeValid(plan.ClusterTier.Value, plan.NodeConfig.DiskSizeGb.Value) { resp.Diagnostics.AddError("Invalid disk size", "The disk size for a paid cluster must be at least 50 GB.") return } - if !(plan.NodeConfig.DiskIops.IsUnknown() || plan.NodeConfig.DiskIops.IsNull()) { + if plan.NodeConfig != nil && !plan.NodeConfig.DiskIops.IsNull() && !plan.NodeConfig.DiskIops.IsUnknown() { isValid, err := util.IsDiskIopsValid(plan.CloudType.Value, plan.ClusterTier.Value, plan.NodeConfig.DiskIops.Value) if !isValid { resp.Diagnostics.AddError("Invalid disk IOPS", err) @@ -1063,26 +1083,19 @@ func (r resourceCluster) Create(ctx context.Context, req tfsdk.CreateResourceReq return } } - numCoresPresent := false - diskSizePresent := false - diskIopsPresent := false - if !regionInfo.NumCores.Unknown && !regionInfo.NumCores.Null { - numCoresPresent = true - } - if !regionInfo.DiskSizeGb.Unknown && !regionInfo.DiskSizeGb.Null { - diskSizePresent = true - } - if !regionInfo.DiskIops.Unknown && !regionInfo.DiskIops.Null { - diskIopsPresent = true - } - if !numCoresPresent && (diskSizePresent || diskIopsPresent) { - resp.Diagnostics.AddError( - "Specify num_cores per region, since per-region disk_size or disk_iops are specified.", - "To specify per-region node configuration, num_cores must be provided.", - ) + if !regionInfo.DiskSizeGb.IsUnknown() && !util.IsDiskSizeValid(plan.ClusterTier.Value, regionInfo.DiskSizeGb.Value) { + resp.Diagnostics.AddError("Invalid disk size in "+regionInfo.Region.Value, "The disk size for a paid cluster must be at least 50 GB.") return } + + if !regionInfo.DiskIops.IsUnknown() && !regionInfo.DiskIops.IsNull() { + isValid, err := util.IsDiskIopsValid(plan.CloudType.Value, plan.ClusterTier.Value, regionInfo.DiskIops.Value) + if !isValid { + resp.Diagnostics.AddError("Invalid disk IOPS in "+regionInfo.Region.Value, err) + return + } + } } projectId, getProjectOK, message := getProjectId(ctx, apiClient, accountId) @@ -1181,7 +1194,7 @@ func (r resourceCluster) Create(ctx context.Context, req tfsdk.CreateResourceReq } else { return handleReadFailureWithRetries(ctx, &readClusterRetries, 2, message) } - return retry.RetryableError(errors.New("The cluster creation is in progress")) + return retry.RetryableError(errors.New("the cluster creation is in progress")) }) if err != nil { @@ -1241,7 +1254,7 @@ func (r resourceCluster) Create(ctx context.Context, req tfsdk.CreateResourceReq } - allowListIDs := []string{} + var allowListIDs []string allowListProvided := false if plan.ClusterAllowListIDs != nil { for i := range plan.ClusterAllowListIDs { @@ -1272,7 +1285,7 @@ func (r resourceCluster) Create(ctx context.Context, req tfsdk.CreateResourceReq } } - regions := []string{} + var regions []string for _, regionInfo := range plan.ClusterRegionInfo { regions = append(regions, regionInfo.Region.Value) } @@ -1292,8 +1305,8 @@ func (r resourceCluster) Create(ctx context.Context, req tfsdk.CreateResourceReq providerType := cluster.CMKSpec.ProviderType.Value switch providerType { case "AWS": - cluster.CMKSpec.AWSCMKSpec.SecretKey = types.String{Value: string(cmkSpec.GetAwsCmkSpec().SecretKey)} - cluster.CMKSpec.AWSCMKSpec.AccessKey = types.String{Value: string(cmkSpec.GetAwsCmkSpec().AccessKey)} + cluster.CMKSpec.AWSCMKSpec.SecretKey = types.String{Value: cmkSpec.GetAwsCmkSpec().SecretKey} + cluster.CMKSpec.AWSCMKSpec.AccessKey = types.String{Value: cmkSpec.GetAwsCmkSpec().AccessKey} case "GCP": if cmkSpec.GetGcpCmkSpec().GcpServiceAccount.IsSet() { gcpServiceAccountData := cmkSpec.GetGcpCmkSpec().GcpServiceAccount.Get() @@ -1305,7 +1318,7 @@ func (r resourceCluster) Create(ctx context.Context, req tfsdk.CreateResourceReq } } case "AZURE": - cluster.CMKSpec.AzureCMKSpec.ClientSecret = types.String{Value: string(cmkSpec.GetAzureCmkSpec().ClientSecret)} + cluster.CMKSpec.AzureCMKSpec.ClientSecret = types.String{Value: cmkSpec.GetAzureCmkSpec().ClientSecret} } } @@ -1387,11 +1400,11 @@ func pauseCluster(ctx context.Context, apiClient *openapiclient.APIClient, accou } else { return handleReadFailureWithRetries(ctx, &readClusterRetries, 2, message) } - return retry.RetryableError(errors.New("The cluster is being paused.")) + return retry.RetryableError(errors.New("the cluster is being paused")) }) if err != nil { - return errors.New("Unable to pause cluster. " + "The operation timed out waiting to pause the cluster.") + return errors.New("unable to pause cluster. " + "The operation timed out waiting to pause the cluster") } return nil @@ -1424,11 +1437,11 @@ func enableConnectionPooling(ctx context.Context, apiClient *openapiclient.APICl } else { return handleReadFailureWithRetries(ctx, &readClusterRetries, 2, message) } - return retry.RetryableError(errors.New("Connection Pooling is being enabled")) + return retry.RetryableError(errors.New("connection Pooling is being enabled")) }) if err != nil { - return errors.New("Unable to enable connection pooling " + "The operation timed out waiting to enable connection pooling") + return errors.New("unable to enable connection pooling " + "The operation timed out waiting to enable connection pooling") } return nil @@ -1460,11 +1473,11 @@ func disableConnectionPooling(ctx context.Context, apiClient *openapiclient.APIC } else { return handleReadFailureWithRetries(ctx, &readClusterRetries, 2, message) } - return retry.RetryableError(errors.New("Connection Pooling is being disabled")) + return retry.RetryableError(errors.New("connection Pooling is being disabled")) }) if err != nil { - return errors.New("Unable to disable connection pooling " + "The operation timed out waiting to disable connection pooling") + return errors.New("unable to disable connection pooling " + "The operation timed out waiting to disable connection pooling") } return nil @@ -1493,11 +1506,11 @@ func editClusterCmk(ctx context.Context, apiClient *openapiclient.APIClient, acc } else { return handleReadFailureWithRetries(ctx, &readClusterRetries, 2, message) } - return retry.RetryableError(errors.New("Cluster CMK is getting updated.")) + return retry.RetryableError(errors.New("cluster CMK is getting updated")) }) if err != nil { - return errors.New("Unable to edit cluster CMK. " + "The operation timed out waiting to edit CMK.") + return errors.New("unable to edit cluster CMK. " + "The operation timed out waiting to edit CMK") } return nil @@ -1539,11 +1552,11 @@ func resumeCluster(ctx context.Context, apiClient *openapiclient.APIClient, acco } else { return handleReadFailureWithRetries(ctx, &readClusterRetries, 2, message) } - return retry.RetryableError(errors.New("The cluster is being resumed.")) + return retry.RetryableError(errors.New("the cluster is being resumed")) }) if err != nil { - return errors.New("Unable to resume cluster. " + "The operation timed out waiting to resume the cluster.") + return errors.New("unable to resume cluster. " + "The operation timed out waiting to resume the cluster") } return nil @@ -1575,7 +1588,7 @@ func (r resourceCluster) Read(ctx context.Context, req tfsdk.ReadResourceRequest var state Cluster getIDsFromState(ctx, req.State, &state) - allowListIDs := []string{} + var allowListIDs []string allowListProvided := false if state.ClusterAllowListIDs != nil { allowListProvided = true @@ -1584,7 +1597,7 @@ func (r resourceCluster) Read(ctx context.Context, req tfsdk.ReadResourceRequest } } - regions := []string{} + var regions []string for _, regionInfo := range state.ClusterRegionInfo { regions = append(regions, regionInfo.Region.Value) } @@ -1611,7 +1624,7 @@ func (r resourceCluster) Read(ctx context.Context, req tfsdk.ReadResourceRequest cluster.CMKSpec.GCPCMKSpec.GcpServiceAccount.ClientId.Value = cmkSpec.GCPCMKSpec.GcpServiceAccount.ClientId.Value cluster.CMKSpec.GCPCMKSpec.GcpServiceAccount.PrivateKey.Value = cmkSpec.GCPCMKSpec.GcpServiceAccount.PrivateKey.Value case "AZURE": - cluster.CMKSpec.AzureCMKSpec.ClientSecret = types.String{Value: string(cmkSpec.AzureCMKSpec.ClientSecret.Value)} + cluster.CMKSpec.AzureCMKSpec.ClientSecret = types.String{Value: cmkSpec.AzureCMKSpec.ClientSecret.Value} } } @@ -1705,7 +1718,7 @@ func resourceClusterRead(ctx context.Context, accountId string, projectId string cmkDataSpec := cmkResp.GetData().Spec.Get() cmkSpec.ProviderType = types.String{Value: string(cmkDataSpec.GetProviderType())} - cmkSpec.IsEnabled = types.Bool{Value: bool(cmkDataSpec.GetIsEnabled())} + cmkSpec.IsEnabled = types.Bool{Value: cmkDataSpec.GetIsEnabled()} switch cmkSpec.ProviderType.Value { case "AWS": @@ -1769,7 +1782,7 @@ func resourceClusterRead(ctx context.Context, accountId string, projectId string } } - // fill all fields of schema except credentials - credentials are not returned by api call + // fill with all fields of schema except credentials - credentials are not returned by api call cluster.AccountID.Value = accountId cluster.ProjectID.Value = projectId cluster.ClusterID.Value = clusterId @@ -1803,8 +1816,16 @@ func resourceClusterRead(ctx context.Context, accountId string, projectId string cluster.NumFaultsToTolerate.Value = int64(*clusterResp.Data.Spec.ClusterInfo.NumFaultsToTolerate.Get()) nodeInfo := clusterResp.Data.Spec.ClusterInfo.NodeInfo.Get() if nodeInfo != nil { - cluster.NodeConfig.NumCores.Value = int64((*nodeInfo).NumCores) - cluster.NodeConfig.DiskSizeGb.Value = int64((*nodeInfo).DiskSizeGb) + if cluster.NodeConfig == nil { + cluster.NodeConfig = &NodeConfig{ + NumCores: types.Int64{Value: int64((*nodeInfo).NumCores)}, + DiskSizeGb: types.Int64{Value: int64((*nodeInfo).DiskSizeGb)}, + } + } else { + cluster.NodeConfig.NumCores.Value = int64((*nodeInfo).NumCores) + cluster.NodeConfig.DiskSizeGb.Value = int64((*nodeInfo).DiskSizeGb) + } + iopsPtr := (*nodeInfo).DiskIops.Get() if iopsPtr != nil { cluster.NodeConfig.DiskIops.Value = int64(*iopsPtr) @@ -1897,9 +1918,7 @@ func resourceClusterRead(ctx context.Context, accountId string, projectId string } } cluster.ClusterRegionInfo = clusterRegionInfo - if len(respClusterRegionInfo) > 0 { - cluster.CloudType.Value = string(respClusterRegionInfo[0].PlacementInfo.CloudInfo.GetCode()) - } + cluster.CloudType.Value = string(respClusterRegionInfo[0].PlacementInfo.CloudInfo.GetCode()) if allowListProvided { for { @@ -1909,8 +1928,8 @@ func resourceClusterRead(ctx context.Context, accountId string, projectId string return cluster, false, errMsg } allowListIDMap := map[string]bool{} - allowListIDs := []types.String{} - allowListStrings := []string{} + var allowListIDs []types.String + var allowListStrings []string // This is being to done to preserve order in the list since an order mismatch is treated as state mismatch by Terraform for _, elem := range clusterAllowListMappingResp.Data { allowListIDMap[elem.Info.Id] = true @@ -1978,11 +1997,11 @@ func handleRestore(ctx context.Context, accountId string, projectId string, clus } else { return retry.RetryableError(errors.New("Unable to get restore state: " + message)) } - return retry.RetryableError(errors.New("The backup restore is in progress")) + return retry.RetryableError(errors.New("the backup restore is in progress")) }) if err != nil { - return errors.New("Unable to restore backup to the cluster: The operation timed out waiting for backup restore.") + return errors.New("unable to restore backup to the cluster: The operation timed out waiting for backup restore") } return nil @@ -1996,12 +2015,12 @@ func (r resourceCluster) Update(ctx context.Context, req tfsdk.UpdateResourceReq return } - if !plan.NodeConfig.DiskSizeGb.IsUnknown() && !util.IsDiskSizeValid(plan.ClusterTier.Value, plan.NodeConfig.DiskSizeGb.Value) { + if plan.NodeConfig != nil && !plan.NodeConfig.DiskSizeGb.IsUnknown() && !util.IsDiskSizeValid(plan.ClusterTier.Value, plan.NodeConfig.DiskSizeGb.Value) { resp.Diagnostics.AddError("Invalid disk size", "The disk size for a paid cluster must be at least 50 GB.") return } - if !(plan.NodeConfig.DiskIops.IsUnknown() || plan.NodeConfig.DiskIops.IsNull()) { + if plan.NodeConfig != nil && !plan.NodeConfig.DiskIops.IsNull() && !plan.NodeConfig.DiskIops.IsUnknown() { isValid, err := util.IsDiskIopsValid(plan.CloudType.Value, plan.ClusterTier.Value, plan.NodeConfig.DiskIops.Value) if !isValid { resp.Diagnostics.AddError("Invalid disk IOPS", err) @@ -2056,6 +2075,19 @@ func (r resourceCluster) Update(ctx context.Context, req tfsdk.UpdateResourceReq return } } + + if !regionInfo.DiskSizeGb.IsUnknown() && !util.IsDiskSizeValid(plan.ClusterTier.Value, regionInfo.DiskSizeGb.Value) { + resp.Diagnostics.AddError("Invalid disk size in "+regionInfo.Region.Value, "The disk size for a paid cluster must be at least 50 GB.") + return + } + + if !(regionInfo.DiskIops.IsUnknown() || regionInfo.DiskIops.IsNull()) { + isValid, err := util.IsDiskIopsValid(plan.CloudType.Value, plan.ClusterTier.Value, regionInfo.DiskIops.Value) + if !isValid { + resp.Diagnostics.AddError("Invalid disk IOPS in "+regionInfo.Region.Value, err) + return + } + } } scheduleId := "" @@ -2124,7 +2156,7 @@ func (r resourceCluster) Update(ctx context.Context, req tfsdk.UpdateResourceReq if retries < 6 { retries++ tflog.Info(ctx, "Cluster edit task not found, retrying...") - return retry.RetryableError(errors.New("Cluster not found, retrying")) + return retry.RetryableError(errors.New("cluster not found, retrying")) } else { tflog.Info(ctx, "Cluster edit task not found, the change would not have required a task creation") return nil @@ -2135,7 +2167,7 @@ func (r resourceCluster) Update(ctx context.Context, req tfsdk.UpdateResourceReq if checkNewTaskSpawned { if asState == string(openapiclient.TASKACTIONSTATEENUM_IN_PROGRESS) { checkNewTaskSpawned = false - return retry.RetryableError(errors.New("Cluster edit operation in progress")) + return retry.RetryableError(errors.New("cluster edit operation in progress")) } else { tflog.Info(ctx, "Cluster edit task not found, the change would not have required a task creation") return nil @@ -2151,7 +2183,7 @@ func (r resourceCluster) Update(ctx context.Context, req tfsdk.UpdateResourceReq } else { return handleReadFailureWithRetries(ctx, &readClusterRetries, 2, message) } - return retry.RetryableError(errors.New("Cluster edit operation in progress")) + return retry.RetryableError(errors.New("cluster edit operation in progress")) }) if err != nil { @@ -2176,7 +2208,7 @@ func (r resourceCluster) Update(ctx context.Context, req tfsdk.UpdateResourceReq } else { return handleReadFailureWithRetries(ctx, &readClusterRetries, 2, message) } - return retry.RetryableError(errors.New("Cluster edit is in progress")) + return retry.RetryableError(errors.New("cluster edit is in progress")) }) if err != nil { @@ -2238,7 +2270,7 @@ func (r resourceCluster) Update(ctx context.Context, req tfsdk.UpdateResourceReq } } - allowListIDs := []string{} + var allowListIDs []string allowListProvided := false if plan.ClusterAllowListIDs != nil { @@ -2293,7 +2325,7 @@ func (r resourceCluster) Update(ctx context.Context, req tfsdk.UpdateResourceReq } } - regions := []string{} + var regions []string for _, regionInfo := range plan.ClusterRegionInfo { regions = append(regions, regionInfo.Region.Value) } @@ -2375,7 +2407,7 @@ func (r resourceCluster) Delete(ctx context.Context, req tfsdk.DeleteResourceReq } else { return handleReadFailureWithRetries(ctx, &readClusterRetries, 2, message) } - return retry.RetryableError(errors.New("Cluster deletion operation in progress")) + return retry.RetryableError(errors.New("cluster deletion operation in progress")) }) if err != nil { @@ -2389,7 +2421,7 @@ func (r resourceCluster) Delete(ctx context.Context, req tfsdk.DeleteResourceReq resp.State.RemoveResource(ctx) } -// Import resource +// ImportState Import resource func (r resourceCluster) ImportState(ctx context.Context, req tfsdk.ImportResourceStateRequest, resp *tfsdk.ImportResourceStateResponse) { // Save the import identifier in the id attribute tfsdk.ResourceImportStatePassthroughID(ctx, path.Root("id"), req, resp) diff --git a/samples/cluster-multi-region.tf b/samples/cluster-multi-region.tf index 207726c..f317cc6 100644 --- a/samples/cluster-multi-region.tf +++ b/samples/cluster-multi-region.tf @@ -7,26 +7,25 @@ resource "ybm_cluster" "multi_region" { region = "us-west2" num_nodes = 1 vpc_id = ybm_vpc.newvpc.vpc_id + num_cores = 2 }, { region = "asia-east1" num_nodes = 1 vpc_id = ybm_vpc.newvpc.vpc_id + num_cores = 2 }, { region = "europe-central2" num_nodes = 1 vpc_id = ybm_vpc.newvpc.vpc_id + num_cores = 2 } ] cluster_tier = "PAID" cluster_allow_list_ids = [ybm_allow_list.mylist.allow_list_id] restore_backup_id = ybm_backup.mybackup.backup_id fault_tolerance = "REGION" - node_config = { - num_cores = 2 - disk_size_gb = 10 - } credentials = { ysql_username = "example_ysql_user" ysql_password = var.ysql_password diff --git a/samples/cluster-single-region.tf b/samples/cluster-single-region.tf index c72f67f..9c7e32a 100644 --- a/samples/cluster-single-region.tf +++ b/samples/cluster-single-region.tf @@ -40,17 +40,14 @@ resource "ybm_cluster" "single_region" { region = "us-west2" num_nodes = 1 vpc_id = ybm_vpc.newvpc.vpc_id + num_cores = 2 } ] cluster_tier = "PAID" cluster_allow_list_ids = [ybm_allow_list.mylist.allow_list_id] fault_tolerance = "NONE" - node_config = { - num_cores = 2 - disk_size_gb = 10 - } - // for custom_backup_schedule to be activated pass true + // for custom_backup_schedule to be activated pass true backup_schedules = [ { state = "ACTIVE" @@ -64,12 +61,11 @@ resource "ybm_cluster" "single_region" { ycql_username = "example_ycql_user" ycql_password = var.ycql_password } - } -data "ybm_cluster" "clustername" { - cluster_name = "terraform-test-posriniv-1" -} +# data "ybm_cluster" "clustername" { +# cluster_name = "terraform-test-posriniv-1" +# } resource "ybm_allow_list" "mylist" { allow_list_name = "all" @@ -87,7 +83,7 @@ resource "ybm_allow_list" "mylist" { # resource "ybm_backup" "mybackup" { # cluster_id = ybm_cluster.single_region.cluster_id # backup_description = "backup" -# retention_period_in_days = 2 +# retention_period_in_days = 2 # } @@ -102,7 +98,7 @@ resource "ybm_vpc" "newvpc" { # cidr = "10.231.0.0/24" # }, # { - # region = "us-west2" + # region = "us-west2" # cidr = "10.9.0.0/24" # } # ] @@ -126,14 +122,14 @@ resource "ybm_read_replicas" "myrr" { primary_cluster_id = ybm_cluster.single_region.cluster_id } -resource "ybm_vpc_peering" "example_vpc_peering" { - name = "example_name" - yugabytedb_vpc_id = "example_vpc_id" - application_vpc_info = { - cloud = "GCP" - project = "example_project" - region = "us-west1" - vpc_id = "application_vpc_id" - cidr = "example_cidr" - } -} +# resource "ybm_vpc_peering" "example_vpc_peering" { +# name = "example_name" +# yugabytedb_vpc_id = "example_vpc_id" +# application_vpc_info = { +# cloud = "GCP" +# project = "example_project" +# region = "us-west1" +# vpc_id = "application_vpc_id" +# cidr = "example_cidr" +# } +# }