diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4d5635f..e64f5c3 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -17,7 +17,7 @@ jobs: - name: Unshallow run: git fetch --prune --unshallow - name: Setup Go - uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0 + uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0 with: go-version: "1.22" - name: Import GPG Key diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e6885d3..f5fbc39 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -26,7 +26,7 @@ jobs: steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0 + - uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0 with: go-version-file: "go.mod" cache: true @@ -36,7 +36,7 @@ jobs: - run: go build -v . - name: Run linters - uses: golangci/golangci-lint-action@971e284b6050e8a5849b72094c50ab08da042db8 # v6.1.1 + uses: golangci/golangci-lint-action@ec5d18412c0aeab7936cb16880d708ba2a64e1ae # v6.2.0 with: version: latest @@ -45,11 +45,13 @@ jobs: steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0 + - uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0 with: go-version-file: "go.mod" cache: true + - uses: hashicorp/setup-terraform@b9cd54a3c349d3f38e8881555d616ced269862dd # v3.1.2 + - run: go generate ./... - name: git diff @@ -83,7 +85,7 @@ jobs: steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0 + - uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0 with: go-version-file: "go.mod" cache: true @@ -108,7 +110,7 @@ jobs: steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0 + - uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0 with: go-version: "1.22" id: go diff --git a/README.md b/README.md index 8eeafa0..e79f8eb 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ The provider currently supports resources and data sources for: - Templates + Template Versions - Groups - Workspace Proxies -- Organizations (Data Source only) +- Organizations ## Requirements diff --git a/docs/index.md b/docs/index.md index 3d9be49..79df017 100644 --- a/docs/index.md +++ b/docs/index.md @@ -27,7 +27,7 @@ terraform { } provider "coderd" { - url = "coder.example.com" + url = "https://coder.example.com" token = "****" } diff --git a/docs/resources/organization.md b/docs/resources/organization.md index 9556be4..6dbc5d1 100644 --- a/docs/resources/organization.md +++ b/docs/resources/organization.md @@ -3,12 +3,17 @@ page_title: "coderd_organization Resource - terraform-provider-coderd" subcategory: "" description: |- - An organization on the Coder deployment + An organization on the Coder deployment. + ~> Warning + This resource is only compatible with Coder version 2.16.0 https://github.com/coder/coder/releases/tag/v2.16.0 and later. --- # coderd_organization (Resource) -An organization on the Coder deployment +An organization on the Coder deployment. + +~> **Warning** +This resource is only compatible with Coder version [2.16.0](https://github.com/coder/coder/releases/tag/v2.16.0) and later. @@ -23,9 +28,9 @@ An organization on the Coder deployment - `description` (String) - `display_name` (String) Display name of the organization. Defaults to name. -- `group_sync` (Block, Optional) (see [below for nested schema](#nestedblock--group_sync)) +- `group_sync` (Block, Optional) Group sync settings to sync groups from an IdP. (see [below for nested schema](#nestedblock--group_sync)) - `icon` (String) -- `role_sync` (Block, Optional) (see [below for nested schema](#nestedblock--role_sync)) +- `role_sync` (Block, Optional) Role sync settings to sync organization roles from an IdP. (see [below for nested schema](#nestedblock--role_sync)) ### Read-Only @@ -55,6 +60,15 @@ Optional: Import is supported using the following syntax: ```shell -# Organizations can be imported by their name -terraform import coderd_organization.our_org our_org +# The ID supplied can be either a organization UUID retrieved via the API +# or the name of the organization. +$ terraform import coderd_organization.our_org our-org +``` +Alternatively, in Terraform v1.5.0 and later, an [`import` block](https://developer.hashicorp.com/terraform/language/import) can be used: + +```terraform +import { + to = coderd_organization.our_org + id = "our-org" +} ``` diff --git a/docs/resources/template.md b/docs/resources/template.md index c0efc4b..0b15d2f 100644 --- a/docs/resources/template.md +++ b/docs/resources/template.md @@ -77,7 +77,7 @@ resource "coderd_template" "ubuntu-main" { - `description` (String) A description of the template. - `display_name` (String) The display name of the template. Defaults to the template name. - `failure_ttl_ms` (Number) (Enterprise) The max lifetime before Coder stops all resources for failed workspaces created from this template, in milliseconds. -- `icon` (String) Relative path or external URL that specifes an icon to be displayed in the dashboard. +- `icon` (String) Relative path or external URL that specifies an icon to be displayed in the dashboard. - `max_port_share_level` (String) (Enterprise) The maximum port share level for workspaces created from this template. Defaults to `owner` on an Enterprise deployment, or `public` otherwise. - `organization_id` (String) The ID of the organization. Defaults to the provider's default organization - `require_active_version` (Boolean) (Enterprise) Whether workspaces must be created from the active version of this template. Defaults to false. diff --git a/examples/provider/provider.tf b/examples/provider/provider.tf index fe3b9dc..d50d5e7 100644 --- a/examples/provider/provider.tf +++ b/examples/provider/provider.tf @@ -7,7 +7,7 @@ terraform { } provider "coderd" { - url = "coder.example.com" + url = "https://coder.example.com" token = "****" } diff --git a/examples/resources/coderd_organization/import.sh b/examples/resources/coderd_organization/import.sh index 882dce6..45bb87a 100644 --- a/examples/resources/coderd_organization/import.sh +++ b/examples/resources/coderd_organization/import.sh @@ -1,2 +1,11 @@ -# Organizations can be imported by their name -terraform import coderd_organization.our_org our_org +# The ID supplied can be either a organization UUID retrieved via the API +# or the name of the organization. +$ terraform import coderd_organization.our_org our-org +``` +Alternatively, in Terraform v1.5.0 and later, an [`import` block](https://developer.hashicorp.com/terraform/language/import) can be used: + +```terraform +import { + to = coderd_organization.our_org + id = "our-org" +} diff --git a/go.mod b/go.mod index 4c43f7c..20cbf9a 100644 --- a/go.mod +++ b/go.mod @@ -3,18 +3,18 @@ module github.com/coder/terraform-provider-coderd go 1.22.8 require ( - cdr.dev/slog v1.6.2-0.20240126064726-20367d4aede6 - github.com/coder/coder/v2 v2.17.0 - github.com/docker/docker v27.2.1+incompatible + cdr.dev/slog v1.6.2-0.20241112041820-0ec81e6e67bb + github.com/coder/coder/v2 v2.18.3 + github.com/docker/docker v27.5.0+incompatible github.com/docker/go-connections v0.5.0 github.com/google/uuid v1.6.0 github.com/hashicorp/terraform-plugin-docs v0.20.1 github.com/hashicorp/terraform-plugin-framework v1.13.0 - github.com/hashicorp/terraform-plugin-framework-validators v0.15.0 + github.com/hashicorp/terraform-plugin-framework-validators v0.16.0 github.com/hashicorp/terraform-plugin-go v0.25.0 github.com/hashicorp/terraform-plugin-log v0.9.0 github.com/hashicorp/terraform-plugin-testing v1.11.0 - github.com/otiai10/copy v1.14.0 + github.com/otiai10/copy v1.14.1 github.com/stretchr/testify v1.10.0 ) @@ -45,7 +45,7 @@ require ( github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cloudflare/circl v1.3.7 // indirect github.com/coder/pretty v0.0.0-20230908205945-e89ba86370e0 // indirect - github.com/coder/serpent v0.8.0 // indirect + github.com/coder/serpent v0.10.0 // indirect github.com/coder/terraform-provider-coder v1.0.2 // indirect github.com/coreos/go-oidc/v3 v3.11.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect @@ -107,6 +107,7 @@ require ( github.com/oklog/run v1.1.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0 // indirect + github.com/otiai10/mint v1.6.3 // indirect github.com/outcaste-io/ristretto v0.2.3 // indirect github.com/philhofer/fwd v1.1.3-0.20240612014219-fbbf4953d986 // indirect github.com/pion/transport/v2 v2.2.10 // indirect @@ -114,7 +115,7 @@ require ( github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/posener/complete v1.2.3 // indirect - github.com/prometheus/client_golang v1.20.4 // indirect + github.com/prometheus/client_golang v1.20.5 // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.60.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect @@ -133,7 +134,7 @@ require ( github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect - github.com/yuin/goldmark v1.7.7 // indirect + github.com/yuin/goldmark v1.7.8 // indirect github.com/yuin/goldmark-meta v1.1.0 // indirect github.com/zclconf/go-cty v1.15.0 // indirect github.com/zeebo/errs v1.3.0 // indirect @@ -148,23 +149,23 @@ require ( go.opentelemetry.io/otel/trace v1.30.0 // indirect go.opentelemetry.io/proto/otlp v1.3.1 // indirect go.uber.org/atomic v1.11.0 // indirect - golang.org/x/crypto v0.29.0 // indirect + golang.org/x/crypto v0.31.0 // indirect golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa // indirect - golang.org/x/mod v0.21.0 // indirect - golang.org/x/net v0.30.0 // indirect - golang.org/x/oauth2 v0.23.0 // indirect - golang.org/x/sync v0.9.0 // indirect - golang.org/x/sys v0.27.0 // indirect - golang.org/x/term v0.26.0 // indirect - golang.org/x/text v0.20.0 // indirect - golang.org/x/time v0.7.0 // indirect - golang.org/x/tools v0.26.0 // indirect + golang.org/x/mod v0.22.0 // indirect + golang.org/x/net v0.33.0 // indirect + golang.org/x/oauth2 v0.24.0 // indirect + golang.org/x/sync v0.10.0 // indirect + golang.org/x/sys v0.28.0 // indirect + golang.org/x/term v0.27.0 // indirect + golang.org/x/text v0.21.0 // indirect + golang.org/x/time v0.8.0 // indirect + golang.org/x/tools v0.27.0 // indirect golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect google.golang.org/appengine v1.6.8 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20241007155032-5fefd90f89a9 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 // indirect - google.golang.org/grpc v1.67.1 // indirect - google.golang.org/protobuf v1.35.1 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241113202542-65e8d215514f // indirect + google.golang.org/grpc v1.68.0 // indirect + google.golang.org/protobuf v1.35.2 // indirect gopkg.in/DataDog/dd-trace-go.v1 v1.69.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index d9a08c6..1c80315 100644 --- a/go.sum +++ b/go.sum @@ -1,13 +1,13 @@ -cdr.dev/slog v1.6.2-0.20240126064726-20367d4aede6 h1:KHblWIE/KHOwQ6lEbMZt6YpcGve2FEZ1sDtrW1Am5UI= -cdr.dev/slog v1.6.2-0.20240126064726-20367d4aede6/go.mod h1:NaoTA7KwopCrnaSb0JXTC0PTp/O/Y83Lndnq0OEV3ZQ= +cdr.dev/slog v1.6.2-0.20241112041820-0ec81e6e67bb h1:4MKA8lBQLnCqj2myJCb5Lzoa65y0tABO4gHrxuMdsCQ= +cdr.dev/slog v1.6.2-0.20241112041820-0ec81e6e67bb/go.mod h1:NaoTA7KwopCrnaSb0JXTC0PTp/O/Y83Lndnq0OEV3ZQ= cloud.google.com/go v0.110.10 h1:LXy9GEO+timppncPIAZoOj3l58LIU9k+kn48AN7IO3Y= cloud.google.com/go/compute v1.23.3 h1:6sVlXXBmbd7jNX0Ipq0trII3e4n1/MsADLK6a+aiVlk= cloud.google.com/go/compute/metadata v0.5.2 h1:UxK4uu/Tn+I3p2dYWTfiX4wva7aYlKixAHn3fyqngqo= cloud.google.com/go/compute/metadata v0.5.2/go.mod h1:C66sj2AluDcIqakBq/M8lw8/ybHgOZqin2obFxa/E5k= -cloud.google.com/go/logging v1.11.0 h1:v3ktVzXMV7CwHq1MBF65wcqLMA7i+z3YxbUsoK7mOKs= -cloud.google.com/go/logging v1.11.0/go.mod h1:5LDiJC/RxTt+fHc1LAt20R9TKiUTReDg6RuuFOZ67+A= -cloud.google.com/go/longrunning v0.6.1 h1:lOLTFxYpr8hcRtcwWir5ITh1PAKUD/sG2lKrTSYjyMc= -cloud.google.com/go/longrunning v0.6.1/go.mod h1:nHISoOZpBcmlwbJmiVk5oDRz0qG/ZxPynEGs1iZ79s0= +cloud.google.com/go/logging v1.12.0 h1:ex1igYcGFd4S/RZWOCU51StlIEuey5bjqwH9ZYjHibk= +cloud.google.com/go/logging v1.12.0/go.mod h1:wwYBt5HlYP1InnrtYI0wtwttpVU1rifnMT7RejksUAM= +cloud.google.com/go/longrunning v0.6.2 h1:xjDfh1pQcWPEvnfjZmwjKQEcHnpz6lHjfy7Fo0MK+hc= +cloud.google.com/go/longrunning v0.6.2/go.mod h1:k/vIs83RN4bE3YCswdXC5PFfWVILjm3hpEUlSko4PiI= dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= @@ -75,22 +75,22 @@ github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyY github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/charmbracelet/lipgloss v0.13.0 h1:4X3PPeoWEDCMvzDvGmTajSyYPcZM4+y8sCA/SsA3cjw= -github.com/charmbracelet/lipgloss v0.13.0/go.mod h1:nw4zy0SBX/F/eAO1cWdcvy6qnkDUxr8Lw7dvFrAIbbY= -github.com/charmbracelet/x/ansi v0.2.3 h1:VfFN0NUpcjBRd4DnKfRaIRo53KRgey/nhOoEqosGDEY= -github.com/charmbracelet/x/ansi v0.2.3/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw= +github.com/charmbracelet/lipgloss v1.0.0 h1:O7VkGDvqEdGi93X+DeqsQ7PKHDgtQfF8j8/O2qFMQNg= +github.com/charmbracelet/lipgloss v1.0.0/go.mod h1:U5fy9Z+C38obMs+T+tJqst9VGzlOYGj4ri9reL3qUlo= +github.com/charmbracelet/x/ansi v0.4.5 h1:LqK4vwBNaXw2AyGIICa5/29Sbdq58GbGdFngSexTdRM= +github.com/charmbracelet/x/ansi v0.4.5/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw= github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d h1:77cEq6EriyTZ0g/qfRdp61a3Uu/AWrgIq2s0ClJV1g0= github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d/go.mod h1:8EPpVsBuRksnlj1mLy4AWzRNQYxauNi62uWcE3to6eA= github.com/chenzhuoyu/iasm v0.9.0 h1:9fhXjVzq5hUy2gkhhgHl95zG2cEAhw9OSGs8toWWAwo= github.com/chenzhuoyu/iasm v0.9.0/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog= github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU= github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA= -github.com/coder/coder/v2 v2.17.0 h1:U59FfsE++IitesBaCUzAX6/9A+VpnXQKO81RzefWVww= -github.com/coder/coder/v2 v2.17.0/go.mod h1:5Fu0xCkdXPuFLwYq6ThyI4DAv4v//Sx5saM/M5CAU2w= +github.com/coder/coder/v2 v2.18.3 h1:3GuiJogiwJhgocQ189lBZpobXdLHTpEAck+I9ybYfAk= +github.com/coder/coder/v2 v2.18.3/go.mod h1:mh7x10UbkIlNO0DjwzNsfD1mDq9iT5USUy1ZAp36mRw= github.com/coder/pretty v0.0.0-20230908205945-e89ba86370e0 h1:3A0ES21Ke+FxEM8CXx9n47SZOKOpgSE1bbJzlE4qPVs= github.com/coder/pretty v0.0.0-20230908205945-e89ba86370e0/go.mod h1:5UuS2Ts+nTToAMeOjNlnHFkPahrtDkmpydBen/3wgZc= -github.com/coder/serpent v0.8.0 h1:6OR+k6fekhSeEDmwwzBgnSjaa7FfGGrMlc3GoAEH9dg= -github.com/coder/serpent v0.8.0/go.mod h1:cZFW6/fP+kE9nd/oRkEHJpG6sXCtQ+AX7WMMEHv0Y3Q= +github.com/coder/serpent v0.10.0 h1:ofVk9FJXSek+SmL3yVE3GoArP83M+1tX+H7S4t8BSuM= +github.com/coder/serpent v0.10.0/go.mod h1:cZFW6/fP+kE9nd/oRkEHJpG6sXCtQ+AX7WMMEHv0Y3Q= github.com/coder/terraform-provider-coder v1.0.2 h1:xKbnJF/XUxcUJlZoC3ZkNOj4PZvk5Stdkel2TCZluDQ= github.com/coder/terraform-provider-coder v1.0.2/go.mod h1:1f3EjO+DA9QcIbM7sBSk/Ffw3u7kh6vXNBIQfV59yUk= github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= @@ -107,8 +107,8 @@ github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczC github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.2.1+incompatible h1:fQdiLfW7VLscyoeYEBz7/J8soYFDZV1u6VW6gJEjNMI= -github.com/docker/docker v27.2.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.5.0+incompatible h1:um++2NcQtGRTz5eEgO6aJimo6/JxrTXC941hd05JO6U= +github.com/docker/docker v27.5.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= @@ -162,8 +162,8 @@ github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= -github.com/go-playground/validator/v10 v10.22.0 h1:k6HsTZ0sTnROkhS//R0O+55JgM8C4Bx7ia+JlgcnOao= -github.com/go-playground/validator/v10 v10.22.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= +github.com/go-playground/validator/v10 v10.23.0 h1:/PwmTwZhS0dPkav3cdK9kV1FsAmrL8sThn8IHr/sO+o= +github.com/go-playground/validator/v10 v10.23.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM= github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= @@ -255,8 +255,8 @@ github.com/hashicorp/terraform-plugin-docs v0.20.1 h1:Fq7E/HrU8kuZu3hNliZGwloFWS github.com/hashicorp/terraform-plugin-docs v0.20.1/go.mod h1:Yz6HoK7/EgzSrHPB9J/lWFzwl9/xep2OPnc5jaJDV90= github.com/hashicorp/terraform-plugin-framework v1.13.0 h1:8OTG4+oZUfKgnfTdPTJwZ532Bh2BobF4H+yBiYJ/scw= github.com/hashicorp/terraform-plugin-framework v1.13.0/go.mod h1:j64rwMGpgM3NYXTKuxrCnyubQb/4VKldEKlcG8cvmjU= -github.com/hashicorp/terraform-plugin-framework-validators v0.15.0 h1:RXMmu7JgpFjnI1a5QjMCBb11usrW2OtAG+iOTIj5c9Y= -github.com/hashicorp/terraform-plugin-framework-validators v0.15.0/go.mod h1:Bh89/hNmqsEWug4/XWKYBwtnw3tbz5BAy1L1OgvbIaY= +github.com/hashicorp/terraform-plugin-framework-validators v0.16.0 h1:O9QqGoYDzQT7lwTXUsZEtgabeWW96zUBh47Smn2lkFA= +github.com/hashicorp/terraform-plugin-framework-validators v0.16.0/go.mod h1:Bh89/hNmqsEWug4/XWKYBwtnw3tbz5BAy1L1OgvbIaY= github.com/hashicorp/terraform-plugin-go v0.25.0 h1:oi13cx7xXA6QciMcpcFi/rwA974rdTxjqEhXJjbAyks= github.com/hashicorp/terraform-plugin-go v0.25.0/go.mod h1:+SYagMYadJP86Kvn+TGeV+ofr/R3g4/If0O5sO96MVw= github.com/hashicorp/terraform-plugin-log v0.9.0 h1:i7hOA+vdAItN1/7UrfBqBwvYPQ9TFvymaRGZED3FCV0= @@ -368,10 +368,10 @@ github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQ github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= -github.com/otiai10/copy v1.14.0 h1:dCI/t1iTdYGtkvCuBG2BgR6KZa83PTclw4U5n2wAllU= -github.com/otiai10/copy v1.14.0/go.mod h1:ECfuL02W+/FkTWZWgQqXPWZgW9oeKCSQ5qVfSc4qc4w= -github.com/otiai10/mint v1.5.1 h1:XaPLeE+9vGbuyEHem1JNk3bYc7KKqyI/na0/mLd/Kks= -github.com/otiai10/mint v1.5.1/go.mod h1:MJm72SBthJjz8qhefc4z1PYEieWmy8Bku7CjcAqyUSM= +github.com/otiai10/copy v1.14.1 h1:5/7E6qsUMBaH5AnQ0sSLzzTg1oTECmcCmT6lvF45Na8= +github.com/otiai10/copy v1.14.1/go.mod h1:oQwrEDDOci3IM8dJF0d8+jnbfPDllW6vUjNc3DoZm9I= +github.com/otiai10/mint v1.6.3 h1:87qsV/aw1F5as1eH1zS/yqHY85ANKVMgkDrf9rcxbQs= +github.com/otiai10/mint v1.6.3/go.mod h1:MJm72SBthJjz8qhefc4z1PYEieWmy8Bku7CjcAqyUSM= github.com/outcaste-io/ristretto v0.2.3 h1:AK4zt/fJ76kjlYObOeNwh4T3asEuaCmp26pOvUOL9w0= github.com/outcaste-io/ristretto v0.2.3/go.mod h1:W8HywhmtlopSB1jeMg3JtdIhf+DYkLAr0VN/s4+MHac= github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= @@ -396,8 +396,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/posener/complete v1.2.3 h1:NP0eAhjcjImqslEwo/1hq7gpajME0fTLTezBKDqfXqo= github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= -github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= -github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y= +github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA= @@ -489,8 +489,8 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -github.com/yuin/goldmark v1.7.7 h1:5m9rrB1sW3JUMToKFQfb+FGt1U7r57IHu5GrYrG2nqU= -github.com/yuin/goldmark v1.7.7/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= +github.com/yuin/goldmark v1.7.8 h1:iERMLn0/QJeHFhxSt3p6PeN9mGnvIKSpG9YYorDMnic= +github.com/yuin/goldmark v1.7.8/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= github.com/yuin/goldmark-meta v1.1.0 h1:pWw+JLHGZe8Rk0EGsMVssiNb/AaPMHfSRszZeUeiOUc= github.com/yuin/goldmark-meta v1.1.0/go.mod h1:U4spWENafuA7Zyg+Lj5RqK/MF+ovMYtBvXi1lBb2VP0= github.com/zclconf/go-cty v1.15.0 h1:tTCRWxsexYUmtt/wVxgDClUe+uQusuI443uL6e+5sXQ= @@ -542,8 +542,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh 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.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= -golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ= -golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg= +golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= +golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa h1:ELnwvuAXPNtPk1TJRuGkI9fDTwym6AYBu0qzT8AcHdI= golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= @@ -551,8 +551,8 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= -golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= +golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -565,10 +565,10 @@ 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.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= -golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= -golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= -golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs= -golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= +golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= +golang.org/x/oauth2 v0.24.0 h1:KTBBxWqUa0ykRPLtV69rRto9TLXcqYkeswu48x/gvNE= +golang.org/x/oauth2 v0.24.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= 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-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -576,8 +576,8 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= -golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= +golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -603,8 +603,8 @@ 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/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= -golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= +golang.org/x/sys v0.28.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.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -612,8 +612,8 @@ golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= -golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU= -golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E= +golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q= +golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= 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= @@ -623,11 +623,11 @@ 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.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= -golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= +golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ= -golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg= +golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= 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.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= @@ -635,8 +635,8 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ= -golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0= +golang.org/x/tools v0.27.0 h1:qEKojBykQkQ4EynWy4S8Weg69NumxKdn40Fce3uc/8o= +golang.org/x/tools v0.27.0/go.mod h1:sUi0ZgbwW9ZPAq26Ekut+weQPR5eIM6GQLQ1Yjm1H0Q= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -646,19 +646,19 @@ golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da/go.mod h1:NDW/Ps6MPRej6f google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 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 v0.0.0-20241015192408-796eee8c2d53 h1:Df6WuGvthPzc+JiQ/G+m+sNX24kc0aTBqoDN/0yyykE= -google.golang.org/genproto v0.0.0-20241015192408-796eee8c2d53/go.mod h1:fheguH3Am2dGp1LfXkrvwqC/KlFq8F0nLq3LryOMrrE= -google.golang.org/genproto/googleapis/api v0.0.0-20241007155032-5fefd90f89a9 h1:T6rh4haD3GVYsgEfWExoCZA2o2FmbNyKpTuAxbEFPTg= -google.golang.org/genproto/googleapis/api v0.0.0-20241007155032-5fefd90f89a9/go.mod h1:wp2WsuBYj6j8wUdo3ToZsdxxixbvQNAHqVJrTgi5E5M= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 h1:X58yt85/IXCx0Y3ZwN6sEIKZzQtDEYaBWrDvErdXrRE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= -google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= -google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= +google.golang.org/genproto v0.0.0-20241113202542-65e8d215514f h1:zDoHYmMzMacIdjNe+P2XiTmPsLawi/pCbSPfxt6lTfw= +google.golang.org/genproto v0.0.0-20241113202542-65e8d215514f/go.mod h1:Q5m6g8b5KaFFzsQFIGdJkSJDGeJiybVenoYFMMa3ohI= +google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 h1:M0KvPgPmDZHPlbRbaNU1APr28TvwvvdUPlSv7PUvy8g= +google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:dguCy7UOdZhTvLzDyt15+rOrawrpM4q7DD9dQ1P11P4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241113202542-65e8d215514f h1:C1QccEa9kUwvMgEUORqQD9S17QesQijxjZ84sO82mfo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241113202542-65e8d215514f/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= +google.golang.org/grpc v1.68.0 h1:aHQeeJbo8zAkAa3pRzrVjZlbz6uSfeOXlJNQM0RAbz0= +google.golang.org/grpc v1.68.0/go.mod h1:fmSPC5AsjSBCK54MyHRx48kpOti1/jRfOlwEWywNjWA= 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.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= -google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= -google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io= +google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/DataDog/dd-trace-go.v1 v1.69.0 h1:zSY6DDsFRMQDNQYKWCv/AEwJXoPpDf1FfMyw7I1B7M8= gopkg.in/DataDog/dd-trace-go.v1 v1.69.0/go.mod h1:U9AOeBHNAL95JXcd/SPf4a7O5GNeF/yD13sJtli/yaU= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/integration/integration.go b/integration/integration.go index f2ed0dd..9f7120f 100644 --- a/integration/integration.go +++ b/integration/integration.go @@ -51,9 +51,10 @@ func StartCoder(ctx context.Context, t *testing.T, name string, useLicense bool) ctr, err := cli.ContainerCreate(ctx, &container.Config{ Image: coderImg + ":" + coderVersion, Env: []string{ - "CODER_HTTP_ADDRESS=0.0.0.0:3000", // Listen on all interfaces inside the container - "CODER_ACCESS_URL=http://localhost:3000", // Set explicitly to avoid creating try.coder.app URLs. - "CODER_TELEMETRY_ENABLE=false", // Avoid creating noise. + "CODER_HTTP_ADDRESS=0.0.0.0:3000", // Listen on all interfaces inside the container + "CODER_ACCESS_URL=http://localhost:3000", // Set explicitly to avoid creating try.coder.app URLs. + "CODER_TELEMETRY_ENABLE=false", // Avoid creating noise. + "CODER_DANGEROUS_DISABLE_RATE_LIMITS=true", // Avoid hitting file rate limit in tests. }, Labels: map[string]string{}, ExposedPorts: map[nat.Port]struct{}{nat.Port("3000/tcp"): {}}, @@ -95,7 +96,7 @@ func StartCoder(ctx context.Context, t *testing.T, name string, useLicense bool) t.Logf("not ready yet: %s", err.Error()) } return err == nil - }, 15*time.Second, time.Second, "coder failed to become ready in time") + }, 20*time.Second, time.Second, "coder failed to become ready in time") _, err = client.CreateFirstUser(ctx, codersdk.CreateFirstUserRequest{ Email: testEmail, Username: testUsername, diff --git a/integration/integration_test.go b/integration/integration_test.go index 3bfdae4..aeb90a5 100644 --- a/integration/integration_test.go +++ b/integration/integration_test.go @@ -166,7 +166,7 @@ func TestIntegration(t *testing.T) { tfCmd.Stderr = &buf tt.preF(t, client) if err := tfCmd.Run(); !assert.NoError(t, err) { - t.Logf("%s", buf.String()) + t.Log(buf.String()) t.FailNow() } tt.assertF(t, client) diff --git a/internal/provider/organization_resource.go b/internal/provider/organization_resource.go index 397f92e..2c39f0c 100644 --- a/internal/provider/organization_resource.go +++ b/internal/provider/organization_resource.go @@ -94,8 +94,11 @@ func (r *OrganizationResource) Metadata(ctx context.Context, req resource.Metada func (r *OrganizationResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { resp.Schema = schema.Schema{ - MarkdownDescription: "An organization on the Coder deployment", + MarkdownDescription: `An organization on the Coder deployment. +~> **Warning** +This resource is only compatible with Coder version [2.16.0](https://github.com/coder/coder/releases/tag/v2.16.0) and later. +`, Attributes: map[string]schema.Attribute{ "id": schema.StringAttribute{ CustomType: UUIDType, @@ -135,6 +138,7 @@ func (r *OrganizationResource) Schema(ctx context.Context, req resource.SchemaRe Blocks: map[string]schema.Block{ "group_sync": schema.SingleNestedBlock{ + MarkdownDescription: `Group sync settings to sync groups from an IdP.`, Attributes: map[string]schema.Attribute{ "field": schema.StringAttribute{ Optional: true, @@ -167,6 +171,7 @@ func (r *OrganizationResource) Schema(ctx context.Context, req resource.SchemaRe }, }, "role_sync": schema.SingleNestedBlock{ + MarkdownDescription: `Role sync settings to sync organization roles from an IdP.`, Attributes: map[string]schema.Attribute{ "field": schema.StringAttribute{ Optional: true, diff --git a/internal/provider/provider.go b/internal/provider/provider.go index b8b9fa7..b7cfe88 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -2,6 +2,7 @@ package provider import ( "context" + "fmt" "net/url" "os" "strings" @@ -101,7 +102,16 @@ func (p *CoderdProvider) Configure(ctx context.Context, req provider.ConfigureRe data.Token = types.StringValue(tokenEnv) } - url, err := url.Parse(data.URL.ValueString()) + rawURL := data.URL.ValueString() + if !strings.HasPrefix(rawURL, "http://") && !strings.HasPrefix(rawURL, "https://") { + scheme := "https" + if strings.HasPrefix(rawURL, "localhost") { + scheme = "http" + } + rawURL = fmt.Sprintf("%s://%s", scheme, rawURL) + } + + url, err := url.Parse(rawURL) if err != nil { resp.Diagnostics.AddError("url", "url is not a valid URL: "+err.Error()) return diff --git a/internal/provider/template_resource.go b/internal/provider/template_resource.go index a5834db..8f72b52 100644 --- a/internal/provider/template_resource.go +++ b/internal/provider/template_resource.go @@ -286,7 +286,7 @@ func (r *TemplateResource) Schema(ctx context.Context, req resource.SchemaReques }, }, "icon": schema.StringAttribute{ - MarkdownDescription: "Relative path or external URL that specifes an icon to be displayed in the dashboard.", + MarkdownDescription: "Relative path or external URL that specifies an icon to be displayed in the dashboard.", Optional: true, Computed: true, Default: stringdefault.StaticString(""), @@ -404,7 +404,7 @@ func (r *TemplateResource) Schema(ctx context.Context, req resource.SchemaReques Required: true, Validators: []validator.List{ listvalidator.SizeAtLeast(1), - NewActiveVersionValidator(), + NewVersionsValidator(), }, NestedObject: schema.NestedAttributeObject{ Attributes: map[string]schema.Attribute{ @@ -867,24 +867,24 @@ func (r *TemplateResource) ConfigValidators(context.Context) []resource.ConfigVa return []resource.ConfigValidator{} } -type activeVersionValidator struct{} +type versionsValidator struct{} -func NewActiveVersionValidator() validator.List { - return &activeVersionValidator{} +func NewVersionsValidator() validator.List { + return &versionsValidator{} } // Description implements validator.List. -func (a *activeVersionValidator) Description(ctx context.Context) string { +func (a *versionsValidator) Description(ctx context.Context) string { return a.MarkdownDescription(ctx) } // MarkdownDescription implements validator.List. -func (a *activeVersionValidator) MarkdownDescription(context.Context) string { - return "Validate that exactly one template version has active set to true." +func (a *versionsValidator) MarkdownDescription(context.Context) string { + return "Validate that template version names are unique and that at most one version is active." } // ValidateList implements validator.List. -func (a *activeVersionValidator) ValidateList(ctx context.Context, req validator.ListRequest, resp *validator.ListResponse) { +func (a *versionsValidator) ValidateList(ctx context.Context, req validator.ListRequest, resp *validator.ListResponse) { if req.ConfigValue.IsNull() || req.ConfigValue.IsUnknown() { return } @@ -908,13 +908,13 @@ func (a *activeVersionValidator) ValidateList(ctx context.Context, req validator uniqueNames[version.Name.ValueString()] = struct{}{} } - // Check if only one item in Version has active set to true + // Ensure at most one version is active active := false for _, version := range data { - // `active` is required, so if it's null or unknown, this is Terraform + // `active` defaults to false, so if it's null or unknown, this is Terraform // requesting an early validation. if version.Active.IsNull() || version.Active.IsUnknown() { - return + continue } if version.Active.ValueBool() { if active { @@ -924,12 +924,9 @@ func (a *activeVersionValidator) ValidateList(ctx context.Context, req validator active = true } } - if !active { - resp.Diagnostics.AddError("Client Error", "At least one template version must be active.") - } } -var _ validator.List = &activeVersionValidator{} +var _ validator.List = &versionsValidator{} type versionsPlanModifier struct{} @@ -956,6 +953,12 @@ func (d *versionsPlanModifier) PlanModifyList(ctx context.Context, req planmodif return } + hasActiveVersion, diag := hasOneActiveVersion(configVersions) + if diag.HasError() { + resp.Diagnostics.Append(diag...) + return + } + for i := range planVersions { hash, err := computeDirectoryHash(planVersions[i].Directory.ValueString()) if err != nil { @@ -974,6 +977,13 @@ func (d *versionsPlanModifier) PlanModifyList(ctx context.Context, req planmodif // If this is the first read, init the private state value if lvBytes == nil { lv = make(LastVersionsByHash) + // If there's no prior private state, this might be resource creation, + // in which case one version must be active. + if !hasActiveVersion { + resp.Diagnostics.AddError("Client Error", "At least one template version must be active when creating a"+ + " `coderd_template` resource.\n(Subsequent resource updates can be made without an active template in the list).") + return + } } else { err := json.Unmarshal(lvBytes, &lv) if err != nil { @@ -982,9 +992,34 @@ func (d *versionsPlanModifier) PlanModifyList(ctx context.Context, req planmodif } } - planVersions.reconcileVersionIDs(lv, configVersions) + diag = planVersions.reconcileVersionIDs(lv, configVersions, hasActiveVersion) + if diag.HasError() { + resp.Diagnostics.Append(diag...) + return + } - resp.PlanValue, resp.Diagnostics = types.ListValueFrom(ctx, req.PlanValue.ElementType(ctx), planVersions) + resp.PlanValue, diag = types.ListValueFrom(ctx, req.PlanValue.ElementType(ctx), planVersions) + if diag.HasError() { + resp.Diagnostics.Append(diag...) + } +} + +func hasOneActiveVersion(data Versions) (hasActiveVersion bool, diags diag.Diagnostics) { + active := false + for _, version := range data { + if version.Active.IsNull() || version.Active.IsUnknown() { + // If null or unknown, the value will be defaulted to false + continue + } + if version.Active.ValueBool() { + if active { + diags.AddError("Client Error", "Only one template version can be active at a time.") + return + } + active = true + } + } + return active, diags } func NewVersionsPlanModifier() planmodifier.List { @@ -1309,6 +1344,7 @@ type PreviousTemplateVersion struct { ID uuid.UUID `json:"id"` Name string `json:"name"` TFVars map[string]string `json:"tf_vars"` + Active bool `json:"active"` } type privateState interface { @@ -1331,6 +1367,7 @@ func (v Versions) setPrivateState(ctx context.Context, ps privateState) (diags d ID: version.ID.ValueUUID(), Name: version.Name.ValueString(), TFVars: tfVars, + Active: version.Active.ValueBool(), }) } else { lv[version.DirectoryHash.ValueString()] = []PreviousTemplateVersion{ @@ -1338,6 +1375,7 @@ func (v Versions) setPrivateState(ctx context.Context, ps privateState) (diags d ID: version.ID.ValueUUID(), Name: version.Name.ValueString(), TFVars: tfVars, + Active: version.Active.ValueBool(), }, } } @@ -1350,7 +1388,7 @@ func (v Versions) setPrivateState(ctx context.Context, ps privateState) (diags d return ps.SetKey(ctx, LastVersionsKey, lvBytes) } -func (planVersions Versions) reconcileVersionIDs(lv LastVersionsByHash, configVersions Versions) { +func (planVersions Versions) reconcileVersionIDs(lv LastVersionsByHash, configVersions Versions, hasOneActiveVersion bool) (diag diag.Diagnostics) { // We remove versions that we've matched from `lv`, so make a copy for // resolving tfvar changes at the end. fullLv := make(LastVersionsByHash) @@ -1420,6 +1458,39 @@ func (planVersions Versions) reconcileVersionIDs(lv LastVersionsByHash, configVe } } } + + // If a version was deactivated, and no active version was set, we need to + // return an error to avoid a post-apply plan being non-empty. + if !hasOneActiveVersion { + for i := range planVersions { + if !planVersions[i].ID.IsUnknown() { + prevs, ok := fullLv[planVersions[i].DirectoryHash.ValueString()] + if !ok { + continue + } + if versionDeactivated(prevs, &planVersions[i]) { + diag.AddError("Client Error", "Plan could not determine which version should be active.\n"+ + "Either specify an active version or modify the contents of the previously active version before marking it as inactive.") + return diag + } + } + } + } + return diag +} + +func versionDeactivated(prevs []PreviousTemplateVersion, planned *TemplateVersion) bool { + for _, prev := range prevs { + if prev.ID == planned.ID.ValueUUID() { + if prev.Active && + !planned.Active.IsNull() && + !planned.Active.IsUnknown() && + !planned.Active.ValueBool() { + return true + } + } + } + return false } func tfVariablesChanged(prevs []PreviousTemplateVersion, planned *TemplateVersion) bool { diff --git a/internal/provider/template_resource_test.go b/internal/provider/template_resource_test.go index c844da0..5bb1e3b 100644 --- a/internal/provider/template_resource_test.go +++ b/internal/provider/template_resource_test.go @@ -245,7 +245,7 @@ func TestAccTemplateResource(t *testing.T) { Versions: []testAccTemplateVersionConfig{ { // Auto-generated version name - Directory: ptr.Ref("../../integration/template-test/example-template-2/"), + Directory: &exTemplateTwo, TerraformVariables: []testAccTemplateKeyValueConfig{ { Key: ptr.Ref("name"), @@ -256,13 +256,14 @@ func TestAccTemplateResource(t *testing.T) { }, { // Auto-generated version name - Directory: ptr.Ref("../../integration/template-test/example-template-2/"), + Directory: &exTemplateTwo, TerraformVariables: []testAccTemplateKeyValueConfig{ { Key: ptr.Ref("name"), Value: ptr.Ref("world"), }, }, + Active: ptr.Ref(false), }, }, ACL: testAccTemplateACLConfig{ @@ -282,11 +283,11 @@ func TestAccTemplateResource(t *testing.T) { cfg4 := cfg1 cfg4.Versions = slices.Clone(cfg4.Versions) - cfg4.Versions[0].Directory = ptr.Ref("../../integration/template-test/example-template/") + cfg4.Versions[0].Directory = &exTemplateOne cfg5 := cfg4 cfg5.Versions = slices.Clone(cfg5.Versions) - cfg5.Versions[1].Directory = ptr.Ref("../../integration/template-test/example-template/") + cfg5.Versions[1].Directory = &exTemplateOne cfg6 := cfg5 cfg6.Versions = slices.Clone(cfg6.Versions) @@ -373,7 +374,7 @@ func TestAccTemplateResource(t *testing.T) { Versions: []testAccTemplateVersionConfig{ { // Auto-generated version name - Directory: ptr.Ref("../../integration/template-test/example-template-2/"), + Directory: &exTemplateTwo, TerraformVariables: []testAccTemplateKeyValueConfig{ { Key: ptr.Ref("name"), @@ -417,6 +418,222 @@ func TestAccTemplateResource(t *testing.T) { }, }) }) + + t.Run("CreateWithNoActiveVersionErrors", func(t *testing.T) { + cfg1 := testAccTemplateResourceConfig{ + URL: client.URL.String(), + Token: client.SessionToken(), + Name: ptr.Ref("example-template"), + Versions: []testAccTemplateVersionConfig{ + { + // Auto-generated version name + Directory: &exTemplateOne, + Active: ptr.Ref(false), + }, + }, + ACL: testAccTemplateACLConfig{ + null: true, + }, + } + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + IsUnitTest: true, + ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, + Steps: []resource.TestStep{ + { + Config: cfg1.String(t), + ExpectError: regexp.MustCompile("At least one template version must be active when creating"), + }, + }, + }) + }) + + t.Run("AmbiguousActiveVersionResolvedByModifying", func(t *testing.T) { + cfg1 := testAccTemplateResourceConfig{ + URL: client.URL.String(), + Token: client.SessionToken(), + Name: ptr.Ref("example-template"), + Versions: []testAccTemplateVersionConfig{ + { + // Auto-generated version name + Directory: &exTemplateOne, + Active: ptr.Ref(true), + }, + }, + ACL: testAccTemplateACLConfig{ + null: true, + }, + } + + cfg2 := cfg1 + cfg2.Versions = slices.Clone(cfg2.Versions) + cfg2.Versions[0].Active = ptr.Ref(false) + + cfg3 := cfg2 + cfg3.Versions = slices.Clone(cfg3.Versions) + cfg3.Versions[0].Directory = &exTemplateTwo + + cfg2b := cfg1 + cfg2b.Versions = slices.Clone(cfg2b.Versions) + cfg2b.Versions = append(cfg2b.Versions, testAccTemplateVersionConfig{ + Directory: &exTemplateTwo, + Active: ptr.Ref(false), + }) + + cfg3b := cfg2b + cfg3b.Versions = slices.Clone(cfg3b.Versions) + cfg3b.Versions[1].Active = ptr.Ref(true) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + IsUnitTest: true, + ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, + Steps: []resource.TestStep{ + { + Config: cfg1.String(t), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckNumTemplateVersions(ctx, client, 1), + ), + }, + // With an unmodified version deactivated, it's not clear what + // the active version should be. + { + Config: cfg2.String(t), + ExpectError: regexp.MustCompile("Plan could not determine which version should be active."), + }, + // If we modify the version, a new version will be created on `coderd`, + // and the old version can remain active. + { + Config: cfg3.String(t), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckNumTemplateVersions(ctx, client, 2), + resource.TestMatchTypeSetElemNestedAttrs("coderd_template.test", "versions.*", map[string]*regexp.Regexp{ + "active": regexp.MustCompile("false"), + }), + ), + }, + }, + }) + }) + + t.Run("AmbiguousActiveVersionResolvedByCreatingNewVersion", func(t *testing.T) { + cfg1 := testAccTemplateResourceConfig{ + URL: client.URL.String(), + Token: client.SessionToken(), + Name: ptr.Ref("example-template"), + Versions: []testAccTemplateVersionConfig{ + { + // Auto-generated version name + Directory: &exTemplateOne, + Active: ptr.Ref(true), + }, + }, + ACL: testAccTemplateACLConfig{ + null: true, + }, + } + + cfg2 := cfg1 + cfg2.Versions = slices.Clone(cfg2.Versions) + cfg2.Versions[0].Active = ptr.Ref(false) + cfg2.Versions = append(cfg2.Versions, testAccTemplateVersionConfig{ + Directory: &exTemplateTwo, + Active: ptr.Ref(false), + }) + + cfg3 := cfg2 + cfg3.Versions = slices.Clone(cfg3.Versions) + cfg3.Versions[1].Active = ptr.Ref(true) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + IsUnitTest: true, + ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, + Steps: []resource.TestStep{ + { + Config: cfg1.String(t), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckNumTemplateVersions(ctx, client, 1), + ), + }, + // Adding a new version that's not active doesn't help + { + Config: cfg2.String(t), + ExpectError: regexp.MustCompile("Plan could not determine which version should be active."), + }, + // Making that new version active will fix the issue + { + Config: cfg3.String(t), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckNumTemplateVersions(ctx, client, 2), + ), + }, + }, + }) + }) + + t.Run("PushNewInactiveVersion", func(t *testing.T) { + cfg1 := testAccTemplateResourceConfig{ + URL: client.URL.String(), + Token: client.SessionToken(), + Name: ptr.Ref("example-template"), + Versions: []testAccTemplateVersionConfig{ + { + // Auto-generated version name + Directory: &exTemplateOne, + Active: ptr.Ref(true), + }, + }, + ACL: testAccTemplateACLConfig{ + null: true, + }, + } + + cfg2 := cfg1 + cfg2.Versions = slices.Clone(cfg2.Versions) + cfg2.Versions[0].Active = ptr.Ref(false) + cfg2.Versions[0].Directory = &exTemplateTwo + + cfg3 := cfg2 + cfg3.Versions = slices.Clone(cfg3.Versions) + cfg3.Versions[0].Active = ptr.Ref(true) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + IsUnitTest: true, + ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, + Steps: []resource.TestStep{ + // Create one active version + { + Config: cfg1.String(t), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckNumTemplateVersions(ctx, client, 1), + ), + }, + // Modify an existing version, make it inactive + { + Config: cfg2.String(t), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckNumTemplateVersions(ctx, client, 2), + resource.TestMatchTypeSetElemNestedAttrs("coderd_template.test", "versions.*", map[string]*regexp.Regexp{ + "active": regexp.MustCompile("false"), + }), + ), + }, + // Make that modification active + { + Config: cfg3.String(t), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckNumTemplateVersions(ctx, client, 2), + resource.TestMatchTypeSetElemNestedAttrs("coderd_template.test", "versions.*", map[string]*regexp.Regexp{ + "active": regexp.MustCompile("true"), + }), + ), + }, + }, + }) + }) } func TestAccTemplateResourceEnterprise(t *testing.T) { @@ -434,6 +651,10 @@ func TestAccTemplateResourceEnterprise(t *testing.T) { }) require.NoError(t, err) + exTemplateOne := t.TempDir() + err = cp.Copy("../../integration/template-test/example-template", exTemplateOne) + require.NoError(t, err) + cfg1 := testAccTemplateResourceConfig{ URL: client.URL.String(), Token: client.SessionToken(), @@ -441,7 +662,7 @@ func TestAccTemplateResourceEnterprise(t *testing.T) { Versions: []testAccTemplateVersionConfig{ { // Auto-generated version name - Directory: ptr.Ref("../../integration/template-test/example-template"), + Directory: &exTemplateOne, Active: ptr.Ref(true), }, }, @@ -569,6 +790,10 @@ func TestAccTemplateResourceAGPL(t *testing.T) { firstUser, err := client.User(ctx, codersdk.Me) require.NoError(t, err) + exTemplateOne := t.TempDir() + err = cp.Copy("../../integration/template-test/example-template", exTemplateOne) + require.NoError(t, err) + cfg1 := testAccTemplateResourceConfig{ URL: client.URL.String(), Token: client.SessionToken(), @@ -576,7 +801,7 @@ func TestAccTemplateResourceAGPL(t *testing.T) { Versions: []testAccTemplateVersionConfig{ { // Auto-generated version name - Directory: ptr.Ref("../../integration/template-test/example-template/"), + Directory: &exTemplateOne, Active: ptr.Ref(true), }, }, @@ -652,8 +877,8 @@ func TestAccTemplateResourceAGPL(t *testing.T) { func TestAccTemplateResourceVariables(t *testing.T) { cfg := ` provider coderd { - url = "%s" - token = "%s" + url = %q + token = %q } data "coderd_organization" "default" { @@ -677,12 +902,12 @@ resource "coderd_template" "sample" { versions = [ { name = "${var.PRIOR_GIT_COMMIT_SHA}" - directory = "../../integration/template-test/example-template" + directory = %q active = var.ACTIVE }, { name = "${var.CURRENT_GIT_COMMIT_SHA}" - directory = "../../integration/template-test/example-template" + directory = %q active = false } ] @@ -691,7 +916,11 @@ resource "coderd_template" "sample" { ctx := context.Background() client := integration.StartCoder(ctx, t, "template_resource_variables_acc", false) - cfg = fmt.Sprintf(cfg, client.URL.String(), client.SessionToken()) + exTemplateOne := t.TempDir() + err := cp.Copy("../../integration/template-test/example-template", exTemplateOne) + require.NoError(t, err) + + cfg = fmt.Sprintf(cfg, client.URL.String(), client.SessionToken(), exTemplateOne, exTemplateOne) resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -911,11 +1140,13 @@ func TestReconcileVersionIDs(t *testing.T) { aUUID := uuid.New() bUUID := uuid.New() cases := []struct { - Name string - planVersions Versions - configVersions Versions - inputState LastVersionsByHash - expectedVersions Versions + Name string + planVersions Versions + configVersions Versions + inputState LastVersionsByHash + expectedVersions Versions + cfgHasActiveVersion bool + expectError bool }{ { Name: "IdenticalDontRename", @@ -1242,13 +1473,46 @@ func TestReconcileVersionIDs(t *testing.T) { }, }, }, + { + Name: "NoPossibleActiveVersion", + planVersions: []TemplateVersion{ + { + Name: types.StringValue("foo"), + DirectoryHash: types.StringValue("aaa"), + ID: NewUUIDUnknown(), + TerraformVariables: []Variable{}, + Active: types.BoolValue(false), + }, + }, + configVersions: []TemplateVersion{ + { + Name: types.StringValue("foo"), + }, + }, + inputState: map[string][]PreviousTemplateVersion{ + "aaa": { + { + ID: aUUID, + Name: "foo", + TFVars: map[string]string{}, + Active: true, + }, + }, + }, + cfgHasActiveVersion: false, + expectError: true, + }, } for _, c := range cases { c := c t.Run(c.Name, func(t *testing.T) { - c.planVersions.reconcileVersionIDs(c.inputState, c.configVersions) - require.Equal(t, c.expectedVersions, c.planVersions) + diag := c.planVersions.reconcileVersionIDs(c.inputState, c.configVersions, c.cfgHasActiveVersion) + if c.expectError { + require.True(t, diag.HasError()) + } else { + require.Equal(t, c.expectedVersions, c.planVersions) + } }) }
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: