diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index d68ee3d..4c0ab14 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -40,7 +40,7 @@ jobs:
steps:
- name: Checkout repository
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
diff --git a/.github/workflows/combine-prs-workflow.yml b/.github/workflows/combine-prs-workflow.yml
index b7c3343..63fd4d4 100644
--- a/.github/workflows/combine-prs-workflow.yml
+++ b/.github/workflows/combine-prs-workflow.yml
@@ -31,7 +31,7 @@ jobs:
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
- - uses: actions/github-script@v6
+ - uses: actions/github-script@v7
id: create-combined-pr
name: Create Combined PR
with:
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 89d21f5..37fa68f 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -17,17 +17,17 @@ permissions:
env:
# Go language version to use for building. This value should also be updated
# in the testing workflow if changed.
- GO_VERSION: "1.19"
+ GO_VERSION: "1.21"
jobs:
goreleaser:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
with:
# Allow goreleaser to access older tag information.
fetch-depth: 0
- - uses: actions/setup-go@v4
+ - uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
# This uses an action (hashicorp/ghaction-import-gpg) that assumes you set your
@@ -36,7 +36,7 @@ jobs:
# or use an alternative one for key handling.
- name: Import GPG key
id: import_gpg
- uses: crazy-max/ghaction-import-gpg@v5.3.0
+ uses: crazy-max/ghaction-import-gpg@v6.1.0
with:
gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }}
passphrase: ${{ secrets.GPG_PASSPHRASE }}
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 845b4bb..b890fee 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -21,7 +21,7 @@ permissions:
env:
# Go language version to use for building. This value should also be updated
# in the release workflow if changed.
- GO_VERSION: "1.19"
+ GO_VERSION: "1.21"
jobs:
# Ensure project builds before running testing matrix
@@ -30,20 +30,20 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- - uses: actions/setup-go@v4
+ - uses: actions/checkout@v4
+ - uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
- - uses: actions/checkout@v3
- run: go mod download
- run: go build -v .
generate:
runs-on: ubuntu-latest
steps:
- - uses: actions/setup-go@v4
+ - uses: actions/checkout@v4
+ - uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
- - uses: actions/checkout@v3
- run: go generate ./...
- name: git diff
run: |
@@ -57,24 +57,31 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 30
strategy:
+ max-parallel: 1
fail-fast: false
matrix:
# list whatever Terraform versions here you would like to support
+ # jobs run in parallel -- some tests create resources with
+ # specific IDs which must be unique... some test resource randomization
+ # is needed but doesn't exist... Currently only testing w/ 1.6
+ # max-parallel: 1 should fix this!
+ # NOTE: required tests are configured in branch protection!
terraform:
# - "1.0.*"
# - "1.1.*"
# - "1.3.*"
- "1.4.*"
+ - "1.6.*"
steps:
- - uses: actions/setup-go@v4
+ - uses: actions/checkout@v4
+ - uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
- - uses: hashicorp/setup-terraform@v2
+ - run: go mod download
+ - uses: hashicorp/setup-terraform@v3
with:
terraform_version: ${{ matrix.terraform }}
terraform_wrapper: false
- - uses: actions/checkout@v3
- - run: go mod download
- env:
# for the time being, only do unit tests, below needs to be changed
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6ce71ce..ee9b7f0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,23 @@
Lists the changes in the provider.
+## Version 0.7.0
+
+- added support for "hide links" node resource property, fixes #80
+- added external connector data source
+- fixed integration test for groups data source
+- return error for external connector configuration when device name is provided instead of "NAT" or "System Bridge", fixes #81
+- updated all package dependencies
+- fix CPULimit property for UMS and ExtConn (they are now always NULL starting with 2.6.0)
+- some cosmetic and test changes
+- added a add-to-booted-lab lifecycle test (addresses #75 but can't reproduce)
+- formatted codebase w/ gofumpt
+- removed cmlclient go.mod local replace and updated cmlclient to 0.0.22 in go.mod
+- added / updated docs and ran generate
+- bumped go version to 1.21 in the workflows
+- added an extconn schema test
+- updated gh action components, only run one test suite in parallel
+
## Version 0.6.2
- The provider (via gocmlclient) now honors proxy configuration provided via environment variables `HTTP_PROXY`, `HTTPS_PROXY` and `NO_PROXY` (or the lowercase versions thereof). `HTTPS_PROXY` takes precedence over `HTTP_PROXY` for https requests.
diff --git a/README.md b/README.md
index e746b87..3c81fb8 100644
--- a/README.md
+++ b/README.md
@@ -17,17 +17,23 @@ The current implementation provides:
- resource `cml2_node` to create, update and destroy nodes in a lab
- resource `cml2_link` to create, update and destroy links between nodes in a lab
- resource `cml2_lifecycle` to control the state of a lab (like `STARTED`, `STOPPED`), including staged starting and configuration injection
+ - resource `cml2_group` to create, update and destroy groups
+ - resource `cml2_user` to create, update and destroy users
- data source `cml2_lab` to retrieve state of an existing lab
- data source `cml2_node` to retrieve state of an existing node in a lab
- - data source `cml2_image` to retrieve the available node images from the controller
+ - data source `cml2_images` to retrieve the available node images from the controller
+ - data source `cml2_groups` to retrieve user groups from the controller
+ - data source `cml2_extconn` to retrieve external connector information from the controller
+ - data source `cml2_system` to retrieve system state (ready state, version, ...) from the controller
+ - data source `cml2_users` to retrieve users from the controller
- Examples (`examples/`) and generated documentation (`docs/`),
- Miscellaneous meta files.
## Requirements
- [Terraform](https://www.terraform.io/downloads.html) >= 1.0
-- [Go](https://golang.org/doc/install) >= 1.18
-- [CML2](https://cisco.com/go/cml) >= 2.4.0
+- [Go](https://golang.org/doc/install) >= 1.21
+- [CML2](https://cisco.com/go/cml) >= 2.6.0
## Building The Provider
diff --git a/TODO.md b/TODO.md
index f4c66eb..1fd52a1 100644
--- a/TODO.md
+++ b/TODO.md
@@ -4,12 +4,14 @@ As this provider is "work-in-progress", there's still plenty of work to do.
- additional resources and data sources
- better test coverage(unit/acceptance)
+- figure out if/how fits this provider
Especially the first bullet requires some discussion in terms of what makes
sense and what doesn't.
## Items Done
+- added external connector data source
- added group and user resources and data sources
- basic acceptance tests
- documentation (content, consistency)
diff --git a/docs/data-sources/connector.md b/docs/data-sources/connector.md
new file mode 100644
index 0000000..e3096c0
--- /dev/null
+++ b/docs/data-sources/connector.md
@@ -0,0 +1,38 @@
+---
+# generated by https://github.com/hashicorp/terraform-plugin-docs
+page_title: "cml2_connector Data Source - terraform-provider-cml2"
+subcategory: ""
+description: |-
+ A data source that retrieves external connectors information from the controller.
+---
+
+# cml2_connector (Data Source)
+
+A data source that retrieves external connectors information from the controller.
+
+
+
+
+## Schema
+
+### Optional
+
+- `label` (String) A connector label to filter the connector list returned by the controller. Connector labels must be unique, so it's either one group or no group at all if a name filter is provided.
+- `tag` (String) A tag name to filter the groups list returned by the controller. Connector tags can be defined on multiple connectors, a list can be returned.
+
+### Read-Only
+
+- `connectors` (Attributes List) A list of all permission groups available on the controller. (see [below for nested schema](#nestedatt--connectors))
+- `id` (String) A UUID. The presence of the ID attribute is mandated by the framework. The attribute is a random UUID and has no actual significance.
+
+
+### Nested Schema for `connectors`
+
+Read-Only:
+
+- `device_name` (String) the actual (Linux network) device name of the external connector.
+- `id` (String) External connector identifier, a UUID.
+- `label` (String) The label of the external connector, like "NAT" or "System Bridge".
+- `protected` (Boolean) Whether the connector is protected, e.g. BPDUs are filtered or not.
+- `snooped` (Boolean) True if the IP address snooper listens on this connector.
+- `tags` (Set of String) The external connector tag set.
diff --git a/docs/data-sources/groups.md b/docs/data-sources/groups.md
index d39811c..b9499e0 100644
--- a/docs/data-sources/groups.md
+++ b/docs/data-sources/groups.md
@@ -58,5 +58,3 @@ Read-Only:
- `id` (String) Lab ID (UUID).
- `permission` (String) Permission.
-
-
diff --git a/docs/data-sources/images.md b/docs/data-sources/images.md
index 7325906..f33d9c2 100644
--- a/docs/data-sources/images.md
+++ b/docs/data-sources/images.md
@@ -63,5 +63,3 @@ Read-Only:
- `ram` (Number) Image specific RAM value, can be null
- `read_only` (Boolean) Is this image definition read only?
- `schema_version` (String) Version of the image definition schemage
-
-
diff --git a/docs/data-sources/lab.md b/docs/data-sources/lab.md
index 92f24e9..8513a33 100644
--- a/docs/data-sources/lab.md
+++ b/docs/data-sources/lab.md
@@ -66,5 +66,3 @@ Read-Only:
- `id` (String) Group ID (UUID).
- `name` (String) Descriptive group name.
- `permission` (String) Permission, either `read_only` or `read_write`.
-
-
diff --git a/docs/data-sources/node.md b/docs/data-sources/node.md
index e0b37dd..d50b0c3 100644
--- a/docs/data-sources/node.md
+++ b/docs/data-sources/node.md
@@ -48,6 +48,7 @@ Read-Only:
- `cpu_limit` (Number) CPU limit in %, 20-100. Can be changed until the node is started once. Will require a replace in that case.
- `cpus` (Number) Number of CPUs. Can be changed until the node is started once. Will require a replace in that case.
- `data_volume` (Number) Size of data volume, in GB. Can be changed until the node is started once. Will require a replace in that case.
+- `hide_links` (Boolean) If true, links are not shown in the topology. This is a visual cue and does not influence any simulation function.
- `id` (String) Node ID (UUID).
- `imagedefinition` (String) Image definition, must match the node type. Can be changed until the node is started once. Will require a replace in that case.
- `interfaces` (Attributes List) List of interfaces on the node. (see [below for nested schema](#nestedatt--node--interfaces))
@@ -83,5 +84,3 @@ Read-Only:
- `console_key` (String)
- `device_number` (Number)
-
-
diff --git a/docs/data-sources/system.md b/docs/data-sources/system.md
index 1002042..94eb0d1 100644
--- a/docs/data-sources/system.md
+++ b/docs/data-sources/system.md
@@ -37,5 +37,3 @@ output "readiness" {
- `id` (String) A UUID. The presence of the ID attribute is mandated by the framework. The attribute is a random UUID and has no actual significance.
- `version` (String) The system software version.
-
-
diff --git a/docs/data-sources/users.md b/docs/data-sources/users.md
index ed35baf..bafc080 100644
--- a/docs/data-sources/users.md
+++ b/docs/data-sources/users.md
@@ -57,5 +57,3 @@ Read-Only:
- `password` (String, Sensitive) Password of the user.
- `resource_pool` (String) Resource pool ID, if any.
- `username` (String) Login name of the user.
-
-
diff --git a/docs/resources/group.md b/docs/resources/group.md
index 882f65e..b8b141b 100644
--- a/docs/resources/group.md
+++ b/docs/resources/group.md
@@ -76,5 +76,3 @@ Required:
- `id` (String) Lab ID (UUID).
- `permission` (String) Permission.
-
-
diff --git a/docs/resources/lab.md b/docs/resources/lab.md
index 36dce6e..e579b59 100644
--- a/docs/resources/lab.md
+++ b/docs/resources/lab.md
@@ -93,5 +93,3 @@ Optional:
Read-Only:
- `name` (String) Descriptive group name.
-
-
diff --git a/docs/resources/lifecycle.md b/docs/resources/lifecycle.md
index 56692f5..11f35bc 100644
--- a/docs/resources/lifecycle.md
+++ b/docs/resources/lifecycle.md
@@ -198,6 +198,7 @@ Optional:
- `cpu_limit` (Number) CPU limit in %, 20-100. Can be changed until the node is started once. Will require a replace in that case.
- `cpus` (Number) Number of CPUs. Can be changed until the node is started once. Will require a replace in that case.
- `data_volume` (Number) Size of data volume, in GB. Can be changed until the node is started once. Will require a replace in that case.
+- `hide_links` (Boolean) If true, links are not shown in the topology. This is a visual cue and does not influence any simulation function.
- `imagedefinition` (String) Image definition, must match the node type. Can be changed until the node is started once. Will require a replace in that case.
- `ram` (Number) Amount of RAM, megabytes. Can be changed until the node is started once. Will require a replace in that case.
- `tags` (Set of String) Set of tags of the node.
@@ -234,5 +235,3 @@ Read-Only:
- `console_key` (String)
- `device_number` (Number)
-
-
diff --git a/docs/resources/link.md b/docs/resources/link.md
index 5ba917b..2740a48 100644
--- a/docs/resources/link.md
+++ b/docs/resources/link.md
@@ -34,5 +34,3 @@ A link resource represents a CML link. At create time, the lab ID, source and de
- `label` (String) link label (auto generated).
- `link_capture_key` (String) link capture key (when running).
- `state` (String) Link state.
-
-
diff --git a/docs/resources/node.md b/docs/resources/node.md
index 263b879..9d69ebd 100644
--- a/docs/resources/node.md
+++ b/docs/resources/node.md
@@ -3,12 +3,12 @@
page_title: "cml2_node Resource - terraform-provider-cml2"
subcategory: ""
description: |-
- A node resource represents a CML node. At create time, the lab ID, a node definition and a label must be provided. Other attributes are optional. Note that some attributes can't be changed after the node state has changed to STARTED (see the lifecyle resource) once. Changing attributes will then require a replace.
+ A node resource represents a CML node. At create time, the lab ID, a node definition and a label must be provided. Other attributes are optional. Note that some attributes can't be changed after the node state has changed to STARTED (see the lifecyle resource) once. Changing attributes will then require a replace. Node configurations are "day zero" configurations. Replacing a configuration typically requires a node replacement if the node has been started. No Configurations can be provided for unmanaged switches. External connectors require the connector label (like "NAT"), not the device name (like "virbr0"). The available connectors can be retrieved via the external connector data source.
---
# cml2_node (Resource)
-A node resource represents a CML node. At create time, the lab ID, a node definition and a label must be provided. Other attributes are optional. Note that some attributes can't be changed after the node state has changed to `STARTED` (see the lifecyle resource) once. Changing attributes will then require a replace.
+A node resource represents a CML node. At create time, the lab ID, a node definition and a label must be provided. Other attributes are optional. Note that some attributes can't be changed after the node state has changed to `STARTED` (see the `lifecyle` resource) once. Changing attributes will then require a replace. Node configurations are "day zero" configurations. Replacing a configuration typically requires a node replacement if the node has been started. No Configurations can be provided for unmanaged switches. External connectors require the connector label (like "NAT"), not the device name (like "virbr0"). The available connectors can be retrieved via the external connector data source.
@@ -28,6 +28,7 @@ A node resource represents a CML node. At create time, the lab ID, a node defini
- `cpu_limit` (Number) CPU limit in %, 20-100. Can be changed until the node is started once. Will require a replace in that case.
- `cpus` (Number) Number of CPUs. Can be changed until the node is started once. Will require a replace in that case.
- `data_volume` (Number) Size of data volume, in GB. Can be changed until the node is started once. Will require a replace in that case.
+- `hide_links` (Boolean) If true, links are not shown in the topology. This is a visual cue and does not influence any simulation function.
- `imagedefinition` (String) Image definition, must match the node type. Can be changed until the node is started once. Will require a replace in that case.
- `ram` (Number) Amount of RAM, megabytes. Can be changed until the node is started once. Will require a replace in that case.
- `tags` (Set of String) Set of tags of the node.
@@ -64,5 +65,3 @@ Read-Only:
- `console_key` (String)
- `device_number` (Number)
-
-
diff --git a/docs/resources/user.md b/docs/resources/user.md
index 6d2e554..f53ab4b 100644
--- a/docs/resources/user.md
+++ b/docs/resources/user.md
@@ -48,5 +48,3 @@ resource "cml2_user" "student1" {
- `id` (String) User ID (UUID).
- `labs` (Set of String) Set of lab IDs the user owns.
- `opt_in` (Boolean) True if has opted in to sending telemetry data.
-
-
diff --git a/examples/data-sources/cml2_connector/data_source.tf b/examples/data-sources/cml2_connector/data_source.tf
new file mode 100644
index 0000000..6ecb290
--- /dev/null
+++ b/examples/data-sources/cml2_connector/data_source.tf
@@ -0,0 +1,15 @@
+# Get a list of all connectors on the system with either the provided tag (the
+# result can have multiple elements) or with a specific name/label (the result
+# has exactly one or zero elements if the label does not exist).
+
+data "cml2_connector" "nat" {
+ tag = "NAT"
+ # Alternatively (or in combination, logical AND):
+ # label = "System Bridge"
+}
+
+output "nat_connector" {
+ # The label can be used as the configuration of an external connector node
+ # The ID is mostly for internal use.
+ value = data.cml2_connector.nat.connectors[0].label
+}
diff --git a/go.mod b/go.mod
index 96d7af4..c5f3e1a 100644
--- a/go.mod
+++ b/go.mod
@@ -1,53 +1,53 @@
module github.com/rschmied/terraform-provider-cml2
-go 1.19
+go 1.21
require (
- github.com/google/uuid v1.3.0
- github.com/hashicorp/terraform-plugin-docs v0.14.1
- github.com/hashicorp/terraform-plugin-framework v1.2.0
- github.com/hashicorp/terraform-plugin-go v0.15.0
- github.com/hashicorp/terraform-plugin-log v0.8.0
- github.com/hashicorp/terraform-plugin-sdk/v2 v2.26.1
- github.com/rschmied/gocmlclient v0.0.21
- github.com/stretchr/testify v1.8.2
+ github.com/google/uuid v1.5.0
+ github.com/hashicorp/terraform-plugin-docs v0.16.0
+ github.com/hashicorp/terraform-plugin-framework v1.4.2
+ github.com/hashicorp/terraform-plugin-go v0.20.0
+ github.com/hashicorp/terraform-plugin-log v0.9.0
+ github.com/hashicorp/terraform-plugin-sdk/v2 v2.31.0
+ github.com/rschmied/gocmlclient v0.0.22
+ github.com/stretchr/testify v1.8.4
)
require (
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/semver/v3 v3.2.1 // indirect
github.com/Masterminds/sprig/v3 v3.2.3 // indirect
- github.com/ProtonMail/go-crypto v0.0.0-20230426101702-58e86b294756 // indirect
+ github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 // indirect
github.com/agext/levenshtein v1.2.3 // 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/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.15.0 // indirect
+ 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/google/go-cmp v0.6.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-cty v1.4.1-0.20200414143053-d3edf31b6320 // indirect
- github.com/hashicorp/go-hclog v1.5.0 // indirect
+ github.com/hashicorp/go-hclog v1.6.2 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
- github.com/hashicorp/go-plugin v1.4.9 // indirect
+ github.com/hashicorp/go-plugin v1.6.0 // 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.5.2 // indirect
- github.com/hashicorp/hcl/v2 v2.16.2 // indirect
+ github.com/hashicorp/hc-install v0.6.2 // indirect
+ github.com/hashicorp/hcl/v2 v2.19.1 // indirect
github.com/hashicorp/logutils v1.0.0 // indirect
- github.com/hashicorp/terraform-exec v0.18.1 // indirect
- github.com/hashicorp/terraform-json v0.16.0 // indirect
- github.com/hashicorp/terraform-registry-address v0.2.0 // indirect
- github.com/hashicorp/terraform-svchost v0.1.0 // indirect
+ github.com/hashicorp/terraform-exec v0.19.0 // indirect
+ github.com/hashicorp/terraform-json v0.18.0 // indirect
+ github.com/hashicorp/terraform-registry-address v0.2.3 // indirect
+ github.com/hashicorp/terraform-svchost v0.1.1 // indirect
github.com/hashicorp/yamux v0.1.1 // indirect
github.com/huandu/xstrings v1.4.0 // indirect
github.com/imdario/mergo v0.3.15 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
- github.com/mattn/go-isatty v0.0.18 // indirect
+ github.com/mattn/go-isatty v0.0.20 // 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
@@ -61,19 +61,20 @@ require (
github.com/shopspring/decimal v1.3.1 // indirect
github.com/spf13/cast v1.5.1 // indirect
github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect
- github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect
+ github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
- github.com/zclconf/go-cty v1.13.1 // indirect
- golang.org/x/crypto v0.9.0 // indirect
- golang.org/x/mod v0.10.0 // indirect
- golang.org/x/net v0.10.0 // indirect
- golang.org/x/sync v0.2.0 // indirect
- golang.org/x/sys v0.8.0 // indirect
- golang.org/x/text v0.9.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.55.0 // indirect
- google.golang.org/protobuf v1.30.0 // indirect
+ github.com/zclconf/go-cty v1.14.1 // indirect
+ golang.org/x/crypto v0.16.0 // indirect
+ golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df // indirect
+ golang.org/x/mod v0.14.0 // indirect
+ golang.org/x/net v0.19.0 // indirect
+ golang.org/x/sync v0.5.0 // indirect
+ golang.org/x/sys v0.15.0 // indirect
+ golang.org/x/text v0.14.0 // indirect
+ google.golang.org/appengine v1.6.8 // indirect
+ google.golang.org/genproto/googleapis/rpc v0.0.0-20231212172506-995d672761c0 // indirect
+ google.golang.org/grpc v1.60.1 // indirect
+ google.golang.org/protobuf v1.32.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
diff --git a/go.sum b/go.sum
index 5ad7e40..a9ab81e 100644
--- a/go.sum
+++ b/go.sum
@@ -1,3 +1,5 @@
+dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
+dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
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/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
@@ -7,50 +9,61 @@ github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYr
github.com/Masterminds/sprig/v3 v3.2.1/go.mod h1:UoaO7Yp8KlPnJIYWTFkMaqPUYKTfGFPhxNuwnnxkKlk=
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/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA=
-github.com/ProtonMail/go-crypto v0.0.0-20230426101702-58e86b294756 h1:L6S7kR7SlhQKplIBpkra3s6yhcZV51lhRnXmYc4HohI=
-github.com/ProtonMail/go-crypto v0.0.0-20230426101702-58e86b294756/go.mod h1:8TI4H3IbrackdNgv+92dI+rhpCaLqM0IfpgCgenFvRE=
-github.com/acomagu/bufpipe v1.0.4 h1:e3H4WUzM3npvo5uv95QuJM3cQspFNtFBzvJ2oNjKIDQ=
+github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
+github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
+github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 h1:kkhsdkhsCvIsutKu5zLMgWtgh9YxGCNAw8Ad8hjwfYg=
+github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo=
github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558=
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/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
-github.com/bwesterb/go-ristretto v1.2.0/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
-github.com/cloudflare/circl v1.1.0/go.mod h1:prBCrKB9DV4poKZY1l9zBXg2QJY7mvgRvtMxxK7fi4I=
+github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA=
+github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8=
+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/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg=
+github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
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/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
+github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
-github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
-github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
+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/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY=
-github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4=
-github.com/go-git/go-billy/v5 v5.4.1 h1:Uwp5tDRkPr+l/TnbHOQzp+tmJfLceOlbVucgpTz8ix4=
-github.com/go-git/go-git/v5 v5.6.1 h1:q4ZRqQl4pR/ZJHc1L5CFjGA1a10u76aV1iC+nh+bHsk=
+github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
+github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
+github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
+github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU=
+github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow=
+github.com/go-git/go-git/v5 v5.10.1 h1:tu8/D8i+TWxgKpzQ3Vc43e+kkhXqtsZCKI/egajKnxk=
+github.com/go-git/go-git/v5 v5.10.1/go.mod h1:uEuHjxkHap8kAl//V5F/nNWwqIYtP/402ddd05mp0wg=
github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68=
+github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
+github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
+github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/protobuf v1.1.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.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
+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/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
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/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.2/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/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU=
+github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
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=
@@ -61,42 +74,42 @@ github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9n
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.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.2 h1:NOtoftovWkDheyUM/8JW3QMiXyxJK3uHRK7wV04nD2I=
+github.com/hashicorp/go-hclog v1.6.2/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.9 h1:ESiK220/qE0aGxWdzKIvRH69iLiuN/PjoLTm69RoWtU=
-github.com/hashicorp/go-plugin v1.4.9/go.mod h1:viDMjcLJuDui6pXb8U4HVfb8AamCWhHGUjr2IrTF67s=
+github.com/hashicorp/go-plugin v1.6.0 h1:wgd4KxHJTVGGqWBq4QPB1i5BZNEx9BR8+OFmHDmTk8A=
+github.com/hashicorp/go-plugin v1.6.0/go.mod h1:lBS5MtSSBZk0SHc66KACcjjlU6WzEVP/8pwz68aMkCI=
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.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek=
github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
-github.com/hashicorp/hc-install v0.5.2 h1:SfwMFnEXVVirpwkDuSF5kymUOhrUxrTq3udEseZdOD0=
-github.com/hashicorp/hc-install v0.5.2/go.mod h1:9QISwe6newMWIfEiXpzuu1k9HAGtQYgnSH8H9T8wmoI=
-github.com/hashicorp/hcl/v2 v2.16.2 h1:mpkHZh/Tv+xet3sy3F9Ld4FyI2tUpWe9x3XtPx9f1a0=
-github.com/hashicorp/hcl/v2 v2.16.2/go.mod h1:JRmR89jycNkrrqnMmvPDMd56n1rQJ2Q6KocSLCMCXng=
+github.com/hashicorp/hc-install v0.6.2 h1:V1k+Vraqz4olgZ9UzKiAcbman9i9scg9GgSt/U3mw/M=
+github.com/hashicorp/hc-install v0.6.2/go.mod h1:2JBpd+NCFKiHiu/yYCGaPyPHhZLxXTpz8oreHa/a3Ps=
+github.com/hashicorp/hcl/v2 v2.19.1 h1://i05Jqznmb2EXqa39Nsvyan2o5XyMowW5fnCKW5RPI=
+github.com/hashicorp/hcl/v2 v2.19.1/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.18.1 h1:LAbfDvNQU1l0NOQlTuudjczVhHj061fNX5H8XZxHlH4=
-github.com/hashicorp/terraform-exec v0.18.1/go.mod h1:58wg4IeuAJ6LVsLUeD2DWZZoc/bYi6dzhLHzxM41980=
-github.com/hashicorp/terraform-json v0.16.0 h1:UKkeWRWb23do5LNAFlh/K3N0ymn1qTOO8c+85Albo3s=
-github.com/hashicorp/terraform-json v0.16.0/go.mod h1:v0Ufk9jJnk6tcIZvScHvetlKfiNTC+WS21mnXIlc0B0=
-github.com/hashicorp/terraform-plugin-docs v0.14.1 h1:MikFi59KxrP/ewrZoaowrB9he5Vu4FtvhamZFustiA4=
-github.com/hashicorp/terraform-plugin-docs v0.14.1/go.mod h1:k2NW8+t113jAus6bb5tQYQgEAX/KueE/u8X2Z45V1GM=
-github.com/hashicorp/terraform-plugin-framework v1.2.0 h1:MZjFFfULnFq8fh04FqrKPcJ/nGpHOvX4buIygT3MSNY=
-github.com/hashicorp/terraform-plugin-framework v1.2.0/go.mod h1:nToI62JylqXDq84weLJ/U3umUsBhZAaTmU0HXIVUOcw=
-github.com/hashicorp/terraform-plugin-go v0.15.0 h1:1BJNSUFs09DS8h/XNyJNJaeusQuWc/T9V99ylU9Zwp0=
-github.com/hashicorp/terraform-plugin-go v0.15.0/go.mod h1:tk9E3/Zx4RlF/9FdGAhwxHExqIHHldqiQGt20G6g+nQ=
-github.com/hashicorp/terraform-plugin-log v0.8.0 h1:pX2VQ/TGKu+UU1rCay0OlzosNKe4Nz1pepLXj95oyy0=
-github.com/hashicorp/terraform-plugin-log v0.8.0/go.mod h1:1myFrhVsBLeylQzYYEV17VVjtG8oYPRFdaZs7xdW2xs=
-github.com/hashicorp/terraform-plugin-sdk/v2 v2.26.1 h1:G9WAfb8LHeCxu7Ae8nc1agZlQOSCUWsb610iAogBhCs=
-github.com/hashicorp/terraform-plugin-sdk/v2 v2.26.1/go.mod h1:xcOSYlRVdPLmDUoqPhO9fiO/YCN/l6MGYeTzGt5jgkQ=
-github.com/hashicorp/terraform-registry-address v0.2.0 h1:92LUg03NhfgZv44zpNTLBGIbiyTokQCDcdH5BhVHT3s=
-github.com/hashicorp/terraform-registry-address v0.2.0/go.mod h1:478wuzJPzdmqT6OGbB/iH82EDcI8VFM4yujknh/1nIs=
-github.com/hashicorp/terraform-svchost v0.1.0 h1:0+RcgZdZYNd81Vw7tu62g9JiLLvbOigp7QtyNh6CjXk=
-github.com/hashicorp/terraform-svchost v0.1.0/go.mod h1:ut8JaH0vumgdCfJaihdcZULqkAwHdQNwNH7taIDdsZM=
+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.18.0 h1:pCjgJEqqDESv4y0Tzdqfxr/edOIGkjs8keY42xfNBwU=
+github.com/hashicorp/terraform-json v0.18.0/go.mod h1:qdeBs11ovMzo5puhrRibdD6d2Dq6TyE/28JiU4tIQxk=
+github.com/hashicorp/terraform-plugin-docs v0.16.0 h1:UmxFr3AScl6Wged84jndJIfFccGyBZn52KtMNsS12dI=
+github.com/hashicorp/terraform-plugin-docs v0.16.0/go.mod h1:M3ZrlKBJAbPMtNOPwHicGi1c+hZUh7/g0ifT/z7TVfA=
+github.com/hashicorp/terraform-plugin-framework v1.4.2 h1:P7a7VP1GZbjc4rv921Xy5OckzhoiO3ig6SGxwelD2sI=
+github.com/hashicorp/terraform-plugin-framework v1.4.2/go.mod h1:GWl3InPFZi2wVQmdVnINPKys09s9mLmTZr95/ngLnbY=
+github.com/hashicorp/terraform-plugin-go v0.20.0 h1:oqvoUlL+2EUbKNsJbIt3zqqZ7wi6lzn4ufkn/UA51xQ=
+github.com/hashicorp/terraform-plugin-go v0.20.0/go.mod h1:Rr8LBdMlY53a3Z/HpP+ZU3/xCDqtKNCkeI9qOyT10QE=
+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.31.0 h1:Bl3e2ei2j/Z3Hc2HIS15Gal2KMKyLAZ2om1HCEvK6es=
+github.com/hashicorp/terraform-plugin-sdk/v2 v2.31.0/go.mod h1:i2C41tszDjiWfziPQDL5R/f3Zp0gahXe5No/MIO9rCE=
+github.com/hashicorp/terraform-registry-address v0.2.3 h1:2TAiKJ1A3MAkZlH1YI/aTVcLZRu7JseiXNRHbOAyoTI=
+github.com/hashicorp/terraform-registry-address v0.2.3/go.mod h1:lFHA76T8jfQteVfT7caREqguFrW3c4MFSPhZB7HHgUM=
+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.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE=
github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
@@ -108,14 +121,20 @@ github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH
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/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
-github.com/jhump/protoreflect v1.6.0 h1:h5jfMVslIg6l29nsMs0D8Wj17RDVdNYti0vDN/PZZoE=
+github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
+github.com/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c=
+github.com/jhump/protoreflect v1.15.1/go.mod h1:jD/2GMKKE6OqX8qTjhADU1e6DShO+gavG9e0Q693nKo=
github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
+github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
+github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
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 v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
+github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
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/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
@@ -125,8 +144,8 @@ 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/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.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98=
-github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
+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/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=
@@ -144,76 +163,80 @@ github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx
github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA=
github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU=
github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4=
+github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI=
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.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/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
-github.com/rschmied/gocmlclient v0.0.21 h1:yPwr5yy0P6Hs/JM3qzvqLfCboDRsE4PpOYn/kOUPN6I=
-github.com/rschmied/gocmlclient v0.0.21/go.mod h1:AxuKqPKsWwqRtThJk5Ozi8B2Hp7/dR/A94zDq3gLQ90=
+github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
+github.com/rschmied/gocmlclient v0.0.22 h1:tXCvhHLlLMUctfWQbx0/DuAIIMTf5IpFA+Ji28+t5fM=
+github.com/rschmied/gocmlclient v0.0.22/go.mod h1:Mf7+8KCjld5AnN+r6LYo3oYVkdPoKtv9+UjxWsLZJTs=
github.com/rschmied/mockresponder v1.0.4 h1:VFXa9Y9QJ/5oZFhKoqh9u3HQlbjcBfE9pxI+BanMlEs=
+github.com/rschmied/mockresponder v1.0.4/go.mod h1:+EEq2xxKOQNbJTTvfqmjYh1zPPCKnZBthHzaZAJSExg=
github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww=
github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY=
github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
+github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
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/skeema/knownhosts v1.1.0 h1:Wvr9V0MxhjRbl3f9nMnKnFfiWTJmtECJ9Njkea3ysW0=
+github.com/skeema/knownhosts v1.2.1 h1:SHWdIUa82uGZz+F+47k8SY4QhhI291cXCpopT1lK2AQ=
+github.com/skeema/knownhosts v1.2.1/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo=
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA=
github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
-github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
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.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
-github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
-github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
-github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
+github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
+github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
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/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/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8=
+github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok=
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/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
-github.com/zclconf/go-cty v1.13.1 h1:0a6bRwuiSHtAmqCqNOE+c2oHgepv0ctoxU4FUe43kwc=
-github.com/zclconf/go-cty v1.13.1/go.mod h1:YKQzy/7pZ7iq2jNFzy5go57xdxdWoLLpaEp4u238AE0=
+github.com/zclconf/go-cty v1.14.1 h1:t9fyA35fwjjUMcmL5hLER+e/rEPqrbCK1/OSE4SI9KA=
+github.com/zclconf/go-cty v1.14.1/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/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.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.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g=
-golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
+golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY=
+golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
+golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df h1:UA2aFVmmsIlefxMk29Dp2juaUSth8Pyn3Tq5Y5mJGME=
+golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
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.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk=
-golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
+golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
+golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
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-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
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.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
-golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
+golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
+golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/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-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI=
-golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
+golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -222,16 +245,16 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w
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-20211007075335-d3039528d8ac/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.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.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
-golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
+golang.org/x/sys v0.15.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=
@@ -241,32 +264,36 @@ 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.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
+golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
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.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
-golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
+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/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
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/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
+golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ=
+golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
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.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
-google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
-google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A=
-google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU=
-google.golang.org/grpc v1.55.0 h1:3Oj82/tFSCeUrRTg/5E/7d/W5A1tj6Ky1ABAuZuv5ag=
-google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8=
+google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=
+google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20231212172506-995d672761c0 h1:/jFB8jK5R3Sq3i/lmeZO0cATSzFfZaJq1J2Euan3XKU=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20231212172506-995d672761c0/go.mod h1:FUoWkonphQm3RhTS+kOEhF8h0iDpm4tdXolVCeZ9KKA=
+google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU=
+google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM=
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.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
-google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
+google.golang.org/protobuf v1.32.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 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
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.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
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=
diff --git a/internal/cmlschema/extconn.go b/internal/cmlschema/extconn.go
new file mode 100644
index 0000000..54a10c1
--- /dev/null
+++ b/internal/cmlschema/extconn.go
@@ -0,0 +1,121 @@
+package cmlschema
+
+import (
+ "context"
+
+ "github.com/hashicorp/terraform-plugin-framework/attr"
+ "github.com/hashicorp/terraform-plugin-framework/diag"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/boolplanmodifier"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/setplanmodifier"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
+ "github.com/hashicorp/terraform-plugin-framework/tfsdk"
+ "github.com/hashicorp/terraform-plugin-framework/types"
+ cmlclient "github.com/rschmied/gocmlclient"
+)
+
+// ExtConnModel is the TF representation of a CML2 External Connector (no
+// operational data at the moment)
+type ExtConnModel struct {
+ ID types.String `tfsdk:"id"`
+ DeviceName types.String `tfsdk:"device_name"`
+ Label types.String `tfsdk:"label"`
+ Protected types.Bool `tfsdk:"protected"`
+ Snooped types.Bool `tfsdk:"snooped"`
+ Tags types.Set `tfsdk:"tags"`
+}
+
+// ExtConnAttrType has the attribute types of a CML2 ExtConnModel
+var ExtConnAttrType = map[string]attr.Type{
+ "id": types.StringType,
+ "device_name": types.StringType,
+ "label": types.StringType,
+ "protected": types.BoolType,
+ "snooped": types.BoolType,
+ "tags": types.SetType{
+ ElemType: types.StringType,
+ },
+}
+
+// ExtConn returns the schema for the ExtConn model
+func ExtConn() map[string]schema.Attribute {
+ return map[string]schema.Attribute{
+ "id": schema.StringAttribute{
+ Computed: true,
+ Description: "External connector identifier, a UUID.",
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.UseStateForUnknown(),
+ },
+ },
+ "device_name": schema.StringAttribute{
+ Computed: true,
+ MarkdownDescription: "the actual (Linux network) device name of the external connector.",
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.UseStateForUnknown(),
+ },
+ },
+ "label": schema.StringAttribute{
+ Computed: true,
+ Description: "The label of the external connector, like \"NAT\" or \"System Bridge\".",
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.UseStateForUnknown(),
+ },
+ },
+ "protected": schema.BoolAttribute{
+ Computed: true,
+ Description: "Whether the connector is protected, e.g. BPDUs are filtered or not.",
+ PlanModifiers: []planmodifier.Bool{
+ boolplanmodifier.UseStateForUnknown(),
+ },
+ },
+ "snooped": schema.BoolAttribute{
+ Computed: true,
+ Description: "True if the IP address snooper listens on this connector.",
+ PlanModifiers: []planmodifier.Bool{
+ boolplanmodifier.UseStateForUnknown(),
+ },
+ },
+ "tags": schema.SetAttribute{
+ Description: "The external connector tag set.",
+ Computed: true,
+ ElementType: types.StringType,
+ PlanModifiers: []planmodifier.Set{
+ setplanmodifier.UseStateForUnknown(),
+ },
+ },
+ }
+}
+
+// NewExtConn creates a TF value from a CML2 extconn object from the gocmlclient
+func NewExtConn(ctx context.Context, extconn *cmlclient.ExtConn, diags *diag.Diagnostics) attr.Value {
+ valueSet := make([]attr.Value, 0)
+ for _, tag := range extconn.Tags {
+ valueSet = append(valueSet, types.StringValue(tag))
+ }
+ tags, diag := types.SetValue(
+ types.StringType,
+ valueSet,
+ )
+ diags.Append(diag...)
+
+ newConnector := ExtConnModel{
+ ID: types.StringValue(extconn.ID),
+ DeviceName: types.StringValue(extconn.DeviceName),
+ Label: types.StringValue(extconn.Label),
+ Protected: types.BoolValue(extconn.Protected),
+ Snooped: types.BoolValue(extconn.Snooped),
+ Tags: tags,
+ }
+
+ var value attr.Value
+ diags.Append(
+ tfsdk.ValueFrom(
+ ctx,
+ newConnector,
+ types.ObjectType{AttrTypes: ExtConnAttrType},
+ &value,
+ )...,
+ )
+ return value
+}
diff --git a/internal/cmlschema/extconn_test.go b/internal/cmlschema/extconn_test.go
new file mode 100644
index 0000000..c45b958
--- /dev/null
+++ b/internal/cmlschema/extconn_test.go
@@ -0,0 +1,61 @@
+package cmlschema_test
+
+import (
+ "context"
+ "testing"
+
+ "github.com/hashicorp/terraform-plugin-framework/datasource/schema"
+ "github.com/hashicorp/terraform-plugin-framework/diag"
+ "github.com/hashicorp/terraform-plugin-framework/path"
+ "github.com/hashicorp/terraform-plugin-framework/tfsdk"
+ "github.com/hashicorp/terraform-plugin-framework/types"
+ cmlclient "github.com/rschmied/gocmlclient"
+ "github.com/rschmied/terraform-provider-cml2/internal/cmlschema"
+ "github.com/stretchr/testify/assert"
+)
+
+var conn1 *cmlclient.ExtConn = &cmlclient.ExtConn{
+ Label: "NAT",
+ DeviceName: "virbr0",
+ Protected: false,
+ Snooped: true,
+ Tags: []string{
+ "NAT",
+ },
+ ID: "58568fbb-e1f8-4b83-a1f8-148c656eed39",
+}
+
+var conn2 *cmlclient.ExtConn = &cmlclient.ExtConn{
+ Label: "System Bridge",
+ DeviceName: "bridge0",
+ Protected: true,
+ Snooped: true,
+ Tags: []string{
+ "System Bridge",
+ },
+ ID: "92f95da2-10fd-4a25-931e-acb31a47962c",
+}
+
+func TestConnector(t *testing.T) {
+ diag := &diag.Diagnostics{}
+ ctx := context.Background()
+
+ for _, connector := range []*cmlclient.ExtConn{conn1, conn2} {
+ value := cmlschema.NewExtConn(ctx, connector, diag)
+ t.Logf("value: %+v", value)
+ t.Logf("errors: %+v", diag.Errors())
+ assert.False(t, diag.HasError())
+ var newExtConn cmlschema.ExtConnModel
+ diag.Append(tfsdk.ValueAs(ctx, value, &newExtConn)...)
+ }
+ assert.False(t, diag.HasError())
+}
+
+func TestExtConnSchema(t *testing.T) {
+ extconnSchema := schema.Schema{
+ Attributes: cmlschema.Converter(cmlschema.ExtConn()),
+ }
+ got, diag := extconnSchema.TypeAtPath(context.TODO(), path.Root("id"))
+ assert.False(t, diag.HasError())
+ assert.Equal(t, types.StringType, got)
+}
diff --git a/internal/cmlschema/group.go b/internal/cmlschema/group.go
index 9464ba7..3a1abad 100644
--- a/internal/cmlschema/group.go
+++ b/internal/cmlschema/group.go
@@ -73,7 +73,6 @@ func newLabs(ctx context.Context, group *cmlclient.Group, diags *diag.Diagnostic
}
func NewGroup(ctx context.Context, group *cmlclient.Group, diags *diag.Diagnostics) attr.Value {
-
newGroup := GroupModel{
ID: types.StringValue(group.ID),
Description: types.StringValue(group.Description),
diff --git a/internal/cmlschema/image_def.go b/internal/cmlschema/image_def.go
index 7eacf16..bb369e0 100644
--- a/internal/cmlschema/image_def.go
+++ b/internal/cmlschema/image_def.go
@@ -93,7 +93,6 @@ func ImageDef() map[string]schema.Attribute {
}
func NewImageDefinition(ctx context.Context, image *cmlclient.ImageDefinition, diags *diag.Diagnostics) attr.Value {
-
newImage := ImageDefinitionModel{
ID: types.StringValue(image.ID),
NodeDefID: types.StringValue(image.NodeDefID),
diff --git a/internal/cmlschema/image_def_test.go b/internal/cmlschema/image_def_test.go
index 9c51c8b..3ff92fa 100644
--- a/internal/cmlschema/image_def_test.go
+++ b/internal/cmlschema/image_def_test.go
@@ -15,7 +15,6 @@ import (
)
var image *cmlclient.ImageDefinition = &cmlclient.ImageDefinition{
-
ID: "22e72ed9-238f-4f8f-966f-4a5dc6b8de1a",
SchemaVersion: "0.0.1",
NodeDefID: "testnodedef",
diff --git a/internal/cmlschema/interface.go b/internal/cmlschema/interface.go
index 5564412..246aee6 100644
--- a/internal/cmlschema/interface.go
+++ b/internal/cmlschema/interface.go
@@ -92,7 +92,6 @@ func Interface() map[string]schema.Attribute {
}
func NewInterface(ctx context.Context, iface *cmlclient.Interface, diags *diag.Diagnostics) attr.Value {
-
ip4List := types.ListNull(types.StringType)
ip6List := types.ListNull(types.StringType)
var macAddress types.String
diff --git a/internal/cmlschema/lab.go b/internal/cmlschema/lab.go
index 9ec3858..f0dace0 100644
--- a/internal/cmlschema/lab.go
+++ b/internal/cmlschema/lab.go
@@ -141,7 +141,6 @@ func Lab() map[string]schema.Attribute {
// NewLab creates a TF value from a CML2 lab object from the gocmlclient
func NewLab(ctx context.Context, lab *cmlclient.Lab, diags *diag.Diagnostics) attr.Value {
-
valueSet := make([]attr.Value, 0)
for _, group := range lab.Groups {
value := NewLabGroup(ctx, group, diags)
diff --git a/internal/cmlschema/lab_group.go b/internal/cmlschema/lab_group.go
index d490c56..714bce4 100644
--- a/internal/cmlschema/lab_group.go
+++ b/internal/cmlschema/lab_group.go
@@ -26,7 +26,6 @@ type LabGroupModel struct {
}
func NewLabGroup(ctx context.Context, group *cmlclient.LabGroup, diags *diag.Diagnostics) attr.Value {
-
newGroup := LabGroupModel{
ID: types.StringValue(group.ID),
Name: types.StringValue(group.Name),
diff --git a/internal/cmlschema/link.go b/internal/cmlschema/link.go
index 9102d2a..2b486e7 100644
--- a/internal/cmlschema/link.go
+++ b/internal/cmlschema/link.go
@@ -149,7 +149,6 @@ func Link() map[string]schema.Attribute {
}
func NewLink(ctx context.Context, link *cmlclient.Link, diags *diag.Diagnostics) attr.Value {
-
newLink := LinkModel{
ID: types.StringValue(link.ID),
Label: types.StringValue(link.Label),
diff --git a/internal/cmlschema/node.go b/internal/cmlschema/node.go
index 21a9c8d..1fd9c7a 100644
--- a/internal/cmlschema/node.go
+++ b/internal/cmlschema/node.go
@@ -6,6 +6,7 @@ import (
"github.com/hashicorp/terraform-plugin-framework/attr"
"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/boolplanmodifier"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/int64planmodifier"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/listplanmodifier"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
@@ -28,6 +29,7 @@ type NodeModel struct {
Tags types.Set `tfsdk:"tags"`
X types.Int64 `tfsdk:"x"`
Y types.Int64 `tfsdk:"y"`
+ HideLinks types.Bool `tfsdk:"hide_links"`
CPUs types.Int64 `tfsdk:"cpus"`
CPUlimit types.Int64 `tfsdk:"cpu_limit"`
RAM types.Int64 `tfsdk:"ram"`
@@ -124,6 +126,7 @@ var NodeAttrType = map[string]attr.Type{
"tags": types.SetType{ElemType: types.StringType},
"x": types.Int64Type,
"y": types.Int64Type,
+ "hide_links": types.BoolType,
"cpus": types.Int64Type,
"cpu_limit": types.Int64Type,
"ram": types.Int64Type,
@@ -134,14 +137,12 @@ var NodeAttrType = map[string]attr.Type{
"compute_id": types.StringType,
}
-var (
- SerialDevicesAttrType = types.ObjectType{
- AttrTypes: map[string]attr.Type{
- "console_key": types.StringType,
- "device_number": types.Int64Type,
- },
- }
-)
+var SerialDevicesAttrType = types.ObjectType{
+ AttrTypes: map[string]attr.Type{
+ "console_key": types.StringType,
+ "device_number": types.Int64Type,
+ },
+}
func Node() map[string]schema.Attribute {
return map[string]schema.Attribute{
@@ -233,6 +234,14 @@ func Node() map[string]schema.Attribute {
int64planmodifier.UseStateForUnknown(),
},
},
+ "hide_links": schema.BoolAttribute{
+ Description: "If true, links are not shown in the topology. This is a visual cue and does not influence any simulation function.",
+ Computed: true,
+ Optional: true,
+ PlanModifiers: []planmodifier.Bool{
+ boolplanmodifier.UseStateForUnknown(),
+ },
+ },
"ram": schema.Int64Attribute{
Description: "Amount of RAM, megabytes. Can be changed until the node is started once. Will require a replace in that case.",
Computed: true,
@@ -368,7 +377,6 @@ func newInterfaces(ctx context.Context, node *cmlclient.Node, diags *diag.Diagno
}
func NewNode(ctx context.Context, node *cmlclient.Node, diags *diag.Diagnostics) attr.Value {
-
newNode := NodeModel{
ID: types.StringValue(node.ID),
LabID: types.StringValue(node.LabID),
@@ -380,6 +388,7 @@ func NewNode(ctx context.Context, node *cmlclient.Node, diags *diag.Diagnostics)
Tags: newTags(ctx, node, diags),
X: types.Int64Value(int64(node.X)),
Y: types.Int64Value(int64(node.Y)),
+ HideLinks: types.BoolValue(bool(node.HideLinks)),
SerialDevices: newSerialDevices(ctx, node, diags),
// these values are null if unset
diff --git a/internal/cmlschema/node_test.go b/internal/cmlschema/node_test.go
index 155bca1..6701e17 100644
--- a/internal/cmlschema/node_test.go
+++ b/internal/cmlschema/node_test.go
@@ -76,7 +76,7 @@ func TestNodeAttrs(t *testing.T) {
got, diag := nodeschema.TypeAtPath(context.TODO(), path.Root("id"))
t.Log(diag.Errors())
- assert.Equal(t, 19, len(nodeschema.Attributes))
+ assert.Equal(t, 20, len(nodeschema.Attributes))
assert.False(t, diag.HasError())
assert.Equal(t, types.StringType, got)
}
diff --git a/internal/cmlschema/provider.go b/internal/cmlschema/provider.go
index c42656e..63f9c3d 100644
--- a/internal/cmlschema/provider.go
+++ b/internal/cmlschema/provider.go
@@ -19,7 +19,6 @@ type ProviderModel struct {
func Provider() map[string]schema.Attribute {
return map[string]schema.Attribute{
-
"address": schema.StringAttribute{
MarkdownDescription: "CML2 controller address, must start with `https://`.",
Required: true,
diff --git a/internal/cmlschema/user.go b/internal/cmlschema/user.go
index 1406329..78f527a 100644
--- a/internal/cmlschema/user.go
+++ b/internal/cmlschema/user.go
@@ -50,7 +50,6 @@ type UserModel struct {
}
func NewUser(ctx context.Context, user *cmlclient.User, diags *diag.Diagnostics) attr.Value {
-
newUser := UserModel{
ID: types.StringValue(user.ID),
Username: types.StringValue(user.Username),
diff --git a/internal/cmlvalidator/duration.go b/internal/cmlvalidator/duration.go
index a169cd1..36eaf94 100644
--- a/internal/cmlvalidator/duration.go
+++ b/internal/cmlvalidator/duration.go
@@ -26,7 +26,6 @@ func (v Duration) MarkdownDescription(ctx context.Context) string {
// Validate runs the main validation logic of the validator, reading
// configuration data out of `req` and updating `resp` with diagnostics.
func (v Duration) ValidateString(ctx context.Context, req validator.StringRequest, resp *validator.StringResponse) {
-
var duration types.String
resp.Diagnostics.Append(tfsdk.ValueAs(ctx, req.ConfigValue, &duration)...)
if resp.Diagnostics.HasError() {
diff --git a/internal/provider/datasource/extconn/extconn.go b/internal/provider/datasource/extconn/extconn.go
new file mode 100644
index 0000000..c285346
--- /dev/null
+++ b/internal/provider/datasource/extconn/extconn.go
@@ -0,0 +1,137 @@
+package extconn
+
+import (
+ "context"
+ "fmt"
+
+ "github.com/google/uuid"
+ "github.com/hashicorp/terraform-plugin-framework/attr"
+ "github.com/hashicorp/terraform-plugin-framework/datasource"
+ "github.com/hashicorp/terraform-plugin-framework/datasource/schema"
+ "github.com/hashicorp/terraform-plugin-framework/tfsdk"
+
+ "github.com/hashicorp/terraform-plugin-framework/types"
+ "github.com/hashicorp/terraform-plugin-log/tflog"
+
+ "github.com/rschmied/terraform-provider-cml2/internal/cmlschema"
+ "github.com/rschmied/terraform-provider-cml2/internal/common"
+)
+
+// Ensure provider defined types fully satisfy framework interfaces
+var _ datasource.DataSource = &ConnectorDataSource{}
+
+type ConnectorDataSourceModel struct {
+ ID types.String `tfsdk:"id"`
+ Label types.String `tfsdk:"label"`
+ Tag types.String `tfsdk:"tag"`
+ Connectors types.List `tfsdk:"connectors"`
+}
+
+func NewDataSource() datasource.DataSource {
+ return &ConnectorDataSource{}
+}
+
+// ConnectorDataSource defines the data source implementation.
+type ConnectorDataSource struct {
+ cfg *common.ProviderConfig
+}
+
+func (d *ConnectorDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
+ resp.TypeName = req.ProviderTypeName + "_connector"
+}
+
+func (d *ConnectorDataSource) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
+ d.cfg = common.DatasourceConfigure(ctx, req, resp)
+}
+
+func (d *ConnectorDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) {
+ resp.Schema.Attributes = map[string]schema.Attribute{
+ "id": schema.StringAttribute{
+ Description: "A UUID. The presence of the ID attribute is mandated by the framework. The attribute is a random UUID and has no actual significance.",
+ Computed: true,
+ },
+ "label": schema.StringAttribute{
+ Description: "A connector label to filter the connector list returned by the controller. Connector labels must be unique, so it's either one group or no group at all if a name filter is provided.",
+ Optional: true,
+ },
+ "tag": schema.StringAttribute{
+ Description: "A tag name to filter the groups list returned by the controller. Connector tags can be defined on multiple connectors, a list can be returned.",
+ Optional: true,
+ },
+ "connectors": schema.ListNestedAttribute{
+ MarkdownDescription: "A list of all permission groups available on the controller.",
+ NestedObject: schema.NestedAttributeObject{
+ Attributes: cmlschema.Converter(cmlschema.ExtConn()),
+ },
+ Computed: true,
+ },
+ }
+
+ resp.Schema.MarkdownDescription = "A data source that retrieves external connectors information from the controller."
+ resp.Diagnostics = nil
+}
+
+func (d *ConnectorDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
+ var data ConnectorDataSourceModel
+
+ tflog.Info(ctx, "Datasource Connectors READ")
+
+ // Read Terraform configuration data into the model
+ resp.Diagnostics.Append(req.Config.Get(ctx, &data)...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ connectors, err := d.cfg.Client().ExtConnectors(ctx)
+ if err != nil {
+ resp.Diagnostics.AddError(
+ common.ErrorLabel,
+ fmt.Sprintf("Unable to get connectors, got error: %s", err),
+ )
+ return
+ }
+
+ result := make([]attr.Value, 0)
+ for _, connector := range connectors {
+ if !data.Label.IsNull() && connector.Label != data.Label.ValueString() {
+ continue
+ }
+ if !data.Tag.IsNull() {
+ found := false
+ for _, tag := range connector.Tags {
+ if tag == data.Tag.ValueString() {
+ found = true
+ break
+ }
+ }
+ if !found {
+ continue
+ }
+ }
+ result = append(result, cmlschema.NewExtConn(
+ ctx, connector, &resp.Diagnostics),
+ )
+
+ }
+
+ resp.Diagnostics.Append(
+ tfsdk.ValueFrom(
+ ctx,
+ result,
+ types.ListType{
+ ElemType: types.ObjectType{
+ AttrTypes: cmlschema.ExtConnAttrType,
+ },
+ },
+ &data.Connectors,
+ )...,
+ )
+ // need an ID
+ // https://developer.hashicorp.com/terraform/plugin/framework/acctests#implement-id-attribute
+ data.ID = types.StringValue(uuid.New().String())
+
+ // Save data into Terraform state
+ resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
+
+ tflog.Info(ctx, "Datasource Connectors READ: done")
+}
diff --git a/internal/provider/datasource/extconn/extconn_test.go b/internal/provider/datasource/extconn/extconn_test.go
new file mode 100644
index 0000000..079f434
--- /dev/null
+++ b/internal/provider/datasource/extconn/extconn_test.go
@@ -0,0 +1,79 @@
+package extconn_test
+
+import (
+ "fmt"
+ "strconv"
+ "testing"
+
+ "github.com/hashicorp/terraform-plugin-framework/providerserver"
+ "github.com/hashicorp/terraform-plugin-go/tfprotov6"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
+ cml "github.com/rschmied/terraform-provider-cml2/internal/provider"
+ cfg "github.com/rschmied/terraform-provider-cml2/internal/testing"
+)
+
+var testAccProtoV6ProviderFactories = map[string]func() (tfprotov6.ProviderServer, error){
+ "cml2": providerserver.NewProtocol6WithError(cml.New("test")()),
+}
+
+func testAccPreCheck(t *testing.T) {
+ // You can add code here to run prior to any test case execution, for
+ // example assertions about the appropriate environment variables being set
+ // are common to see in a pre-check function.
+}
+
+func TestExtConnDataSource(t *testing.T) {
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { testAccPreCheck(t) },
+ ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
+ Steps: []resource.TestStep{
+ // Read testing
+ {
+ Config: testExtConnDataSourceConfig(cfg.Cfg, "", ""),
+ Check: resource.ComposeAggregateTestCheckFunc(
+ resource.TestCheckResourceAttrWith("data.cml2_connector.test", "connectors.#", func(value string) error {
+ num, err := strconv.Atoi(value)
+ if err == nil && num == 0 {
+ return fmt.Errorf("expected at least one connector definition, got %d", num)
+ }
+ return err
+ }),
+ ),
+ },
+ {
+ Config: testExtConnDataSourceConfig(cfg.Cfg, "", "NAT"),
+ Check: resource.ComposeAggregateTestCheckFunc(
+ resource.TestCheckOutput("bla", "virbr0"),
+ ),
+ },
+ {
+ Config: testExtConnDataSourceConfig(cfg.Cfg, "NAT", ""),
+ Check: resource.ComposeAggregateTestCheckFunc(
+ resource.TestCheckOutput("bla", "virbr0"),
+ ),
+ },
+ },
+ })
+}
+
+func testExtConnDataSourceConfig(cfg, label, tag string) string {
+ connectorCfg := ""
+ if len(label) > 0 {
+ connectorCfg = fmt.Sprintf("label = %q", label)
+ }
+ if len(tag) > 0 {
+ connectorCfg += fmt.Sprintf("\ntag = %q", tag)
+ }
+ return fmt.Sprintf(`
+ %[1]s
+ data "cml2_connector" "test" {
+ %[2]s
+ }
+ locals {
+ cl = data.cml2_connector.test.connectors
+ }
+ output "bla" {
+ value = element(local.cl, 0).device_name
+ }
+ `, cfg, connectorCfg)
+}
diff --git a/internal/provider/datasource/groups/groups_test.go b/internal/provider/datasource/groups/groups_test.go
index a91b736..73c0db9 100644
--- a/internal/provider/datasource/groups/groups_test.go
+++ b/internal/provider/datasource/groups/groups_test.go
@@ -52,8 +52,13 @@ func TestGroupDataSource(t *testing.T) {
func testGroupDataSourceConfig(cfg string) string {
return fmt.Sprintf(`
%[1]s
+ resource "cml2_group" "thegroup" {
+ description = "the students"
+ name = "students"
+ }
data "cml2_groups" "test" {
name = "students"
+ depends_on = [ cml2_group.thegroup ]
}
output "bla" {
value = data.cml2_groups.test.groups[0].name
diff --git a/internal/provider/datasource/lab/main.go b/internal/provider/datasource/lab/main.go
index a42db61..1b5e269 100644
--- a/internal/provider/datasource/lab/main.go
+++ b/internal/provider/datasource/lab/main.go
@@ -16,8 +16,10 @@ import (
)
// Ensure provider defined types fully satisfy framework interfaces
-var _ datasource.DataSource = &LabDataSource{}
-var _ datasource.DataSourceWithValidateConfig = &LabDataSource{}
+var (
+ _ datasource.DataSource = &LabDataSource{}
+ _ datasource.DataSourceWithValidateConfig = &LabDataSource{}
+)
type LabDataSourceModel struct {
ID types.String `tfsdk:"id"`
diff --git a/internal/provider/datasource/system/system.go b/internal/provider/datasource/system/system.go
index f4b45af..9a7440d 100644
--- a/internal/provider/datasource/system/system.go
+++ b/internal/provider/datasource/system/system.go
@@ -34,7 +34,7 @@ func NewDataSource() datasource.DataSource {
return &SystemDataSource{}
}
-// ImagesDataSource defines the data source implementation.
+// SystemDataSource defines the data source implementation.
type SystemDataSource struct {
cfg *common.ProviderConfig
}
diff --git a/internal/provider/datasource/users/users_test.go b/internal/provider/datasource/users/users_test.go
index 8424222..7c72bba 100644
--- a/internal/provider/datasource/users/users_test.go
+++ b/internal/provider/datasource/users/users_test.go
@@ -22,7 +22,6 @@ func testAccPreCheck(t *testing.T) {
}
func TestUsersDataSource(t *testing.T) {
-
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
diff --git a/internal/provider/provider.go b/internal/provider/provider.go
index 65133c8..3ad949a 100644
--- a/internal/provider/provider.go
+++ b/internal/provider/provider.go
@@ -9,6 +9,7 @@ import (
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/rschmied/terraform-provider-cml2/internal/common"
+ d_extconn "github.com/rschmied/terraform-provider-cml2/internal/provider/datasource/extconn"
d_groups "github.com/rschmied/terraform-provider-cml2/internal/provider/datasource/groups"
d_images "github.com/rschmied/terraform-provider-cml2/internal/provider/datasource/images"
d_lab "github.com/rschmied/terraform-provider-cml2/internal/provider/datasource/lab"
@@ -97,6 +98,7 @@ func (p *CML2Provider) DataSources(ctx context.Context) []func() datasource.Data
d_system.NewDataSource,
d_groups.NewDataSource,
d_users.NewDataSource,
+ d_extconn.NewDataSource,
}
}
diff --git a/internal/provider/resource/group/create.go b/internal/provider/resource/group/create.go
index aaf391a..d4b6ddd 100644
--- a/internal/provider/resource/group/create.go
+++ b/internal/provider/resource/group/create.go
@@ -14,7 +14,6 @@ import (
)
func (r *GroupResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
-
var (
data cmlschema.GroupModel
err error
diff --git a/internal/provider/resource/group/meta.go b/internal/provider/resource/group/meta.go
index 366ae49..78213d1 100644
--- a/internal/provider/resource/group/meta.go
+++ b/internal/provider/resource/group/meta.go
@@ -11,8 +11,10 @@ import (
)
// Ensure provider defined types fully satisfy framework interfaces
-var _ resource.Resource = &GroupResource{}
-var _ resource.ResourceWithImportState = &GroupResource{}
+var (
+ _ resource.Resource = &GroupResource{}
+ _ resource.ResourceWithImportState = &GroupResource{}
+)
type GroupResource struct {
cfg *common.ProviderConfig
diff --git a/internal/provider/resource/lab/create.go b/internal/provider/resource/lab/create.go
index 4580b85..7f00168 100644
--- a/internal/provider/resource/lab/create.go
+++ b/internal/provider/resource/lab/create.go
@@ -16,7 +16,6 @@ import (
)
func (r *LabResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
-
var (
labModel cmlschema.LabModel
err error
diff --git a/internal/provider/resource/lab/delete.go b/internal/provider/resource/lab/delete.go
index 81dad8e..45cf568 100644
--- a/internal/provider/resource/lab/delete.go
+++ b/internal/provider/resource/lab/delete.go
@@ -14,7 +14,6 @@ import (
)
func (r *LabResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
-
var (
data cmlschema.LabModel
err error
diff --git a/internal/provider/resource/lab/meta.go b/internal/provider/resource/lab/meta.go
index 9c8b0a4..72ef76b 100644
--- a/internal/provider/resource/lab/meta.go
+++ b/internal/provider/resource/lab/meta.go
@@ -11,9 +11,11 @@ import (
)
// Ensure provider defined types fully satisfy framework interfaces
-var _ resource.Resource = &LabResource{}
-var _ resource.ResourceWithImportState = &LabResource{}
-var _ resource.ResourceWithModifyPlan = &LabResource{}
+var (
+ _ resource.Resource = &LabResource{}
+ _ resource.ResourceWithImportState = &LabResource{}
+ _ resource.ResourceWithModifyPlan = &LabResource{}
+)
type LabResource struct {
cfg *common.ProviderConfig
diff --git a/internal/provider/resource/lab/modify_plan.go b/internal/provider/resource/lab/modify_plan.go
index cd525c2..0117cae 100644
--- a/internal/provider/resource/lab/modify_plan.go
+++ b/internal/provider/resource/lab/modify_plan.go
@@ -2,7 +2,6 @@ package lab
import (
"context"
- "fmt"
"reflect"
"github.com/hashicorp/terraform-plugin-framework/resource"
@@ -12,7 +11,6 @@ import (
)
func (r *LabResource) ModifyPlan(ctx context.Context, req resource.ModifyPlanRequest, resp *resource.ModifyPlanResponse) {
-
var stateData, planData cmlschema.LabModel
tflog.Info(ctx, "Resource Lab MODIFYPLAN")
@@ -28,8 +26,8 @@ func (r *LabResource) ModifyPlan(ctx context.Context, req resource.ModifyPlanReq
return
}
- tflog.Info(ctx, fmt.Sprintf("XXX plan: %v", planData.Groups))
- tflog.Info(ctx, fmt.Sprintf("XXX state: %v", stateData.Groups))
+ // tflog.Info(ctx, fmt.Sprintf("XXX plan: %v", planData.Groups))
+ // tflog.Info(ctx, fmt.Sprintf("XXX state: %v", stateData.Groups))
// this makes TF crash
// planData.Groups = types.SetUnknown(
diff --git a/internal/provider/resource/lab/update.go b/internal/provider/resource/lab/update.go
index 0f85783..b358937 100644
--- a/internal/provider/resource/lab/update.go
+++ b/internal/provider/resource/lab/update.go
@@ -13,7 +13,6 @@ import (
)
func (r LabResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
-
var (
data cmlschema.LabModel
err error
diff --git a/internal/provider/resource/lifecycle/lifecycle_test.go b/internal/provider/resource/lifecycle/lifecycle_test.go
index f1617d0..efd0a79 100644
--- a/internal/provider/resource/lifecycle/lifecycle_test.go
+++ b/internal/provider/resource/lifecycle/lifecycle_test.go
@@ -100,7 +100,6 @@ func TestAccLifecycleConfigCheck(t *testing.T) {
}
func TestAccLifecycleImportLab(t *testing.T) {
-
const (
initialAlpineConfig = "new config for alpine"
changedAlpineConfig = "changed config for alpine"
@@ -231,6 +230,27 @@ func TestAccLifecycleSequence(t *testing.T) {
})
}
+func TestAccLifecycleAddNodeToBooted(t *testing.T) {
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { testAccPreCheck(t) },
+ ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
+ Steps: []resource.TestStep{
+ {
+ Config: testAccLifecycleAddNodeToBooted(cfg.Cfg, 0),
+ Check: resource.ComposeAggregateTestCheckFunc(
+ resource.TestCheckResourceAttr("cml2_lifecycle.top", "booted", "true"),
+ ),
+ },
+ {
+ Config: testAccLifecycleAddNodeToBooted(cfg.Cfg, 1),
+ Check: resource.ComposeAggregateTestCheckFunc(
+ resource.TestCheckResourceAttr("cml2_lifecycle.top", "booted", "true"),
+ ),
+ },
+ },
+ })
+}
+
func testAccLifecyclekResourceConfig(cfg string) string {
return fmt.Sprintf(`
%[1]s
@@ -254,6 +274,7 @@ resource "cml2_link" "l1" {
node_a = cml2_node.r1.id
node_b = cml2_node.r2.id
}
+
resource "cml2_lifecycle" "top" {
lab_id = cml2_lab.this.id
elements = [
@@ -289,10 +310,18 @@ resource "cml2_lab" "this" {
resource "cml2_node" "ext" {
lab_id = cml2_lab.this.id
label = "Internet"
+ configuration = "NAT"
nodedefinition = "external_connector"
tags = [ "bla" ]
}
+resource "cml2_node" "ums" {
+ lab_id = cml2_lab.this.id
+ label = "Unmanaged Switch"
+ nodedefinition = "unmanaged_switch"
+ tags = [ "bla" ]
+}
+
resource "cml2_node" "r1" {
lab_id = cml2_lab.this.id
label = "R1"
@@ -309,15 +338,24 @@ resource "cml2_node" "r2" {
resource "cml2_link" "l1" {
lab_id = cml2_lab.this.id
node_a = cml2_node.ext.id
+ node_b = cml2_node.ums.id
+}
+
+resource "cml2_link" "l2" {
+ lab_id = cml2_lab.this.id
+ node_a = cml2_node.ums.id
node_b = cml2_node.r1.id
}
+
resource "cml2_lifecycle" "top" {
lab_id = cml2_lab.this.id
elements = [
cml2_node.ext.id,
+ cml2_node.ums.id,
cml2_node.r1.id,
cml2_node.r2.id,
cml2_link.l1.id,
+ cml2_link.l2.id,
]
staging = {
stages = [ "bla" ]
@@ -403,3 +441,147 @@ resource "cml2_lab" "this" {
}
`, cfg)
}
+
+func testAccLifecycleAddNodeToBooted(cfg string, stage int) string {
+ if stage == 0 {
+ return fmt.Sprintf(`
+%[1]s
+resource "cml2_lab" "this" {
+ title = "lifecycle add node to booted"
+}
+
+resource "cml2_node" "ext" {
+ lab_id = cml2_lab.this.id
+ label = "Internet"
+ configuration = "NAT"
+ nodedefinition = "external_connector"
+}
+
+resource "cml2_node" "ums" {
+ lab_id = cml2_lab.this.id
+ label = "Unmanaged Switch"
+ nodedefinition = "unmanaged_switch"
+}
+
+resource "cml2_node" "r1" {
+ lab_id = cml2_lab.this.id
+ label = "R1"
+ nodedefinition = "alpine"
+}
+
+resource "cml2_node" "r2" {
+ lab_id = cml2_lab.this.id
+ label = "R2"
+ nodedefinition = "alpine"
+}
+
+resource "cml2_link" "l0" {
+ lab_id = cml2_lab.this.id
+ node_a = cml2_node.ext.id
+ node_b = cml2_node.ums.id
+}
+
+resource "cml2_link" "l1" {
+ lab_id = cml2_lab.this.id
+ node_a = cml2_node.ums.id
+ node_b = cml2_node.r1.id
+}
+
+resource "cml2_link" "l2" {
+ lab_id = cml2_lab.this.id
+ node_a = cml2_node.ums.id
+ node_b = cml2_node.r2.id
+}
+
+resource "cml2_lifecycle" "top" {
+ lab_id = cml2_lab.this.id
+ elements = [
+ cml2_node.ext.id,
+ cml2_node.ums.id,
+ cml2_node.r1.id,
+ cml2_node.r2.id,
+ cml2_link.l0.id,
+ cml2_link.l1.id,
+ cml2_link.l2.id,
+ ]
+}
+ `, cfg)
+ } else {
+ return fmt.Sprintf(`
+%[1]s
+resource "cml2_lab" "this" {
+ title = "lifecycle add node to booted"
+}
+
+resource "cml2_node" "ext" {
+ lab_id = cml2_lab.this.id
+ label = "Internet"
+ configuration = "NAT"
+ nodedefinition = "external_connector"
+}
+
+resource "cml2_node" "ums" {
+ lab_id = cml2_lab.this.id
+ label = "Unmanaged Switch"
+ nodedefinition = "unmanaged_switch"
+}
+
+resource "cml2_node" "r1" {
+ lab_id = cml2_lab.this.id
+ label = "R1"
+ nodedefinition = "alpine"
+}
+
+resource "cml2_node" "r2" {
+ lab_id = cml2_lab.this.id
+ label = "R2"
+ nodedefinition = "alpine"
+}
+
+resource "cml2_node" "r3" {
+ lab_id = cml2_lab.this.id
+ label = "R3"
+ nodedefinition = "alpine"
+}
+
+resource "cml2_link" "l0" {
+ lab_id = cml2_lab.this.id
+ node_a = cml2_node.ext.id
+ node_b = cml2_node.ums.id
+}
+
+resource "cml2_link" "l1" {
+ lab_id = cml2_lab.this.id
+ node_a = cml2_node.ums.id
+ node_b = cml2_node.r1.id
+}
+
+resource "cml2_link" "l2" {
+ lab_id = cml2_lab.this.id
+ node_a = cml2_node.ums.id
+ node_b = cml2_node.r2.id
+}
+
+resource "cml2_link" "l3" {
+ lab_id = cml2_lab.this.id
+ node_a = cml2_node.ums.id
+ node_b = cml2_node.r3.id
+}
+
+resource "cml2_lifecycle" "top" {
+ lab_id = cml2_lab.this.id
+ elements = [
+ cml2_node.ext.id,
+ cml2_node.ums.id,
+ cml2_node.r1.id,
+ cml2_node.r2.id,
+ cml2_node.r3.id,
+ cml2_link.l0.id,
+ cml2_link.l1.id,
+ cml2_link.l2.id,
+ cml2_link.l3.id,
+ ]
+}
+ `, cfg)
+ }
+}
diff --git a/internal/provider/resource/lifecycle/meta.go b/internal/provider/resource/lifecycle/meta.go
index 504888f..6b3025b 100644
--- a/internal/provider/resource/lifecycle/meta.go
+++ b/internal/provider/resource/lifecycle/meta.go
@@ -14,10 +14,12 @@ import (
)
// Ensure provider defined types fully satisfy framework interfaces
-var _ resource.Resource = &LabLifecycleResource{}
-var _ resource.ResourceWithImportState = &LabLifecycleResource{}
-var _ resource.ResourceWithValidateConfig = &LabLifecycleResource{}
-var _ resource.ResourceWithModifyPlan = &LabLifecycleResource{}
+var (
+ _ resource.Resource = &LabLifecycleResource{}
+ _ resource.ResourceWithImportState = &LabLifecycleResource{}
+ _ resource.ResourceWithValidateConfig = &LabLifecycleResource{}
+ _ resource.ResourceWithModifyPlan = &LabLifecycleResource{}
+)
type LabLifecycleResource struct {
cfg *common.ProviderConfig
diff --git a/internal/provider/resource/lifecycle/modify_plan.go b/internal/provider/resource/lifecycle/modify_plan.go
index 15062d3..da9640a 100644
--- a/internal/provider/resource/lifecycle/modify_plan.go
+++ b/internal/provider/resource/lifecycle/modify_plan.go
@@ -15,7 +15,6 @@ import (
)
func (r *LabLifecycleResource) ModifyPlan(ctx context.Context, req resource.ModifyPlanRequest, resp *resource.ModifyPlanResponse) {
-
var configData, planData, stateData cmlschema.LabLifecycleModel
tflog.Info(ctx, "Resource Lifecycle MODIFYPLAN")
diff --git a/internal/provider/resource/lifecycle/utilities.go b/internal/provider/resource/lifecycle/utilities.go
index 4152717..91862f7 100644
--- a/internal/provider/resource/lifecycle/utilities.go
+++ b/internal/provider/resource/lifecycle/utilities.go
@@ -89,7 +89,6 @@ func (r *LabLifecycleResource) startNodesAll(ctx context.Context, diags *diag.Di
}
func (r *LabLifecycleResource) startNodes(ctx context.Context, diags *diag.Diagnostics, start startData) {
-
// start all nodes at once, no staging
if start.staging == nil {
r.startNodesAll(ctx, diags, start)
diff --git a/internal/provider/resource/link/create.go b/internal/provider/resource/link/create.go
index 7dffc06..516c51c 100644
--- a/internal/provider/resource/link/create.go
+++ b/internal/provider/resource/link/create.go
@@ -16,7 +16,6 @@ import (
)
func (r *LinkResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
-
var (
data cmlschema.LinkModel
err error
diff --git a/internal/provider/resource/link/link_test.go b/internal/provider/resource/link/link_test.go
index 37ce40d..47af207 100644
--- a/internal/provider/resource/link/link_test.go
+++ b/internal/provider/resource/link/link_test.go
@@ -63,7 +63,6 @@ func TestAccLinkResource(t *testing.T) {
}
func TestAccLifecycleResourceDaniel(t *testing.T) {
-
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
diff --git a/internal/provider/resource/link/meta.go b/internal/provider/resource/link/meta.go
index 37edfac..d00079b 100644
--- a/internal/provider/resource/link/meta.go
+++ b/internal/provider/resource/link/meta.go
@@ -11,9 +11,11 @@ import (
)
// Ensure provider defined types fully satisfy framework interfaces
-var _ resource.Resource = &LinkResource{}
-var _ resource.ResourceWithImportState = &LinkResource{}
-var _ resource.ResourceWithModifyPlan = &LinkResource{}
+var (
+ _ resource.Resource = &LinkResource{}
+ _ resource.ResourceWithImportState = &LinkResource{}
+ _ resource.ResourceWithModifyPlan = &LinkResource{}
+)
type LinkResource struct {
cfg *common.ProviderConfig
diff --git a/internal/provider/resource/link/modify_plan.go b/internal/provider/resource/link/modify_plan.go
index 0334618..40e4f48 100644
--- a/internal/provider/resource/link/modify_plan.go
+++ b/internal/provider/resource/link/modify_plan.go
@@ -10,7 +10,6 @@ import (
)
func (r *LinkResource) ModifyPlan(ctx context.Context, req resource.ModifyPlanRequest, resp *resource.ModifyPlanResponse) {
-
var planData, stateData cmlschema.LinkModel
tflog.Info(ctx, "Resource Link MODIFYPLAN")
diff --git a/internal/provider/resource/link/update.go b/internal/provider/resource/link/update.go
index 9254f22..879e74a 100644
--- a/internal/provider/resource/link/update.go
+++ b/internal/provider/resource/link/update.go
@@ -9,7 +9,6 @@ import (
)
func (r LinkResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
-
var data cmlschema.LinkModel
tflog.Info(ctx, "Resource Link UPDATE")
diff --git a/internal/provider/resource/node/create.go b/internal/provider/resource/node/create.go
index 8643881..c9504de 100644
--- a/internal/provider/resource/node/create.go
+++ b/internal/provider/resource/node/create.go
@@ -16,7 +16,6 @@ import (
)
func (r *NodeResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
-
var (
data cmlschema.NodeModel
err error
@@ -58,7 +57,9 @@ func (r *NodeResource) Create(ctx context.Context, req resource.CreateRequest, r
if !data.Y.IsUnknown() {
node.Y = int(data.Y.ValueInt64())
}
-
+ if !data.HideLinks.IsUnknown() {
+ node.HideLinks = bool(data.HideLinks.ValueBool())
+ }
if !data.RAM.IsUnknown() {
node.RAM = int(data.RAM.ValueInt64())
}
@@ -78,6 +79,15 @@ func (r *NodeResource) Create(ctx context.Context, req resource.CreateRequest, r
node.ImageDefinition = data.ImageDefinition.ValueString()
}
+ // can't set a configuration for an unmanaged switch
+ if node.NodeDefinition == "unmanaged_switch" && !data.Configuration.IsUnknown() {
+ resp.Diagnostics.AddError(
+ "Unmanaged switch configuration",
+ "Can't provide UMS configuration",
+ )
+ return
+ }
+
newNode, err := r.cfg.Client().NodeCreate(ctx, &node)
if err != nil {
resp.Diagnostics.AddError(
@@ -87,6 +97,19 @@ func (r *NodeResource) Create(ctx context.Context, req resource.CreateRequest, r
return
}
+ // work around the fact that creating an external connector will "resolve"
+ // the device name (if given, worked in previous versions" with the
+ // label... e.g. virbr0 -> NAT, bridge0 -> System Bridge. We return an
+ // error in this case, otherwise we'd run into inconsistent state!
+ if node.NodeDefinition == "external_connector" && node.Configuration != nil && *newNode.Configuration != *node.Configuration {
+ resp.Diagnostics.AddError(
+ "External connector configuration",
+ fmt.Sprintf("provide proper external connector configuration, not a device name (deprecated). API returned %q, configured was %q!", *newNode.Configuration, *node.Configuration),
+ )
+ return
+ // newNode.Configuration = node.Configuration
+ }
+
resp.Diagnostics.Append(
tfsdk.ValueFrom(
ctx,
diff --git a/internal/provider/resource/node/delete.go b/internal/provider/resource/node/delete.go
index c46a577..1680690 100644
--- a/internal/provider/resource/node/delete.go
+++ b/internal/provider/resource/node/delete.go
@@ -14,7 +14,6 @@ import (
)
func (r *NodeResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
-
var (
data cmlschema.NodeModel
err error
diff --git a/internal/provider/resource/node/meta.go b/internal/provider/resource/node/meta.go
index f43d04f..3a2e401 100644
--- a/internal/provider/resource/node/meta.go
+++ b/internal/provider/resource/node/meta.go
@@ -11,9 +11,11 @@ import (
)
// Ensure provider defined types fully satisfy framework interfaces
-var _ resource.Resource = &NodeResource{}
-var _ resource.ResourceWithImportState = &NodeResource{}
-var _ resource.ResourceWithModifyPlan = &NodeResource{}
+var (
+ _ resource.Resource = &NodeResource{}
+ _ resource.ResourceWithImportState = &NodeResource{}
+ _ resource.ResourceWithModifyPlan = &NodeResource{}
+)
type NodeResource struct {
cfg *common.ProviderConfig
@@ -30,7 +32,14 @@ func (r *NodeResource) Configure(ctx context.Context, req resource.ConfigureRequ
func (r *NodeResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
// This description is used by the documentation generator and the language
// server.
- resp.Schema.MarkdownDescription = "A node resource represents a CML node. At create time, the lab ID, a node definition and a label must be provided. Other attributes are optional. Note that some attributes can't be changed after the node state has changed to `STARTED` (see the lifecyle resource) once. Changing attributes will then require a replace."
+ resp.Schema.MarkdownDescription = "A node resource represents a CML node. At create time, the lab ID, a " +
+ "node definition and a label must be provided. Other attributes are optional. Note that some " +
+ "attributes can't be changed after the node state has changed to `STARTED` (see the `lifecyle` resource) " +
+ "once. Changing attributes will then require a replace. " +
+ "Node configurations are \"day zero\" configurations. Replacing a configuration typically requires a " +
+ "node replacement if the node has been started. No Configurations can be provided for unmanaged switches. " +
+ "External connectors require the connector label (like \"NAT\"), not the device name (like \"virbr0\"). " +
+ "The available connectors can be retrieved via the external connector data source."
resp.Schema.Attributes = cmlschema.Node()
resp.Diagnostics = nil
}
diff --git a/internal/provider/resource/node/modify_plan.go b/internal/provider/resource/node/modify_plan.go
index 0cee147..ded5547 100644
--- a/internal/provider/resource/node/modify_plan.go
+++ b/internal/provider/resource/node/modify_plan.go
@@ -11,27 +11,26 @@ import (
"github.com/rschmied/terraform-provider-cml2/internal/cmlschema"
)
-// ModifyPlan is called when the provider has an opportunity to modify
-// the plan: once during the plan phase when Terraform is determining
-// the diff that should be shown to the user for approval, and once
-// during the apply phase with any unknown values from configuration
-// filled in with their final values.
+// ModifyPlan is called when the provider has an opportunity to modify the
+// plan: once during the plan phase when Terraform is determining the diff that
+// should be shown to the user for approval, and once during the apply phase
+// with any unknown values from configuration filled in with their final
+// values.
//
-// The planned new state is represented by
-// ModifyPlanResponse.Plan. It must meet the following
-// constraints:
-// 1. Any non-Computed attribute set in config must preserve the exact
-// config value or return the corresponding attribute value from the
-// prior state (ModifyPlanRequest.State).
-// 2. Any attribute with a known value must not have its value changed
-// in subsequent calls to ModifyPlan or Create/Read/Update.
-// 3. Any attribute with an unknown value may either remain unknown
-// or take on any value of the expected type.
+// The planned new state is represented by ModifyPlanResponse.Plan. It must
+// meet the following constraints:
+//
+// 1. Any non-Computed attribute set in config must preserve the exact config
+// value or return the corresponding attribute value from the prior state
+// (ModifyPlanRequest.State).
+// 2. Any attribute with a known value must not have its value changed in
+// subsequent calls to ModifyPlan or Create/Read/Update.
+// 3. Any attribute with an unknown value may either remain unknown or take on
+// any value of the expected type.
//
// Any errors will prevent further resource-level plan modifications.
func (r *NodeResource) ModifyPlan(ctx context.Context, req resource.ModifyPlanRequest, resp *resource.ModifyPlanResponse) {
-
// var stateData, planData cmlschema.NodeModel
var configData, planData, stateData cmlschema.NodeModel
@@ -61,22 +60,15 @@ func (r *NodeResource) ModifyPlan(ctx context.Context, req resource.ModifyPlanRe
// changing certain attributes require a replace
nodeExists := stateData.State.ValueString() != cmlclient.NodeStateDefined
- // if planData.ComputeID.IsUnknown() {
- // planData.ComputeID = types.StringNull()
- // }
- // if planData.SerialDevices.IsUnknown() {
- // planData.SerialDevices = types.ListNull(cmlschema.SerialDevicesAttrType)
- // }
- // if planData.VNCkey.IsUnknown() {
- // planData.VNCkey = types.StringNull()
- // }
- // if planData.Interfaces.IsUnknown() {
- // planData.Interfaces = types.ListNull(types.ObjectType{AttrTypes: cmlschema.InterfaceAttrType})
- // }
-
- // the following are the attributes where the replace is depending on
- // the node state...
- if !planData.Configuration.IsUnknown() && nodeExists {
+ // tflog.Warn(ctx, "### CONDITION ###", map[string]any{
+ // "type_state": stateData.NodeDefinition.ValueString(),
+ // "type_plan": planData.NodeDefinition.ValueString(),
+ // "config_state": stateData.Configuration.ValueString(),
+ // "config_plan": planData.Configuration.ValueString(),
+ // "unknown_plan": planData.Configuration.IsUnknown(),
+ // })
+
+ if nodeExists && !stateData.Configuration.Equal(planData.Configuration) {
resp.RequiresReplace = append(resp.RequiresReplace, path.Root("configuration"))
}
@@ -116,11 +108,14 @@ func (r *NodeResource) ModifyPlan(ctx context.Context, req resource.ModifyPlanRe
}
planData.CPUlimit = configData.CPUlimit
}
- if planData.CPUlimit.IsUnknown() {
+ if planData.CPUlimit.IsUnknown() && planData.NodeDefinition.ValueString() != "external_connector" && planData.NodeDefinition.ValueString() != "unmanaged_switch" {
// CPUlimit is the weird one here as it is possible to set the value to null
// and this actually works on updating on the controller (PATCH). However,
// when reading the data again, the value comes back as 100.
// See SIMPLE-5052 and cmlclient.NodeGet()
+ // Also: Need to restrict this to devices other than UMS and ExtConn as those
+ // do always return NULL for the value w/ 2.6.0
+ // TODO: need to see what IOL returns in 2.7.0
planData.CPUlimit = types.Int64Value(int64(100))
}
diff --git a/internal/provider/resource/node/node_test.go b/internal/provider/resource/node/node_test.go
index ae1531f..5fb455a 100644
--- a/internal/provider/resource/node/node_test.go
+++ b/internal/provider/resource/node/node_test.go
@@ -57,6 +57,7 @@ func TestAccNodeResource(t *testing.T) {
resource.TestCheckNoResourceAttr("cml2_node.r1", "imagedefinition"),
resource.TestCheckResourceAttr("cml2_node.r1", "x", "100"),
resource.TestCheckResourceAttr("cml2_node.r1", "y", "100"),
+ resource.TestCheckResourceAttr("cml2_node.r1", "hide_links", "false"),
resource.TestCheckResourceAttr("cml2_node.r1", "tags.#", "1"),
resource.TestCheckTypeSetElemAttr("cml2_node.r1", "tags.*", "test"),
),
@@ -69,6 +70,7 @@ func TestAccNodeResource(t *testing.T) {
resource.TestCheckResourceAttr("cml2_node.r1", "label", "alpine-99"),
resource.TestCheckResourceAttr("cml2_node.r1", "x", "100"),
resource.TestCheckResourceAttr("cml2_node.r1", "y", "200"),
+ resource.TestCheckResourceAttr("cml2_node.r1", "hide_links", "true"),
resource.TestCheckResourceAttr("cml2_node.r1", "tags.#", "2"),
resource.TestCheckTypeSetElemAttr("cml2_node.r1", "tags.*", "test"),
resource.TestCheckTypeSetElemAttr("cml2_node.r1", "tags.*", "tag2"),
@@ -82,6 +84,7 @@ func TestAccNodeResource(t *testing.T) {
resource.TestCheckResourceAttrSet("cml2_node.r1", "imagedefinition"),
resource.TestCheckResourceAttr("cml2_node.r1", "x", "100"),
resource.TestCheckResourceAttr("cml2_node.r1", "y", "200"),
+ resource.TestCheckResourceAttr("cml2_node.r1", "hide_links", "false"),
resource.TestCheckResourceAttr("cml2_node.r1", "ram", "1024"),
resource.TestCheckResourceAttr("cml2_node.r1", "cpus", "2"),
resource.TestCheckResourceAttr("cml2_node.r1", "boot_disk_size", "64"),
@@ -202,6 +205,70 @@ func TestAccNodeResourceNullConfig(t *testing.T) {
})
}
+func TestAccNodeResourceExtConn(t *testing.T) {
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { testAccPreCheck(t) },
+ ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
+ Steps: []resource.TestStep{
+ {
+ Config: testAccNodeResourceConfigNodeDefExtConn(cfg.Cfg, ""),
+ Check: resource.TestCheckResourceAttrWith("cml2_node.ext", "configuration", func(value string) error {
+ expected := "NAT"
+ if value == expected {
+ return nil
+ }
+ return fmt.Errorf("expected %q to contain %q", value, expected)
+ }),
+ // Destroy: ,
+ },
+ {
+ Config: testAccNodeResourceConfigNodeDefExtConn(cfg.Cfg, "NAT"),
+ Check: resource.TestCheckResourceAttrWith("cml2_node.ext", "configuration", func(value string) error {
+ expected := "NAT"
+ if value == expected {
+ return nil
+ }
+ return fmt.Errorf("expected %q to contain %q", value, expected)
+ }),
+ },
+ // this tests the error condition in Update!
+ {
+ Config: testAccNodeResourceConfigNodeDefExtConn(cfg.Cfg, "virbr0"),
+ ExpectError: regexp.MustCompile("provide proper external connector configuration, not a device name"),
+ },
+ },
+ })
+ // same test, this time the error is raised in Create!
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { testAccPreCheck(t) },
+ ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
+ Steps: []resource.TestStep{
+ {
+ Config: testAccNodeResourceConfigNodeDefExtConn(cfg.Cfg, "virbr0"),
+ ExpectError: regexp.MustCompile("provide proper external connector configuration, not a device name"),
+ },
+ },
+ })
+}
+
+func testAccNodeResourceConfigNodeDefExtConn(cfg, extconnname string) string {
+ var config string
+ if len(extconnname) > 0 {
+ config = fmt.Sprintf("configuration = %q", extconnname)
+ }
+ return fmt.Sprintf(`
+%[1]s
+resource "cml2_lab" "test" {
+}
+resource "cml2_node" "ext" {
+ lab_id = cml2_lab.test.id
+ label = "ext0"
+ nodedefinition = "external_connector"
+ %[2]s
+}
+`, cfg, config)
+}
+
func testAccNodeResourceConfigNodeDefInvalid(cfg string) string {
return fmt.Sprintf(`
%[1]s
@@ -267,6 +334,7 @@ func testAccNodeResourceConfig(cfg string, step int) string {
label = "alpine-99"
x = 100
y = 200
+ hide_links = true
nodedefinition = "alpine"
tags = [ "test", "tag2" ]
}
@@ -285,6 +353,7 @@ func testAccNodeResourceConfig(cfg string, step int) string {
label = "alpine-99"
x = 100
y = 200
+ hide_links = false
nodedefinition = "alpine"
imagedefinition = element(data.cml2_images.test.image_list, 0).id
ram = 1024
@@ -371,5 +440,4 @@ resource "cml2_node" "r1" {
nodedefinition = "alpine"
}
`, cfg)
-
}
diff --git a/internal/provider/resource/node/update.go b/internal/provider/resource/node/update.go
index e747fec..6416f6b 100644
--- a/internal/provider/resource/node/update.go
+++ b/internal/provider/resource/node/update.go
@@ -14,7 +14,6 @@ import (
)
func (r NodeResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
-
var (
stateData, planData cmlschema.NodeModel
err error
@@ -33,9 +32,10 @@ func (r NodeResource) Update(ctx context.Context, req resource.UpdateRequest, re
}
node := &cmlclient.Node{
- ID: planData.ID.ValueString(),
- LabID: planData.LabID.ValueString(),
- State: planData.State.ValueString(),
+ ID: planData.ID.ValueString(),
+ LabID: planData.LabID.ValueString(),
+ State: planData.State.ValueString(),
+ NodeDefinition: planData.NodeDefinition.ValueString(),
}
if !planData.X.IsNull() {
@@ -44,6 +44,9 @@ func (r NodeResource) Update(ctx context.Context, req resource.UpdateRequest, re
if !planData.Y.IsNull() {
node.Y = int(planData.Y.ValueInt64())
}
+ if !planData.HideLinks.IsNull() {
+ node.HideLinks = bool(planData.HideLinks.ValueBool())
+ }
if !planData.Label.IsNull() {
node.Label = planData.Label.ValueString()
}
@@ -94,6 +97,28 @@ func (r NodeResource) Update(ctx context.Context, req resource.UpdateRequest, re
return
}
+ // work around the fact that updating an external connector will "resolve"
+ // the device name (if given, worked in previous versions" with the
+ // label... e.g. virbr0 -> NAT, bridge0 -> System Bridge. We want to keep
+ // the original value in this case, otherwise we run into inconsistent
+ // state!
+ if node.NodeDefinition == "external_connector" {
+ // tflog.Warn(ctx, "$$$", map[string]any{
+ // "plan_config": planData.Configuration.ValueString(),
+ // "state_config": stateData.Configuration.ValueString(),
+ // "old_config": *node.Configuration,
+ // "new_config": *newNode.Configuration,
+ // })
+ // if the state hasn't changed but it should have
+ if planData.Configuration.ValueString() != *newNode.Configuration {
+ resp.Diagnostics.AddError(
+ "External connector configuration",
+ fmt.Sprintf("provide proper external connector configuration, not a device name (deprecated). API returned %q, configured was %q!", *newNode.Configuration, *node.Configuration),
+ )
+ return
+ }
+ }
+
resp.Diagnostics.Append(
tfsdk.ValueFrom(
ctx,
diff --git a/internal/provider/resource/user/create.go b/internal/provider/resource/user/create.go
index db86a61..a235ad8 100644
--- a/internal/provider/resource/user/create.go
+++ b/internal/provider/resource/user/create.go
@@ -14,7 +14,6 @@ import (
)
func (r *UserResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
-
var (
data cmlschema.UserModel
err error
diff --git a/internal/provider/resource/user/meta.go b/internal/provider/resource/user/meta.go
index 92f9aa8..a060524 100644
--- a/internal/provider/resource/user/meta.go
+++ b/internal/provider/resource/user/meta.go
@@ -11,8 +11,10 @@ import (
)
// Ensure provider defined types fully satisfy framework interfaces
-var _ resource.Resource = &UserResource{}
-var _ resource.ResourceWithImportState = &UserResource{}
+var (
+ _ resource.Resource = &UserResource{}
+ _ resource.ResourceWithImportState = &UserResource{}
+)
type UserResource struct {
cfg *common.ProviderConfig