Compare commits

...

15 Commits

Author SHA1 Message Date
Oscar Hermoso 709fb3ce28 🍞 Fix load balancer caring about order of server_ids (#104) 2025-10-05 13:24:58 +08:00
dependabot[bot] 5313e1c7ab 🐹 Bump github.com/hashicorp/terraform-plugin-framework (#103)
Bumps the minor-patch group with 1 update: [github.com/hashicorp/terraform-plugin-framework](https://github.com/hashicorp/terraform-plugin-framework).


Updates `github.com/hashicorp/terraform-plugin-framework` from 1.16.0 to 1.16.1
- [Release notes](https://github.com/hashicorp/terraform-plugin-framework/releases)
- [Changelog](https://github.com/hashicorp/terraform-plugin-framework/blob/main/CHANGELOG.md)
- [Commits](https://github.com/hashicorp/terraform-plugin-framework/compare/v1.16.0...v1.16.1)

---
updated-dependencies:
- dependency-name: github.com/hashicorp/terraform-plugin-framework
  dependency-version: 1.16.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: minor-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-05 09:46:54 +08:00
dependabot[bot] ce349f53f0 🐈 Bump actions/setup-go from 5 to 6 (#100)
Bumps [actions/setup-go](https://github.com/actions/setup-go) from 5 to 6.
- [Release notes](https://github.com/actions/setup-go/releases)
- [Commits](https://github.com/actions/setup-go/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/setup-go
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-05 09:46:41 +08:00
dependabot[bot] 9d3d3e9af3 🐹 Bump the minor-patch group with 4 updates (#101)
Bumps the minor-patch group with 4 updates: [github.com/hashicorp/terraform-plugin-docs](https://github.com/hashicorp/terraform-plugin-docs), [github.com/hashicorp/terraform-plugin-framework](https://github.com/hashicorp/terraform-plugin-framework), [github.com/hashicorp/terraform-plugin-framework-timeouts](https://github.com/hashicorp/terraform-plugin-framework-timeouts) and [github.com/hashicorp/terraform-plugin-go](https://github.com/hashicorp/terraform-plugin-go).


Updates `github.com/hashicorp/terraform-plugin-docs` from 0.22.0 to 0.23.0
- [Release notes](https://github.com/hashicorp/terraform-plugin-docs/releases)
- [Changelog](https://github.com/hashicorp/terraform-plugin-docs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/hashicorp/terraform-plugin-docs/compare/v0.22.0...v0.23.0)

Updates `github.com/hashicorp/terraform-plugin-framework` from 1.15.1 to 1.16.0
- [Release notes](https://github.com/hashicorp/terraform-plugin-framework/releases)
- [Changelog](https://github.com/hashicorp/terraform-plugin-framework/blob/main/CHANGELOG.md)
- [Commits](https://github.com/hashicorp/terraform-plugin-framework/compare/v1.15.1...v1.16.0)

Updates `github.com/hashicorp/terraform-plugin-framework-timeouts` from 0.5.0 to 0.6.0
- [Release notes](https://github.com/hashicorp/terraform-plugin-framework-timeouts/releases)
- [Changelog](https://github.com/hashicorp/terraform-plugin-framework-timeouts/blob/main/CHANGELOG.md)
- [Commits](https://github.com/hashicorp/terraform-plugin-framework-timeouts/compare/v0.5.0...v0.6.0)

Updates `github.com/hashicorp/terraform-plugin-go` from 0.28.0 to 0.29.0
- [Release notes](https://github.com/hashicorp/terraform-plugin-go/releases)
- [Changelog](https://github.com/hashicorp/terraform-plugin-go/blob/main/CHANGELOG.md)
- [Commits](https://github.com/hashicorp/terraform-plugin-go/compare/v0.28.0...v0.29.0)

---
updated-dependencies:
- dependency-name: github.com/hashicorp/terraform-plugin-docs
  dependency-version: 0.23.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: minor-patch
- dependency-name: github.com/hashicorp/terraform-plugin-framework
  dependency-version: 1.16.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: minor-patch
- dependency-name: github.com/hashicorp/terraform-plugin-framework-timeouts
  dependency-version: 0.6.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: minor-patch
- dependency-name: github.com/hashicorp/terraform-plugin-go
  dependency-version: 0.29.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: minor-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-29 10:58:01 +08:00
Oscar Hermoso a0a227c88c Merge pull request #102 from an9wer/server-ipv6
6️⃣ Add "ipv6" attribute to servers
2025-09-29 09:54:22 +08:00
Oscar Hermoso f8edcd0e06 Add tests, update docs, bump OpenAPI schema version 2025-09-29 09:48:25 +08:00
an9wer 04552e0fcf Add 'ipv6' attribute to servers 2025-09-28 12:53:15 +09:30
dependabot[bot] 66fcb6f85e 🐹 Bump github.com/hashicorp/terraform-plugin-testing (#99)
Bumps the minor-patch group with 1 update: [github.com/hashicorp/terraform-plugin-testing](https://github.com/hashicorp/terraform-plugin-testing).


Updates `github.com/hashicorp/terraform-plugin-testing` from 1.13.2 to 1.13.3
- [Release notes](https://github.com/hashicorp/terraform-plugin-testing/releases)
- [Changelog](https://github.com/hashicorp/terraform-plugin-testing/blob/v1.13.3/CHANGELOG.md)
- [Commits](https://github.com/hashicorp/terraform-plugin-testing/compare/v1.13.2...v1.13.3)

---
updated-dependencies:
- dependency-name: github.com/hashicorp/terraform-plugin-testing
  dependency-version: 1.13.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: minor-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-22 12:50:05 +08:00
dependabot[bot] 806bdebaf8 🐈 Bump goreleaser/goreleaser-action in the minor-patch group (#94)
Bumps the minor-patch group with 1 update: [goreleaser/goreleaser-action](https://github.com/goreleaser/goreleaser-action).


Updates `goreleaser/goreleaser-action` from 6.3.0 to 6.4.0
- [Release notes](https://github.com/goreleaser/goreleaser-action/releases)
- [Commits](https://github.com/goreleaser/goreleaser-action/compare/9c156ee8a17a598857849441385a2041ef570552...e435ccd777264be153ace6237001ef4d979d3a7a)

---
updated-dependencies:
- dependency-name: goreleaser/goreleaser-action
  dependency-version: 6.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: minor-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-22 12:49:33 +08:00
dependabot[bot] dd06380c63 🐈 Bump actions/checkout from 4 to 5 (#95)
Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 5.
- [Release notes](https://github.com/actions/checkout/releases)
- [Commits](https://github.com/actions/checkout/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-22 12:49:03 +08:00
Oscar Hermoso 322a8fda80 👆 Update OpenAPI schema to 0.32.1 (#97) 2025-08-18 11:21:23 +08:00
Oscar Hermoso a50daac8e9 🧨 Fix unspecified attribute for load balancer (#93)
* 🧨 Fix unspecified attribute for load balancer

* remove duplicated `timeouts` in schema, test to ensure `ip` is set
2025-08-04 12:22:24 +08:00
dependabot[bot] 424828123d 🐹 Bump github.com/hashicorp/terraform-plugin-framework (#92)
Bumps the minor-patch group with 1 update: [github.com/hashicorp/terraform-plugin-framework](https://github.com/hashicorp/terraform-plugin-framework).


Updates `github.com/hashicorp/terraform-plugin-framework` from 1.15.0 to 1.15.1
- [Release notes](https://github.com/hashicorp/terraform-plugin-framework/releases)
- [Changelog](https://github.com/hashicorp/terraform-plugin-framework/blob/main/CHANGELOG.md)
- [Commits](https://github.com/hashicorp/terraform-plugin-framework/compare/v1.15.0...v1.15.1)

---
updated-dependencies:
- dependency-name: github.com/hashicorp/terraform-plugin-framework
  dependency-version: 1.15.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: minor-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-02 16:12:23 +08:00
Oscar Hermoso 4c50298eca ⛑️ require replacement if VPC ip_range changes (#89) 2025-07-20 09:44:53 +08:00
dependabot[bot] cbef2be0fe 🐹 Bump the minor-patch group across 1 directory with 2 updates (#87)
Bumps the minor-patch group with 2 updates in the / directory: [github.com/hashicorp/terraform-plugin-docs](https://github.com/hashicorp/terraform-plugin-docs) and [github.com/oapi-codegen/oapi-codegen/v2](https://github.com/oapi-codegen/oapi-codegen).


Updates `github.com/hashicorp/terraform-plugin-docs` from 0.21.0 to 0.22.0
- [Release notes](https://github.com/hashicorp/terraform-plugin-docs/releases)
- [Changelog](https://github.com/hashicorp/terraform-plugin-docs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/hashicorp/terraform-plugin-docs/compare/v0.21.0...v0.22.0)

Updates `github.com/oapi-codegen/oapi-codegen/v2` from 2.4.1 to 2.5.0
- [Release notes](https://github.com/oapi-codegen/oapi-codegen/releases)
- [Commits](https://github.com/oapi-codegen/oapi-codegen/compare/v2.4.1...v2.5.0)

---
updated-dependencies:
- dependency-name: github.com/hashicorp/terraform-plugin-docs
  dependency-version: 0.22.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: minor-patch
- dependency-name: github.com/oapi-codegen/oapi-codegen/v2
  dependency-version: 2.5.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: minor-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-18 14:41:42 +08:00
38 changed files with 857 additions and 310 deletions
+8 -3
View File
@@ -23,11 +23,11 @@ jobs:
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
# Allow goreleaser to access older tag information.
fetch-depth: 0
- uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2
- uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0
with:
go-version-file: 'go.mod'
cache: true
@@ -38,10 +38,15 @@ jobs:
gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }}
passphrase: ${{ secrets.PASSPHRASE }}
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@9c156ee8a17a598857849441385a2041ef570552 # v6.3.0
uses: goreleaser/goreleaser-action@e435ccd777264be153ace6237001ef4d979d3a7a # v6.4.0
with:
args: release --clean
env:
# GitHub sets the GITHUB_TOKEN secret automatically.
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GPG_FINGERPRINT: ${{ steps.import_gpg.outputs.fingerprint }}
- name: Publish Release
if: startsWith(github.ref, 'refs/tags/v')
run: gh release edit "${{ github.ref }}" --draft false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+4 -4
View File
@@ -23,8 +23,8 @@ jobs:
group: test
cancel-in-progress: true # would be nice if GH offered cancel-pending instead, https://github.com/orgs/community/discussions/63136
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
- uses: actions/checkout@v5
- uses: actions/setup-go@v6
with:
go-version-file: 'go.mod'
- uses: hashicorp/setup-terraform@v3
@@ -54,8 +54,8 @@ jobs:
# name: Unit Tests
# runs-on: ubuntu-latest
# steps:
# - uses: actions/checkout@v4
# - uses: actions/setup-go@v5
# - uses: actions/checkout@v5
# - uses: actions/setup-go@v6
# with:
# go-version-file: 'go.mod'
# - run: go test -v -cover ./...
+1 -1
View File
@@ -20,9 +20,9 @@ Planned features:
- [x] Cloud Init
- [x] Updating server properties
- [x] "Advanced Features"
- [x] IPV6
- [ ] Customised Backups
- [ ] Software
- [ ] IPV6
- [ ] Alerts
- [x] SSH Keys
- [x] Virtual Private Cloud
+8 -2
View File
@@ -29,16 +29,22 @@ data "binarylane_load_balancer" "example" {
- `forwarding_rules` (Attributes List) The rules that control which traffic the load balancer will forward to servers in the pool. Leave null to accept a default "HTTP" only forwarding rule. (see [below for nested schema](#nestedatt--forwarding_rules))
- `health_check` (Object) The rules that determine which servers are considered 'healthy' and in the server pool for the load balancer. Leave this null to accept appropriate defaults based on the forwarding_rules. (see [below for nested schema](#nestedatt--health_check))
- `ip` (String) The IPv4 address of the load balancer.
- `name` (String) The hostname of the load balancer.
- `region` (String) Leave null to create an anycast load balancer.
- `server_ids` (List of Number) A list of server IDs to assign to this load balancer.
- `server_ids` (Set of Number) A list of server IDs to assign to this load balancer.
<a id="nestedatt--forwarding_rules"></a>
### Nested Schema for `forwarding_rules`
Read-Only:
- `entry_protocol` (String) The protocol that traffic must match for the load balancer to forward it. Valid values are "http" and "https".
- `entry_protocol` (String) The protocol that traffic must match for this load balancer to forward traffic according to this rule.
| Value | Description |
| ----- | ----------- |
| http | The load balancer will forward HTTP traffic that matches this rule. |
| https | The load balancer will forward HTTPS traffic that matches this rule. |
<a id="nestedatt--health_check"></a>
+3
View File
@@ -34,6 +34,7 @@ data "binarylane_server" "example" {
- \> 60 GB must be a multiple of 10
- \> 200 GB must be a multiple of 100
- `image` (String) The slug of the selected operating system, such as `debian-12`. You can fetch a full list of images from the BinaryLane API.
- `ipv6` (Boolean) If `true` this will add a public and private IPv6 address to the server. By default, IPv6 is disabled.
- `memory` (Number) The total memory in MB for this server. Leave null to accept the default size. Valid values:
- must be a multiple of 128
- \> 2048 MB must be a multiple of 1024
@@ -43,7 +44,9 @@ data "binarylane_server" "example" {
- `permalink` (String) A randomly generated two-word identifier assigned to servers in regions that support this feature
- `port_blocking` (Boolean) Port blocking of outgoing connections for email, SSH and Remote Desktop (TCP ports 22, 25, and 3389) is enabled by default for all new servers. If this is false port blocking will be disabled. Disabling port blocking is only available to reviewed accounts.
- `private_ipv4_addresses` (List of String) The private IPv4 addresses assigned to the server.
- `private_ipv6_addresses` (List of String) The private IPv6 addresses assigned to the server.
- `public_ipv4_addresses` (List of String) The public IPv4 addresses assigned to the server.
- `public_ipv6_addresses` (List of String) The public IPv6 addresses assigned to the server.
- `region` (String) The slug of the selected region.
- `size` (String) The slug of the selected size.
- `source_and_destination_check` (Boolean) This attribute can only be set if your server also has a `vpc_id` attribute set. When enabled (which is `true` by default), your server will only be able to send or receive packets that are directly addressed to one of the IP addresses associated with the Cloud Server. Generally, this is desirable behaviour because it prevents IP conflicts and other hard-to-diagnose networking faults due to incorrect network configuration. When `source_and_destination_check` is `false`, your Cloud Server will be able to send and receive packets addressed to any server. This is typically used when you want to use your Cloud Server as a VPN endpoint, a NAT server to provide internet access, or IP forwarding.
-1
View File
@@ -1,7 +1,6 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "binarylane Provider"
subcategory: ""
description: |-
---
+11 -2
View File
@@ -40,19 +40,25 @@ resource "binarylane_load_balancer" "example" {
- `forwarding_rules` (Attributes List) The rules that control which traffic the load balancer will forward to servers in the pool. Leave null to accept a default "HTTP" only forwarding rule. (see [below for nested schema](#nestedatt--forwarding_rules))
- `health_check` (Attributes) The rules that determine which servers are considered 'healthy' and in the server pool for the load balancer. Leave this null to accept appropriate defaults based on the forwarding_rules. (see [below for nested schema](#nestedatt--health_check))
- `region` (String) Leave null to create an anycast load balancer.
- `server_ids` (List of Number) A list of server IDs to assign to this load balancer.
- `server_ids` (Set of Number) A list of server IDs to assign to this load balancer.
- `timeouts` (Attributes) (see [below for nested schema](#nestedatt--timeouts))
### Read-Only
- `id` (Number) The ID of the load balancer to fetch.
- `ip` (String) The IPv4 address of the load balancer.
<a id="nestedatt--forwarding_rules"></a>
### Nested Schema for `forwarding_rules`
Required:
- `entry_protocol` (String) The protocol that traffic must match for the load balancer to forward it. Valid values are "http" and "https".
- `entry_protocol` (String) The protocol that traffic must match for this load balancer to forward traffic according to this rule.
| Value | Description |
| ----- | ----------- |
| http | The load balancer will forward HTTP traffic that matches this rule. |
| https | The load balancer will forward HTTPS traffic that matches this rule. |
<a id="nestedatt--health_check"></a>
@@ -76,11 +82,14 @@ Optional:
Optional:
- `create` (String) A string that can be [parsed as a duration](https://pkg.go.dev/time#ParseDuration) consisting of numbers and unit suffixes, such as "30s" or "2h45m". Valid time units are "s" (seconds), "m" (minutes), "h" (hours).
- `update` (String) A string that can be [parsed as a duration](https://pkg.go.dev/time#ParseDuration) consisting of numbers and unit suffixes, such as "30s" or "2h45m". Valid time units are "s" (seconds), "m" (minutes), "h" (hours).
## Import
Import is supported using the following syntax:
The [`terraform import` command](https://developer.hashicorp.com/terraform/cli/commands/import) can be used, for example:
```shell
terraform import binarylane_load_balancer.example "<name or id>"
```
+5
View File
@@ -44,6 +44,7 @@ resource "binarylane_server" "example" {
- must be a multiple of 5
- \> 60 GB must be a multiple of 10
- \> 200 GB must be a multiple of 100
- `ipv6` (Boolean) If `true` this will add a public and private IPv6 address to the server. By default, IPv6 is disabled.
- `memory` (Number) The total memory in MB for this server. Leave null to accept the default size. Valid values:
- must be a multiple of 128
- \> 2048 MB must be a multiple of 1024
@@ -64,7 +65,9 @@ resource "binarylane_server" "example" {
- `password_change_supported` (Boolean) If this is true then the `password` attribute can be changed with Terraform. If this is false then the `password` attribute can only be replaced with a null/empty value, which will clear the root/administrator password allowing the password to be changed via the web console.
- `permalink` (String) A randomly generated two-word identifier assigned to servers in regions that support this feature
- `private_ipv4_addresses` (List of String) The private IPv4 addresses assigned to the server.
- `private_ipv6_addresses` (List of String) The private IPv6 addresses assigned to the server.
- `public_ipv4_addresses` (List of String) The public IPv4 addresses assigned to the server.
- `public_ipv6_addresses` (List of String) The public IPv6 addresses assigned to the server.
<a id="nestedatt--advanced_features"></a>
### Nested Schema for `advanced_features`
@@ -98,6 +101,8 @@ Optional:
Import is supported using the following syntax:
The [`terraform import` command](https://developer.hashicorp.com/terraform/cli/commands/import) can be used, for example:
```shell
terraform import binarylane_server.example "<server name or id>"
```
+2
View File
@@ -71,6 +71,8 @@ Optional:
Import is supported using the following syntax:
The [`terraform import` command](https://developer.hashicorp.com/terraform/cli/commands/import) can be used, for example:
```shell
terraform import binarylane_server_firewall_rules.example "<server name or id>"
```
+2
View File
@@ -47,6 +47,8 @@ resource "binarylane_server" "example" {
Import is supported using the following syntax:
The [`terraform import` command](https://developer.hashicorp.com/terraform/cli/commands/import) can be used, for example:
```shell
terraform import binarylane_ssh_key.example "<SSH Key ID or fingerprint>"
```
+2
View File
@@ -43,6 +43,8 @@ resource "binarylane_server" "example" {
Import is supported using the following syntax:
The [`terraform import` command](https://developer.hashicorp.com/terraform/cli/commands/import) can be used, for example:
```shell
terraform import binarylane_vpc.example "<vpc_id>"
```
+2
View File
@@ -67,6 +67,8 @@ Optional:
Import is supported using the following syntax:
The [`terraform import` command](https://developer.hashicorp.com/terraform/cli/commands/import) can be used, for example:
```shell
terraform import binarylane_vpc_route_entries.example "<vpc_id>"
```
+2 -2
View File
@@ -3,10 +3,10 @@ bootcmd:
# If you have additional installation steps that need to be awaited, define
# these in the `bootcmd` section and they will also be awaited.
#
- [cloud-init-per, once, 'example-installing', sh, -c, 'sleep 60'] # pretend this is a slow installation step
- [cloud-init-per, instance, 'example-installing', sh, -c, 'sleep 60'] # pretend this is a slow installation step
- [
cloud-init-per,
once,
instance,
'example-done',
sh,
-c,
+26 -25
View File
@@ -1,6 +1,6 @@
module terraform-provider-binarylane
go 1.23.0
go 1.24.0
toolchain go1.24.1
@@ -8,14 +8,14 @@ require (
github.com/deepmap/oapi-codegen v1.16.3
github.com/hashicorp/terraform-plugin-codegen-framework v0.4.1
github.com/hashicorp/terraform-plugin-codegen-openapi v0.3.0
github.com/hashicorp/terraform-plugin-docs v0.21.0
github.com/hashicorp/terraform-plugin-framework v1.15.0
github.com/hashicorp/terraform-plugin-framework-timeouts v0.5.0
github.com/hashicorp/terraform-plugin-docs v0.23.0
github.com/hashicorp/terraform-plugin-framework v1.16.1
github.com/hashicorp/terraform-plugin-framework-timeouts v0.6.0
github.com/hashicorp/terraform-plugin-framework-validators v0.18.0
github.com/hashicorp/terraform-plugin-go v0.28.0
github.com/hashicorp/terraform-plugin-go v0.29.0
github.com/hashicorp/terraform-plugin-log v0.9.0
github.com/hashicorp/terraform-plugin-testing v1.13.2
github.com/oapi-codegen/oapi-codegen/v2 v2.4.1
github.com/hashicorp/terraform-plugin-testing v1.13.3
github.com/oapi-codegen/oapi-codegen/v2 v2.5.0
github.com/oapi-codegen/runtime v1.1.2
)
@@ -32,14 +32,14 @@ require (
github.com/armon/go-radix v1.0.0 // indirect
github.com/bahlo/generic-list-go v0.2.0 // indirect
github.com/bgentry/speakeasy v0.1.0 // indirect
github.com/bmatcuk/doublestar/v4 v4.8.1 // indirect
github.com/bmatcuk/doublestar/v4 v4.9.1 // indirect
github.com/buger/jsonparser v1.1.1 // indirect
github.com/cloudflare/circl v1.6.1 // indirect
github.com/dprotaso/go-yit v0.0.0-20220510233725-9ba8df137936 // indirect
github.com/fatih/color v1.18.0 // indirect
github.com/frankban/quicktest v1.14.6 // indirect
github.com/fsnotify/fsnotify v1.5.4 // indirect
github.com/getkin/kin-openapi v0.131.0 // indirect
github.com/getkin/kin-openapi v0.132.0 // indirect
github.com/go-openapi/jsonpointer v0.21.0 // indirect
github.com/go-openapi/swag v0.23.0 // indirect
github.com/golang/protobuf v1.5.4 // indirect
@@ -52,18 +52,18 @@ require (
github.com/hashicorp/go-cty v1.5.0 // indirect
github.com/hashicorp/go-hclog v1.6.3 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/go-plugin v1.6.3 // indirect
github.com/hashicorp/go-plugin v1.7.0 // indirect
github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
github.com/hashicorp/go-uuid v1.0.3 // indirect
github.com/hashicorp/go-version v1.7.0 // indirect
github.com/hashicorp/hc-install v0.9.2 // indirect
github.com/hashicorp/hcl/v2 v2.23.0 // indirect
github.com/hashicorp/logutils v1.0.0 // indirect
github.com/hashicorp/terraform-exec v0.23.0 // indirect
github.com/hashicorp/terraform-json v0.25.0 // indirect
github.com/hashicorp/terraform-exec v0.23.1 // indirect
github.com/hashicorp/terraform-json v0.27.0 // indirect
github.com/hashicorp/terraform-plugin-codegen-spec v0.2.0 // indirect
github.com/hashicorp/terraform-plugin-sdk/v2 v2.37.0 // indirect
github.com/hashicorp/terraform-registry-address v0.3.0 // indirect
github.com/hashicorp/terraform-registry-address v0.4.0 // indirect
github.com/hashicorp/terraform-svchost v0.1.1 // indirect
github.com/hashicorp/yamux v0.1.2 // indirect
github.com/huandu/xstrings v1.4.0 // indirect
@@ -88,7 +88,8 @@ require (
github.com/posener/complete v1.2.3 // indirect
github.com/rivo/uniseg v0.2.0 // indirect
github.com/shopspring/decimal v1.3.1 // indirect
github.com/speakeasy-api/openapi-overlay v0.9.0 // indirect
github.com/speakeasy-api/jsonpath v0.6.0 // indirect
github.com/speakeasy-api/openapi-overlay v0.10.2 // indirect
github.com/spf13/cast v1.5.1 // indirect
github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect
github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect
@@ -100,20 +101,20 @@ require (
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
github.com/yuin/goldmark v1.7.7 // indirect
github.com/yuin/goldmark-meta v1.1.0 // indirect
github.com/zclconf/go-cty v1.16.3 // indirect
github.com/zclconf/go-cty v1.17.0 // indirect
go.abhg.dev/goldmark/frontmatter v0.2.0 // indirect
golang.org/x/crypto v0.40.0 // indirect
golang.org/x/crypto v0.41.0 // indirect
golang.org/x/exp v0.0.0-20240409090435-93d18d7e34b8 // indirect
golang.org/x/mod v0.25.0 // indirect
golang.org/x/net v0.42.0 // indirect
golang.org/x/sync v0.16.0 // indirect
golang.org/x/sys v0.34.0 // indirect
golang.org/x/text v0.27.0 // indirect
golang.org/x/tools v0.34.0 // indirect
golang.org/x/mod v0.27.0 // indirect
golang.org/x/net v0.43.0 // indirect
golang.org/x/sync v0.17.0 // indirect
golang.org/x/sys v0.35.0 // indirect
golang.org/x/text v0.29.0 // indirect
golang.org/x/tools v0.36.0 // indirect
google.golang.org/appengine v1.6.8 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250715232539-7130f93afb79 // indirect
google.golang.org/grpc v1.73.0 // indirect
google.golang.org/protobuf v1.36.6 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250728155136-f173205681a0 // indirect
google.golang.org/grpc v1.75.1 // indirect
google.golang.org/protobuf v1.36.9 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
+76 -70
View File
@@ -30,10 +30,10 @@ github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xW
github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w=
github.com/bmatcuk/doublestar/v4 v4.8.1 h1:54Bopc5c2cAvhLRAzqOGCYHYyhcDHsFF4wWIR5wKP38=
github.com/bmatcuk/doublestar/v4 v4.8.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
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/bmatcuk/doublestar/v4 v4.9.1 h1:X8jg9rRZmJd4yRy7ZeNDRnM+T3ZfHv15JiBJ/avrEXE=
github.com/bmatcuk/doublestar/v4 v4.9.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
github.com/bufbuild/protocompile v0.14.1 h1:iA73zAf/fyljNjQKwYzUHD6AD4R8KMasmwa/FBatYVw=
github.com/bufbuild/protocompile v0.14.1/go.mod h1:ppVdAIhbr2H8asPk6k4pY7t9zB1OU5DoEw9xY/FUi1c=
github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs=
github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
@@ -45,8 +45,9 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3
github.com/cyphar/filepath-securejoin v0.4.1 h1:JyxxyPEaktOD+GAnqIqTf9A8tHyAG22rowi7HkoSU1s=
github.com/cyphar/filepath-securejoin v0.4.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI=
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/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/deepmap/oapi-codegen v1.16.3 h1:GT9G86SbQtT1r8ZB+4Cybi9VGdu1P5ieNvNdEoCSbrA=
github.com/deepmap/oapi-codegen v1.16.3/go.mod h1:JD6ErqeX0nYnhdciLc61Konj3NBASREMlkHOgHn8WAM=
github.com/dprotaso/go-yit v0.0.0-20191028211022-135eb7262960/go.mod h1:9HQzr9D/0PGwMEbC3d5AB7oi67+h4TsQqItC1GVYG58=
@@ -63,16 +64,16 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI=
github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
github.com/getkin/kin-openapi v0.131.0 h1:NO2UeHnFKRYhZ8wg6Nyh5Cq7dHk4suQQr72a4pMrDxE=
github.com/getkin/kin-openapi v0.131.0/go.mod h1:3OlG51PCYNsPByuiMB0t4fjnNlIDnaEDsjiKUV8nL58=
github.com/getkin/kin-openapi v0.132.0 h1:3ISeLMsQzcb5v26yeJrBcdTCEQTag36ZjaGk7MIRUwk=
github.com/getkin/kin-openapi v0.132.0/go.mod h1:3OlG51PCYNsPByuiMB0t4fjnNlIDnaEDsjiKUV8nL58=
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.6.2 h1:6Q86EsPXMa7c3YZ3aLAQsMA0VlWmy43r6FHqa/UNbRM=
github.com/go-git/go-billy/v5 v5.6.2/go.mod h1:rcFC2rAsp/erv7CMz9GczHcuD0D32fWzH+MJAU+jaUU=
github.com/go-git/go-git/v5 v5.14.0 h1:/MD3lCrGjCen5WfEAzKg00MJJffKhC8gzS80ycmCi60=
github.com/go-git/go-git/v5 v5.14.0/go.mod h1:Z5Xhoia5PcWA3NF8vRLURn9E5FRhSl7dGj9ItW3Wk5k=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
@@ -124,8 +125,8 @@ github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVH
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.6.3 h1:xgHB+ZUSYeuJi96WtxEjzi23uh7YQpznjGh0U0UUrwg=
github.com/hashicorp/go-plugin v1.6.3/go.mod h1:MRobyh+Wc/nYy1V4KAXUiYfzxoYhs7V1mlH1Z7iY2h0=
github.com/hashicorp/go-plugin v1.7.0 h1:YghfQH/0QmPNc/AZMTFE3ac8fipZyZECHdDPshfk+mA=
github.com/hashicorp/go-plugin v1.7.0/go.mod h1:BExt6KEaIYx804z8k4gRzRLEvxKVb+kn0NMcihqOqb8=
github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU=
github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk=
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
@@ -139,34 +140,34 @@ github.com/hashicorp/hcl/v2 v2.23.0 h1:Fphj1/gCylPxHutVSEOf2fBOh1VE4AuLV7+kbJf3q
github.com/hashicorp/hcl/v2 v2.23.0/go.mod h1:62ZYHrXgPoX8xBnzl8QzbWq4dyDsDtfCRgIq1rbJEvA=
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.23.0 h1:MUiBM1s0CNlRFsCLJuM5wXZrzA3MnPYEsiXmzATMW/I=
github.com/hashicorp/terraform-exec v0.23.0/go.mod h1:mA+qnx1R8eePycfwKkCRk3Wy65mwInvlpAeOwmA7vlY=
github.com/hashicorp/terraform-json v0.25.0 h1:rmNqc/CIfcWawGiwXmRuiXJKEiJu1ntGoxseG1hLhoQ=
github.com/hashicorp/terraform-json v0.25.0/go.mod h1:sMKS8fiRDX4rVlR6EJUMudg1WcanxCMoWwTLkgZP/vc=
github.com/hashicorp/terraform-exec v0.23.1 h1:diK5NSSDXDKqHEOIQefBMu9ny+FhzwlwV0xgUTB7VTo=
github.com/hashicorp/terraform-exec v0.23.1/go.mod h1:e4ZEg9BJDRaSalGm2z8vvrPONt0XWG0/tXpmzYTf+dM=
github.com/hashicorp/terraform-json v0.27.0 h1:REIlFzMMkIyTbhq69NC30bYiUYLv7iVhwM8ObnLo0p8=
github.com/hashicorp/terraform-json v0.27.0/go.mod h1:GzPLJ1PLdUG5xL6xn1OXWIjteQRT2CNT9o/6A9mi9hE=
github.com/hashicorp/terraform-plugin-codegen-framework v0.4.1 h1:eaI/3dsu2T5QAXbA+7N+B+UBj20GdtYnsRuYypKh3S4=
github.com/hashicorp/terraform-plugin-codegen-framework v0.4.1/go.mod h1:kpYM23L7NtcfaQdWAN0QFkV/lU0w16qJ2ddAPCI4zAg=
github.com/hashicorp/terraform-plugin-codegen-openapi v0.3.0 h1:IKpc337XKk50QyQPSxLrHwdqSo1E2XqCMxFkWsZcTvc=
github.com/hashicorp/terraform-plugin-codegen-openapi v0.3.0/go.mod h1:tT6wl80h7nsMBw+1yZRgJXi+Ys85PUai11weDqysvp4=
github.com/hashicorp/terraform-plugin-codegen-spec v0.2.0 h1:91dQG1A/DxP6vRz9GiytDTrZTXDbhHPvmpYnAyWA/Vw=
github.com/hashicorp/terraform-plugin-codegen-spec v0.2.0/go.mod h1:fywrEKpordQypmAjz/HIfm2LuNVmyJ6KDe8XT9GdJxQ=
github.com/hashicorp/terraform-plugin-docs v0.21.0 h1:yoyA/Y719z9WdFJAhpUkI1jRbKP/nteVNBaI3hW7iQ8=
github.com/hashicorp/terraform-plugin-docs v0.21.0/go.mod h1:J4Wott1J2XBKZPp/NkQv7LMShJYOcrqhQ2myXBcu64s=
github.com/hashicorp/terraform-plugin-framework v1.15.0 h1:LQ2rsOfmDLxcn5EeIwdXFtr03FVsNktbbBci8cOKdb4=
github.com/hashicorp/terraform-plugin-framework v1.15.0/go.mod h1:hxrNI/GY32KPISpWqlCoTLM9JZsGH3CyYlir09bD/fI=
github.com/hashicorp/terraform-plugin-framework-timeouts v0.5.0 h1:I/N0g/eLZ1ZkLZXUQ0oRSXa8YG/EF0CEuQP1wXdrzKw=
github.com/hashicorp/terraform-plugin-framework-timeouts v0.5.0/go.mod h1:t339KhmxnaF4SzdpxmqW8HnQBHVGYazwtfxU0qCs4eE=
github.com/hashicorp/terraform-plugin-docs v0.23.0 h1:sipnfD4/9EJBg9zekym+s1H6qmLAKJHhGWBwvN9v/hE=
github.com/hashicorp/terraform-plugin-docs v0.23.0/go.mod h1:J4b5AtMRgJlDrwCQz+G4hKABgHY5m56PnsRmdAzBwW8=
github.com/hashicorp/terraform-plugin-framework v1.16.1 h1:1+zwFm3MEqd/0K3YBB2v9u9DtyYHyEuhVOfeIXbteWA=
github.com/hashicorp/terraform-plugin-framework v1.16.1/go.mod h1:0xFOxLy5lRzDTayc4dzK/FakIgBhNf/lC4499R9cV4Y=
github.com/hashicorp/terraform-plugin-framework-timeouts v0.6.0 h1:Vv16e7EW4nT9668IV0RhdpEmnLl0im7BZx6J+QMlUkg=
github.com/hashicorp/terraform-plugin-framework-timeouts v0.6.0/go.mod h1:rpHo9hZLn4vEkvNL5xsSdLRdaDZKSinuc0xL+BdOpVA=
github.com/hashicorp/terraform-plugin-framework-validators v0.18.0 h1:OQnlOt98ua//rCw+QhBbSqfW3QbwtVrcdWeQN5gI3Hw=
github.com/hashicorp/terraform-plugin-framework-validators v0.18.0/go.mod h1:lZvZvagw5hsJwuY7mAY6KUz45/U6fiDR0CzQAwWD0CA=
github.com/hashicorp/terraform-plugin-go v0.28.0 h1:zJmu2UDwhVN0J+J20RE5huiF3XXlTYVIleaevHZgKPA=
github.com/hashicorp/terraform-plugin-go v0.28.0/go.mod h1:FDa2Bb3uumkTGSkTFpWSOwWJDwA7bf3vdP3ltLDTH6o=
github.com/hashicorp/terraform-plugin-go v0.29.0 h1:1nXKl/nSpaYIUBU1IG/EsDOX0vv+9JxAltQyDMpq5mU=
github.com/hashicorp/terraform-plugin-go v0.29.0/go.mod h1:vYZbIyvxyy0FWSmDHChCqKvI40cFTDGSb3D8D70i9GM=
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.37.0 h1:NFPMacTrY/IdcIcnUB+7hsore1ZaRWU9cnB6jFoBnIM=
github.com/hashicorp/terraform-plugin-sdk/v2 v2.37.0/go.mod h1:QYmYnLfsosrxjCnGY1p9c7Zj6n9thnEE+7RObeYs3fA=
github.com/hashicorp/terraform-plugin-testing v1.13.2 h1:mSotG4Odl020vRjIenA3rggwo6Kg6XCKIwtRhYgp+/M=
github.com/hashicorp/terraform-plugin-testing v1.13.2/go.mod h1:WHQ9FDdiLoneey2/QHpGM/6SAYf4A7AZazVg7230pLE=
github.com/hashicorp/terraform-registry-address v0.3.0 h1:HMpK3nqaGFPS9VmgRXrJL/dzHNdheGVKk5k7VlFxzCo=
github.com/hashicorp/terraform-registry-address v0.3.0/go.mod h1:jRGCMiLaY9zii3GLC7hqpSnwhfnCN5yzvY0hh4iCGbM=
github.com/hashicorp/terraform-plugin-testing v1.13.3 h1:QLi/khB8Z0a5L54AfPrHukFpnwsGL8cwwswj4RZduCo=
github.com/hashicorp/terraform-plugin-testing v1.13.3/go.mod h1:WHQ9FDdiLoneey2/QHpGM/6SAYf4A7AZazVg7230pLE=
github.com/hashicorp/terraform-registry-address v0.4.0 h1:S1yCGomj30Sao4l5BMPjTGZmCNzuv7/GDTDX99E9gTk=
github.com/hashicorp/terraform-registry-address v0.4.0/go.mod h1:LRS1Ay0+mAiRkUyltGT+UHWkIqTFvigGn/LbMshfflE=
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.2 h1:XtB8kyFOyHXYVFnwT5C3+Bdo8gArse7j2AQ0DA0Uey8=
@@ -181,8 +182,8 @@ github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=
github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
github.com/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c=
github.com/jhump/protoreflect v1.15.1/go.mod h1:jD/2GMKKE6OqX8qTjhADU1e6DShO+gavG9e0Q693nKo=
github.com/jhump/protoreflect v1.17.0 h1:qOEr613fac2lOuTgWN4tPAtLL7fUSbuJL5X5XumQh94=
github.com/jhump/protoreflect v1.17.0/go.mod h1:h9+vUUL38jiBzck8ck+6G/aeMX8Z4QUY/NiJPwPNi+8=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d/go.mod h1:2PavIy+JPciBPrBUjwbNvtwB6RQlve+hkpll6QSNmOE=
@@ -224,8 +225,8 @@ github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwd
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
github.com/oapi-codegen/oapi-codegen/v2 v2.4.1 h1:ykgG34472DWey7TSjd8vIfNykXgjOgYJZoQbKfEeY/Q=
github.com/oapi-codegen/oapi-codegen/v2 v2.4.1/go.mod h1:N5+lY1tiTDV3V1BeHtOxeWXHoPVeApvsvjJqegfoaz8=
github.com/oapi-codegen/oapi-codegen/v2 v2.5.0 h1:iJvF8SdB/3/+eGOXEpsWkD8FQAHj6mqkb6Fnsoc8MFU=
github.com/oapi-codegen/oapi-codegen/v2 v2.5.0/go.mod h1:fwlMxUEMuQK5ih9aymrxKPQqNm2n8bdLk1ppjH+lr9w=
github.com/oapi-codegen/runtime v1.1.2 h1:P2+CubHq8fO4Q6fV1tqDBZHCwpVpvPg7oKiYzQgXIyI=
github.com/oapi-codegen/runtime v1.1.2/go.mod h1:SK9X900oXmPWilYR5/WKPzt3Kqxn/uS/+lbpREv+eCg=
github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 h1:G7ERwszslrBzRxj//JalHPu/3yz+De2J+4aLtSRlHiY=
@@ -254,15 +255,16 @@ github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0V
github.com/pjbgf/sha1cd v0.3.2 h1:a9wb0bp1oC2TGwStyn0Umc/IGKQnEgF0vVaZ8QF8eo4=
github.com/pjbgf/sha1cd v0.3.2/go.mod h1:zQWigSxVmsHEZow5qaLtPYxpcKMMQpa09ixqBxuCS6A=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
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/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/posener/complete v1.2.3 h1:NP0eAhjcjImqslEwo/1hq7gpajME0fTLTezBKDqfXqo=
github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s=
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
@@ -271,8 +273,10 @@ github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5g
github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
github.com/skeema/knownhosts v1.3.1 h1:X2osQ+RAjK76shCbvhHHHVl3ZlgDm8apHEHFqRjnBY8=
github.com/skeema/knownhosts v1.3.1/go.mod h1:r7KTdC8l4uxWRyK2TpQZ/1o5HaSzh06ePQNxPwTcfiY=
github.com/speakeasy-api/openapi-overlay v0.9.0 h1:Wrz6NO02cNlLzx1fB093lBlYxSI54VRhy1aSutx0PQg=
github.com/speakeasy-api/openapi-overlay v0.9.0/go.mod h1:f5FloQrHA7MsxYg9djzMD5h6dxrHjVVByWKh7an8TRc=
github.com/speakeasy-api/jsonpath v0.6.0 h1:IhtFOV9EbXplhyRqsVhHoBmmYjblIRh5D1/g8DHMXJ8=
github.com/speakeasy-api/jsonpath v0.6.0/go.mod h1:ymb2iSkyOycmzKwbEAYPJV/yi2rSmvBCLZJcyD+VVWw=
github.com/speakeasy-api/openapi-overlay v0.10.2 h1:VOdQ03eGKeiHnpb1boZCGm7x8Haj6gST0P3SGTX95GU=
github.com/speakeasy-api/openapi-overlay v0.10.2/go.mod h1:n0iOU7AqKpNFfEt6tq7qYITC4f0yzVVdFw0S7hukemg=
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=
@@ -283,8 +287,8 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
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.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
@@ -313,37 +317,37 @@ github.com/yuin/goldmark v1.7.7 h1:5m9rrB1sW3JUMToKFQfb+FGt1U7r57IHu5GrYrG2nqU=
github.com/yuin/goldmark v1.7.7/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
github.com/yuin/goldmark-meta v1.1.0 h1:pWw+JLHGZe8Rk0EGsMVssiNb/AaPMHfSRszZeUeiOUc=
github.com/yuin/goldmark-meta v1.1.0/go.mod h1:U4spWENafuA7Zyg+Lj5RqK/MF+ovMYtBvXi1lBb2VP0=
github.com/zclconf/go-cty v1.16.3 h1:osr++gw2T61A8KVYHoQiFbFd1Lh3JOCXc/jFLJXKTxk=
github.com/zclconf/go-cty v1.16.3/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE=
github.com/zclconf/go-cty v1.17.0 h1:seZvECve6XX4tmnvRzWtJNHdscMtYEx5R7bnnVyd/d0=
github.com/zclconf/go-cty v1.17.0/go.mod h1:wqFzcImaLTI6A5HfsRwB0nj5n0MRZFwmey8YoFPPs3U=
github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940 h1:4r45xpDWB6ZMSMNJFMOjqrGHynW3DIBuR2H9j0ug+Mo=
github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940/go.mod h1:CmBdvvj3nqzfzJ6nTCIwDTPZ56aVGvDrmztiO5g3qrM=
go.abhg.dev/goldmark/frontmatter v0.2.0 h1:P8kPG0YkL12+aYk2yU3xHv4tcXzeVnN+gU0tJ5JnxRw=
go.abhg.dev/goldmark/frontmatter v0.2.0/go.mod h1:XqrEkZuM57djk7zrlRUB02x8I5J0px76YjkOzhB4YlU=
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ=
go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y=
go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M=
go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE=
go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY=
go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg=
go.opentelemetry.io/otel/sdk/metric v1.35.0 h1:1RriWBmCKgkeHEhM7a2uMjMUfP7MsOF5JpUCaEqEI9o=
go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w=
go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs=
go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc=
go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ=
go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I=
go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE=
go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E=
go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI=
go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg=
go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFhbjxHHspCPc=
go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps=
go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4=
go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM=
golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY=
golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
golang.org/x/exp v0.0.0-20240409090435-93d18d7e34b8 h1:ESSUROHIBHg7USnszlcdmjBEwdMj9VUvU+OPk4yl2mc=
golang.org/x/exp v0.0.0-20240409090435-93d18d7e34b8/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI=
golang.org/x/mod v0.3.0/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.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w=
golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ=
golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
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=
@@ -354,14 +358,14 @@ golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
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.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs=
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
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-20201020160332-67f06af15bc9/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.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/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=
@@ -386,8 +390,8 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
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=
@@ -397,25 +401,27 @@ golang.org/x/text v0.3.6/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.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
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-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo=
golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg=
golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg=
golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
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=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
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/googleapis/rpc v0.0.0-20250715232539-7130f93afb79 h1:1ZwqphdOdWYXsUHgMpU/101nCtf/kSp9hOrcvFsnl10=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250715232539-7130f93afb79/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
google.golang.org/grpc v1.73.0 h1:VIWSmpI2MegBtTuFt5/JWy2oXxtjJ/e89Z70ImfD2ok=
google.golang.org/grpc v1.73.0/go.mod h1:50sbHOUqWoCQGI8V2HQLJM0B+LMlIUjNSZmow7EVBQc=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250728155136-f173205681a0 h1:MAKi5q709QWfnkkpNQ0M12hYJ1+e8qYVDyowc4U1XZM=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250728155136-f173205681a0/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
google.golang.org/grpc v1.75.1 h1:/ODCNEuf9VghjgO3rqLcfg8fiOP0nSluljWFlDxELLI=
google.golang.org/grpc v1.75.1/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
@@ -424,8 +430,8 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
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.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw=
google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+1 -1
View File
@@ -1,6 +1,6 @@
// Package binarylane provides primitives to interact with the openapi HTTP API.
//
// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.4.1 DO NOT EDIT.
// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.5.0 DO NOT EDIT.
package binarylane
import (
+66 -24
View File
@@ -1,6 +1,6 @@
// Package binarylane provides primitives to interact with the openapi HTTP API.
//
// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.4.1 DO NOT EDIT.
// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.5.0 DO NOT EDIT.
package binarylane
import (
@@ -1189,10 +1189,10 @@ type ConsoleResponse struct {
// CreateLoadBalancerRequest defines model for CreateLoadBalancerRequest.
type CreateLoadBalancerRequest struct {
// ForwardingRules The rules that control which traffic the load balancer will forward to servers in the pool. Leave null to accept a default "HTTP" only forwarding rule.
ForwardingRules *[]ForwardingRule `json:"forwarding_rules" tfsdk:"forwarding_rules"`
ForwardingRules *[]ForwardingRuleRequest `json:"forwarding_rules" tfsdk:"forwarding_rules"`
// HealthCheck The rules that determine which servers are considered 'healthy' and in the server pool for the load balancer. Leave this null to accept appropriate defaults based on the forwarding_rules.
HealthCheck *HealthCheck `json:"health_check"`
HealthCheck *HealthCheckRequest `json:"health_check"`
// Name The hostname of the load balancer.
Name string `json:"name"`
@@ -1603,14 +1603,50 @@ type ForwardingRule struct {
EntryProtocol LoadBalancerRuleProtocol `json:"entry_protocol" tfsdk:"entry_protocol"`
}
// ForwardingRuleRequest defines model for ForwardingRuleRequest.
type ForwardingRuleRequest struct {
// EntryProtocol The protocol that traffic must match for this load balancer to forward traffic according to this rule.
//
// | Value | Description |
// | ----- | ----------- |
// | http | The load balancer will forward HTTP traffic that matches this rule. |
// | https | The load balancer will forward HTTPS traffic that matches this rule. |
//
EntryProtocol LoadBalancerRuleProtocol `json:"entry_protocol" tfsdk:"entry_protocol"`
}
// ForwardingRulesRequest defines model for ForwardingRulesRequest.
type ForwardingRulesRequest struct {
// ForwardingRules The rules that control which traffic the load balancer will forward to servers in the pool.
ForwardingRules []ForwardingRule `json:"forwarding_rules"`
ForwardingRules []ForwardingRuleRequest `json:"forwarding_rules"`
}
// HealthCheck defines model for HealthCheck.
type HealthCheck struct {
// Path The path to the health check endpoint.
Path string `json:"path"`
// Protocol The protocol used for the health check.
//
// | Value | Description |
// | ----- | ----------- |
// | http | The health check will be performed via HTTP. |
// | https | The health check will be performed via HTTPS. |
// | both | The health check will be performed via both HTTP and HTTPS. Failing a health check on one protocol will remove the server from the pool of servers only for that protocol. |
//
Protocol HealthCheckProtocol `json:"protocol"`
}
// HealthCheckProtocol
// | Value | Description |
// | ----- | ----------- |
// | http | The health check will be performed via HTTP. |
// | https | The health check will be performed via HTTPS. |
// | both | The health check will be performed via both HTTP and HTTPS. Failing a health check on one protocol will remove the server from the pool of servers only for that protocol. |
type HealthCheckProtocol = string
// HealthCheckRequest defines model for HealthCheckRequest.
type HealthCheckRequest struct {
// Path Leave null to accept the default '/' path.
Path *string `json:"path"`
@@ -1625,14 +1661,6 @@ type HealthCheck struct {
Protocol *HealthCheckProtocol `json:"protocol"`
}
// HealthCheckProtocol
// | Value | Description |
// | ----- | ----------- |
// | http | The health check will be performed via HTTP. |
// | https | The health check will be performed via HTTPS. |
// | both | The health check will be performed via both HTTP and HTTPS. Failing a health check on one protocol will remove the server from the pool of servers only for that protocol. |
type HealthCheckProtocol = string
// Host defines model for Host.
type Host struct {
// DisplayName The name for this host. If this is a dedicated host this property will be empty.
@@ -1887,6 +1915,11 @@ type License struct {
// LicensedSoftware defines model for LicensedSoftware.
type LicensedSoftware struct {
// Incompatible Software that is incompatible with the server will be automatically removed at the next plan change.
// Servers may have incompatible software due to changes made by support. Software is not incompatible merely because it is disabled;
// disabled software may be retained by servers that already have it, incompatible software will be removed.
Incompatible bool `json:"incompatible"`
// LicenceCount The current licence count for the software.
LicenceCount int32 `json:"licence_count"`
@@ -1912,29 +1945,38 @@ type Links struct {
// LoadBalancer defines model for LoadBalancer.
type LoadBalancer struct {
// CreatedAt The date and time in ISO8601 format of the creation of the load balancer.
CreatedAt *time.Time `json:"created_at,omitempty"`
CreatedAt time.Time `json:"created_at"`
// ForwardingRules The rules that control which traffic the load balancer will forward to servers in the pool.
ForwardingRules *[]ForwardingRule `json:"forwarding_rules,omitempty"`
ForwardingRules []ForwardingRule `json:"forwarding_rules"`
// HealthCheck The rules that determine which servers are considered 'healthy' and in the server pool for the load balancer.
HealthCheck *HealthCheck `json:"health_check,omitempty" tfsdk:"health_check"`
HealthCheck HealthCheck `json:"health_check" tfsdk:"health_check"`
// Id The ID of the load balancer.
Id *int64 `json:"id,omitempty"`
Id int64 `json:"id"`
// Ip The IPv4 address of the load balancer.
Ip *string `json:"ip,omitempty"`
Ip string `json:"ip"`
// Name The hostname of the load balancer.
Name *string `json:"name,omitempty"`
Name string `json:"name"`
// Region The region the load balancer is located in. If this value is null the load balancer is an 'AnyCast' load balancer.
Region *Region `json:"region"`
// ServerIds The server IDs of the servers that are currently in the load balancer pool (regardless of their current 'health').
ServerIds *[]int64 `json:"server_ids,omitempty"`
Status *LoadBalancerStatus `json:"status,omitempty"`
ServerIds []int64 `json:"server_ids"`
// Status The current status of the load balancer.
//
// | Value | Description |
// | ----- | ----------- |
// | new | The load balancer is currently being built and is not ready to accept connections. |
// | active | The load balancer is available. |
// | errored | The load balancer is in an errored state. |
//
Status LoadBalancerStatus `json:"status"`
}
// LoadBalancerAvailabilityOption defines model for LoadBalancerAvailabilityOption.
@@ -1946,7 +1988,7 @@ type LoadBalancerAvailabilityOption struct {
PriceHourly *float64 `json:"price_hourly,omitempty"`
// PriceMonthly Monthly Price in AU$.
PriceMonthly *float64 `json:"price_monthly,omitempty"`
PriceMonthly float64 `json:"price_monthly"`
// Regions The slugs of regions where this load balancer option is available. If this is an Anycast load balancer option this will be null.
Regions *[]string `json:"regions"`
@@ -2279,7 +2321,7 @@ type Resize struct {
// ChangeImage This may be left null to keep the current base image for the server. If this is provided the server disks will be destroyed and the server will be rebuilt from the selected image.
ChangeImage *ChangeImage `json:"change_image"`
// ChangeLicenses This may be left null to keep the current licenses for the server. If this is provided any licenses that are not included will be removed.
// ChangeLicenses This may be left null to keep the current licenses for the server. If this is provided any licenses that are not included will be removed. Any licences that are invalid will be removed regardless, see the documentation for `servers/{server_id}/software` for more information.
ChangeLicenses *ChangeLicenses `json:"change_licenses"`
// Options If this is null and the server has no selected size options the defaults for the size will be used. If this is null and the server has currently selected size options those will be preserved. If this is provided any option fields that are not included will be removed from the existing server.
@@ -3048,10 +3090,10 @@ type UpdateDomainRecordRequest struct {
// UpdateLoadBalancerRequest defines model for UpdateLoadBalancerRequest.
type UpdateLoadBalancerRequest struct {
// ForwardingRules The rules that control which traffic the load balancer will forward to servers in the pool. Leave null to accept a default "HTTP" only forwarding rule.
ForwardingRules *[]ForwardingRule `json:"forwarding_rules"`
ForwardingRules *[]ForwardingRuleRequest `json:"forwarding_rules"`
// HealthCheck The rules that determine which servers are considered 'healthy' and in the server pool for the load balancer. Leave this null to accept appropriate defaults based on the forwarding_rules.
HealthCheck *HealthCheck `json:"health_check"`
HealthCheck *HealthCheckRequest `json:"health_check"`
// Name The hostname of the load balancer.
Name string `json:"name"`
@@ -7,6 +7,7 @@ import (
"terraform-provider-binarylane/internal/resources"
"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/types"
)
var (
@@ -22,8 +23,9 @@ type loadBalancerDataSource struct {
bc *BinarylaneClient
}
type loadBalancerDataSourceModel struct {
type loadBalancerDataModel struct {
resources.LoadBalancerModel
Ip types.String `tfsdk:"ip"`
}
func (d *loadBalancerDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
@@ -52,7 +54,7 @@ func (d *loadBalancerDataSource) Configure(
func (d *loadBalancerDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) {
ds, err := convertResourceSchemaToDataSourceSchema(
resources.LoadBalancerResourceSchema(ctx),
loadBalancerSchema(ctx),
AttributeConfig{
RequiredAttributes: &[]string{"id"},
},
@@ -63,10 +65,11 @@ func (d *loadBalancerDataSource) Schema(ctx context.Context, req datasource.Sche
}
resp.Schema = *ds
resp.Schema.Description = "Retrieve details about a BinaryLane Load Balancer."
resp.Schema.MarkdownDescription = resp.Schema.Description
}
func (d *loadBalancerDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
var data loadBalancerDataSourceModel
var data loadBalancerDataModel
// Read Terraform prior state data into the model
resp.Diagnostics.Append(req.Config.Get(ctx, &data)...)
@@ -93,7 +96,7 @@ func (d *loadBalancerDataSource) Read(ctx context.Context, req datasource.ReadRe
return
}
diags := setLoadBalancerModelState(ctx, &data.LoadBalancerModel, lbResp.JSON200.LoadBalancer)
diags := setLoadBalancerModelState(ctx, &data, lbResp.JSON200.LoadBalancer)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
+148 -90
View File
@@ -10,14 +10,17 @@ import (
"time"
"github.com/hashicorp/terraform-plugin-framework-timeouts/resource/timeouts"
"github.com/hashicorp/terraform-plugin-framework-validators/listvalidator"
"github.com/hashicorp/terraform-plugin-framework/attr"
"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/int64planmodifier"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/listdefault"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-log/tflog"
)
@@ -37,7 +40,7 @@ type loadBalancerResource struct {
}
type loadBalancerResourceModel struct {
resources.LoadBalancerModel
loadBalancerDataModel
Timeouts timeouts.Value `tfsdk:"timeouts"`
}
@@ -60,15 +63,15 @@ func (d *loadBalancerResource) Configure(_ context.Context, req resource.Configu
d.bc = &bc
}
func (r *loadBalancerResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
resp.Schema = resources.LoadBalancerResourceSchema(ctx)
resp.Schema.Description = "Provides a BinaryLane Load Balancer resource. This can be used to create, update, and delete load balancers."
resp.Schema.MarkdownDescription = resp.Schema.Description +
func loadBalancerSchema(ctx context.Context) schema.Schema {
s := resources.LoadBalancerResourceSchema(ctx)
s.Description = "Provides a BinaryLane Load Balancer resource. This can be used to create, update, and delete load balancers."
s.MarkdownDescription = s.Description +
" See [the docs](https://support.binarylane.com.au/support/solutions/articles/1000025661-load-balancer) for more information."
// Overrides
id := resp.Schema.Attributes["id"]
resp.Schema.Attributes["id"] = &schema.Int64Attribute{
id := s.Attributes["id"]
s.Attributes["id"] = schema.Int64Attribute{
Description: id.GetDescription(),
MarkdownDescription: id.GetMarkdownDescription(),
// read only
@@ -80,8 +83,8 @@ func (r *loadBalancerResource) Schema(ctx context.Context, req resource.SchemaRe
},
}
region := resp.Schema.Attributes["region"]
resp.Schema.Attributes["region"] = &schema.StringAttribute{
region := s.Attributes["region"]
s.Attributes["region"] = schema.StringAttribute{
Description: region.GetDescription(),
MarkdownDescription: region.GetMarkdownDescription(),
Optional: true,
@@ -91,9 +94,56 @@ func (r *loadBalancerResource) Schema(ctx context.Context, req resource.SchemaRe
},
}
forwardingRules := s.Attributes["forwarding_rules"].(schema.ListNestedAttribute)
s.Attributes["forwarding_rules"] = schema.ListNestedAttribute{
NestedObject: forwardingRules.NestedObject,
Description: forwardingRules.GetDescription(),
MarkdownDescription: forwardingRules.GetMarkdownDescription(),
Required: false,
Optional: true,
Computed: true,
Default: listdefault.StaticValue(types.ListValueMust(
types.ObjectType{
AttrTypes: resources.ForwardingRulesValue{}.AttributeTypes(ctx),
},
[]attr.Value{
types.ObjectValueMust(
map[string]attr.Type{
"entry_protocol": types.StringType,
},
map[string]attr.Value{
"entry_protocol": types.StringValue("http"),
},
),
},
)),
Validators: []validator.List{
listvalidator.SizeAtLeast(1),
},
}
// Additional attributes
s.Attributes["ip"] = schema.StringAttribute{
Description: "The IPv4 address of the load balancer.",
MarkdownDescription: "The IPv4 address of the load balancer.",
Required: false,
Optional: false,
Computed: true,
PlanModifiers: []planmodifier.String{
stringplanmodifier.UseStateForUnknown(),
},
}
return s
}
func (r *loadBalancerResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
resp.Schema = loadBalancerSchema(ctx)
resp.Schema.Attributes["timeouts"] =
timeouts.Attributes(ctx, timeouts.Opts{
Create: true,
Update: true,
})
}
@@ -107,9 +157,14 @@ func (r *loadBalancerResource) Create(ctx context.Context, req resource.CreateRe
return
}
timeout, diags := data.Timeouts.Create(ctx, 20*time.Minute)
resp.Diagnostics.Append(diags...)
ctx, cancel := context.WithTimeout(ctx, timeout)
defer cancel()
// Create API call logic
forwardingRules := []binarylane.ForwardingRule{}
diags := data.LoadBalancerModel.ForwardingRules.ElementsAs(ctx, &forwardingRules, false)
forwardingRules := []binarylane.ForwardingRuleRequest{}
diags = data.LoadBalancerModel.ForwardingRules.ElementsAs(ctx, &forwardingRules, false)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
@@ -129,7 +184,7 @@ func (r *loadBalancerResource) Create(ctx context.Context, req resource.CreateRe
}
if data.HealthCheck.Path.ValueStringPointer() != nil || data.HealthCheck.Protocol.ValueStringPointer() != nil {
body.HealthCheck = &binarylane.HealthCheck{
body.HealthCheck = &binarylane.HealthCheckRequest{
Path: data.HealthCheck.Path.ValueStringPointer(),
Protocol: data.HealthCheck.Protocol.ValueStringPointer(),
}
@@ -154,7 +209,7 @@ func (r *loadBalancerResource) Create(ctx context.Context, req resource.CreateRe
return
}
diags = setLoadBalancerModelState(ctx, &data.LoadBalancerModel, lbResp.JSON200.LoadBalancer)
diags = setLoadBalancerModelState(ctx, &data.loadBalancerDataModel, lbResp.JSON200.LoadBalancer)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
@@ -163,60 +218,20 @@ func (r *loadBalancerResource) Create(ctx context.Context, req resource.CreateRe
// Save data into Terraform state
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
// Wait for server to be ready
var createActionId int64
// Wait for load balancer to be ready
var actionId int64
for _, action := range *lbResp.JSON200.Links.Actions {
if *action.Rel == "create_load_balancer" {
createActionId = *action.Id
actionId = *action.Id
break
}
}
if createActionId == 0 {
resp.Diagnostics.AddError(
"Unable to wait for load balancer to be created, links.actions with rel=create_load_balancer missing from response",
fmt.Sprintf("Received %s creating new load balancer: name=%s. Details: %s", lbResp.Status(), data.Name.ValueString(), lbResp.Body))
err = r.waitForAction(ctx, actionId)
if err != nil {
resp.Diagnostics.AddError("Error waiting for load balancer to be created", err.Error())
return
}
createTimeout, diags := data.Timeouts.Create(ctx, 20*time.Minute)
resp.Diagnostics.Append(diags...)
ctx, cancel := context.WithTimeout(ctx, createTimeout)
defer cancel()
var lastReadyResp *binarylane.GetActionsActionIdResponse
retryLoop:
for {
select {
case <-ctx.Done():
if lastReadyResp == nil {
return
}
resp.Diagnostics.AddError(
"Timed out waiting for load balancer to be created",
fmt.Sprintf(
"Timed out waiting for load balancer %s to be created, last response was status=%s, body: %s",
data.Name.ValueString(),
lastReadyResp.Status(),
lastReadyResp.Body,
),
)
return
default:
readyResp, err := r.bc.client.GetActionsActionIdWithResponse(ctx, createActionId)
if err != nil {
resp.Diagnostics.AddError("Error waiting for load balancer to be created", err.Error())
return
}
if readyResp.StatusCode() == http.StatusOK && readyResp.JSON200.Action.CompletedAt != nil {
break retryLoop
}
lastReadyResp = readyResp
tflog.Debug(ctx, fmt.Sprintf("Waiting for load balancer to be created: name=%s, status=%s, details: %s", data.Name.ValueString(), readyResp.Status(), readyResp.Body))
}
time.Sleep(time.Second * 5)
}
}
func (r *loadBalancerResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
@@ -253,7 +268,7 @@ func (r *loadBalancerResource) Read(ctx context.Context, req resource.ReadReques
return
}
diags := setLoadBalancerModelState(ctx, &data.LoadBalancerModel, lbResp.JSON200.LoadBalancer)
diags := setLoadBalancerModelState(ctx, &data.loadBalancerDataModel, lbResp.JSON200.LoadBalancer)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
@@ -274,7 +289,7 @@ func (r *loadBalancerResource) Update(ctx context.Context, req resource.UpdateRe
}
// Update API call logic
forwardingRules := &[]binarylane.ForwardingRule{}
forwardingRules := &[]binarylane.ForwardingRuleRequest{}
diags := data.LoadBalancerModel.ForwardingRules.ElementsAs(ctx, forwardingRules, true)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
@@ -293,13 +308,18 @@ func (r *loadBalancerResource) Update(ctx context.Context, req resource.UpdateRe
body := binarylane.UpdateLoadBalancerRequest{
Name: data.Name.ValueString(),
ForwardingRules: forwardingRules,
HealthCheck: &binarylane.HealthCheck{
HealthCheck: &binarylane.HealthCheckRequest{
Path: data.HealthCheck.Path.ValueStringPointer(),
Protocol: data.HealthCheck.Protocol.ValueStringPointer(),
},
ServerIds: serverIds,
}
timeout, diags := data.Timeouts.Update(ctx, 20*time.Minute)
resp.Diagnostics.Append(diags...)
ctx, cancel := context.WithTimeout(ctx, timeout)
defer cancel()
lbResp, err := r.bc.client.PutLoadBalancersLoadBalancerIdWithResponse(ctx, data.Id.ValueInt64(), body)
if err != nil {
resp.Diagnostics.AddError(
@@ -317,12 +337,27 @@ func (r *loadBalancerResource) Update(ctx context.Context, req resource.UpdateRe
return
}
diags = setLoadBalancerModelState(ctx, &data.LoadBalancerModel, lbResp.JSON200.LoadBalancer)
diags = setLoadBalancerModelState(ctx, &data.loadBalancerDataModel, lbResp.JSON200.LoadBalancer)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}
// Wait for load balancer to be ready
var actionId int64
for _, action := range *lbResp.JSON200.Links.Actions {
if *action.Rel == "update_load_balancer" {
actionId = *action.Id
break
}
}
err = r.waitForAction(ctx, actionId)
if err != nil {
resp.Diagnostics.AddError("Error waiting for load balancer to be updated", err.Error())
return
}
// Save updated data into Terraform state
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
}
@@ -396,7 +431,7 @@ func (r *loadBalancerResource) ImportState(
loadBalancers := *lbResp.JSON200.LoadBalancers
for _, lb := range loadBalancers {
if *lb.Name == req.ID {
if lb.Name == req.ID {
loadBalancer = lb
nextPage = false
break
@@ -410,23 +445,16 @@ func (r *loadBalancerResource) ImportState(
page++
}
if loadBalancer.Id == nil {
resp.Diagnostics.AddError(
"Could not find load balancer by name",
fmt.Sprintf("Error finding load balancer: name=%s", req.ID),
)
return
}
diags := resp.State.SetAttribute(ctx, path.Root("id"), *loadBalancer.Id)
diags := resp.State.SetAttribute(ctx, path.Root("id"), loadBalancer.Id)
resp.Diagnostics.Append(diags...)
}
func setLoadBalancerModelState(ctx context.Context, data *resources.LoadBalancerModel, lb *binarylane.LoadBalancer) diag.Diagnostics {
func setLoadBalancerModelState(ctx context.Context, data *loadBalancerDataModel, lb *binarylane.LoadBalancer) diag.Diagnostics {
var diags, diag diag.Diagnostics
data.Id = types.Int64Value(*lb.Id)
data.Name = types.StringValue(*lb.Name)
data.Id = types.Int64Value(lb.Id)
data.Name = types.StringValue(lb.Name)
data.Ip = types.StringValue(lb.Ip)
if lb.Region == nil {
data.Region = types.StringNull()
@@ -434,20 +462,16 @@ func setLoadBalancerModelState(ctx context.Context, data *resources.LoadBalancer
data.Region = types.StringValue(*lb.Region.Slug)
}
data.ServerIds, diags = types.ListValueFrom(ctx, types.Int64Type, lb.ServerIds)
data.ServerIds, diags = types.SetValueFrom(ctx, types.Int64Type, lb.ServerIds)
if lb.HealthCheck == nil {
data.HealthCheck = resources.NewHealthCheckValueNull()
} else {
data.HealthCheck, diag = resources.NewHealthCheckValue(
resources.HealthCheckValue{}.AttributeTypes(ctx),
map[string]attr.Value{
"path": types.StringValue(*lb.HealthCheck.Path),
"protocol": types.StringValue(*lb.HealthCheck.Protocol),
},
)
diags.Append(diag...)
}
data.HealthCheck, diag = resources.NewHealthCheckValue(
resources.HealthCheckValue{}.AttributeTypes(ctx),
map[string]attr.Value{
"path": types.StringValue(lb.HealthCheck.Path),
"protocol": types.StringValue(lb.HealthCheck.Protocol),
},
)
diags.Append(diag...)
data.ForwardingRules, diag = types.ListValueFrom(ctx,
types.ObjectType{AttrTypes: resources.ForwardingRulesValue{}.AttributeTypes(ctx)},
@@ -457,3 +481,37 @@ func setLoadBalancerModelState(ctx context.Context, data *resources.LoadBalancer
return diags
}
func (r *loadBalancerResource) waitForAction(ctx context.Context, actionId int64) error {
var lastReadyResp *binarylane.GetActionsActionIdResponse
for {
select {
case <-ctx.Done():
if lastReadyResp == nil {
return fmt.Errorf("timed out waiting for action: action_id=%d", actionId)
} else {
return fmt.Errorf("timed out waiting for action: action_id=%d, last response was status=%s, body: %s",
actionId, lastReadyResp.Status(), lastReadyResp.Body)
}
default:
readyResp, err := r.bc.client.GetActionsActionIdWithResponse(ctx, actionId)
if err != nil {
return fmt.Errorf("unexpected error waiting for action: action_id=%d, error: %w", actionId, err)
}
if readyResp.StatusCode() == http.StatusOK && *readyResp.JSON200.Action.Status == binarylane.Errored {
return fmt.Errorf("action failed with error: action_id=%d, error: %s", actionId, readyResp.Body)
}
if readyResp.StatusCode() == http.StatusOK && readyResp.JSON200.Action.CompletedAt != nil {
return nil
}
lastReadyResp = readyResp
tflog.Debug(ctx,
fmt.Sprintf("waiting for action for action_id=%d: last response was status=%s, details: %s",
actionId, readyResp.Status(), readyResp.Body,
),
)
}
time.Sleep(time.Second * 5)
}
}
+139 -10
View File
@@ -4,12 +4,15 @@ import (
"context"
"fmt"
"log"
"maps"
"net/http"
"slices"
"strings"
"terraform-provider-binarylane/internal/binarylane"
"testing"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/terraform"
)
func TestLoadBalancerResource(t *testing.T) {
@@ -35,7 +38,7 @@ resource "binarylane_server" "test" {
resource "binarylane_load_balancer" "test" {
name = "tf-test-lb"
server_ids = [binarylane_server.test.0.id, binarylane_server.test.1.id]
forwarding_rules = [{ entry_protocol = "http" }]
# initially, skip defining forwarding_rules, health_check, to test default values
}
data "binarylane_load_balancer" "test" {
@@ -50,20 +53,26 @@ data "binarylane_load_balancer" "test" {
resource.TestCheckResourceAttr("binarylane_load_balancer.test", "name", "tf-test-lb"),
resource.TestCheckNoResourceAttr("binarylane_load_balancer.test", "region"),
resource.TestCheckResourceAttr("binarylane_load_balancer.test", "server_ids.#", "2"),
resource.TestCheckResourceAttrPair("binarylane_load_balancer.test", "server_ids.0", "binarylane_server.test.0", "id"),
resource.TestCheckResourceAttrPair("binarylane_load_balancer.test", "server_ids.1", "binarylane_server.test.1", "id"),
testCheckIfResourceAttrContainsAttr("binarylane_load_balancer.test", "server_ids", "binarylane_server.test.0", "id"),
testCheckIfResourceAttrContainsAttr("binarylane_load_balancer.test", "server_ids", "binarylane_server.test.1", "id"),
resource.TestCheckResourceAttr("binarylane_load_balancer.test", "forwarding_rules.#", "1"),
resource.TestCheckResourceAttr("binarylane_load_balancer.test", "forwarding_rules.0.entry_protocol", "http"),
resource.TestCheckResourceAttr("binarylane_load_balancer.test", "health_check.path", "/"),
resource.TestCheckResourceAttr("binarylane_load_balancer.test", "health_check.protocol", "http"),
resource.TestCheckResourceAttrSet("binarylane_load_balancer.test", "ip"),
// Verify data source values
resource.TestCheckResourceAttrPair("data.binarylane_load_balancer.test", "id", "binarylane_load_balancer.test", "id"),
resource.TestCheckResourceAttr("data.binarylane_load_balancer.test", "name", "tf-test-lb"),
resource.TestCheckNoResourceAttr("data.binarylane_load_balancer.test", "region"),
resource.TestCheckResourceAttr("data.binarylane_load_balancer.test", "server_ids.#", "2"),
resource.TestCheckResourceAttrPair("data.binarylane_load_balancer.test", "server_ids.0", "binarylane_server.test.0", "id"),
resource.TestCheckResourceAttrPair("data.binarylane_load_balancer.test", "server_ids.1", "binarylane_server.test.1", "id"),
testCheckIfResourceAttrContainsAttr("data.binarylane_load_balancer.test", "server_ids", "binarylane_server.test.0", "id"),
testCheckIfResourceAttrContainsAttr("data.binarylane_load_balancer.test", "server_ids", "binarylane_server.test.1", "id"),
resource.TestCheckResourceAttr("data.binarylane_load_balancer.test", "forwarding_rules.#", "1"),
resource.TestCheckResourceAttr("data.binarylane_load_balancer.test", "forwarding_rules.0.entry_protocol", "http"),
resource.TestCheckResourceAttr("data.binarylane_load_balancer.test", "health_check.path", "/"),
resource.TestCheckResourceAttr("data.binarylane_load_balancer.test", "health_check.protocol", "http"),
resource.TestCheckResourceAttrSet("data.binarylane_load_balancer.test", "ip"),
),
},
// Test import by ID
@@ -79,6 +88,64 @@ data "binarylane_load_balancer" "test" {
ImportStateId: "tf-test-lb",
ImportStateVerify: true,
},
{
Taint: []string{"binarylane_server.test[0]"},
Config: providerConfig + `
resource "binarylane_server" "test" {
count = 2
name = "tf-test-lb-server-${count.index}"
region = "per"
image = "debian-12"
size = "std-min"
password = "` + password + `"
public_ipv4_count = 1
}
resource "binarylane_load_balancer" "test" {
name = "tf-test-lb"
server_ids = [binarylane_server.test.0.id, binarylane_server.test.1.id]
# updated
forwarding_rules = [{ entry_protocol = "https" }]
health_check = {
path = "/test-health"
protocol = "https"
}
}
data "binarylane_load_balancer" "test" {
depends_on = [binarylane_load_balancer.test]
id = binarylane_load_balancer.test.id
}
`,
Check: resource.ComposeAggregateTestCheckFunc(
// Verify resource values
resource.TestCheckResourceAttrSet("binarylane_load_balancer.test", "id"),
resource.TestCheckResourceAttr("binarylane_load_balancer.test", "name", "tf-test-lb"),
resource.TestCheckNoResourceAttr("binarylane_load_balancer.test", "region"),
resource.TestCheckResourceAttr("binarylane_load_balancer.test", "server_ids.#", "2"),
testCheckIfResourceAttrContainsAttr("binarylane_load_balancer.test", "server_ids", "binarylane_server.test.0", "id"),
testCheckIfResourceAttrContainsAttr("binarylane_load_balancer.test", "server_ids", "binarylane_server.test.1", "id"),
resource.TestCheckResourceAttr("binarylane_load_balancer.test", "forwarding_rules.#", "1"),
resource.TestCheckResourceAttr("binarylane_load_balancer.test", "forwarding_rules.0.entry_protocol", "https"),
resource.TestCheckResourceAttr("binarylane_load_balancer.test", "health_check.path", "/test-health"),
resource.TestCheckResourceAttr("binarylane_load_balancer.test", "health_check.protocol", "https"),
resource.TestCheckResourceAttrSet("binarylane_load_balancer.test", "ip"),
// Verify data source values
resource.TestCheckResourceAttrPair("data.binarylane_load_balancer.test", "id", "binarylane_load_balancer.test", "id"),
resource.TestCheckResourceAttr("data.binarylane_load_balancer.test", "name", "tf-test-lb"),
resource.TestCheckNoResourceAttr("data.binarylane_load_balancer.test", "region"),
resource.TestCheckResourceAttr("data.binarylane_load_balancer.test", "server_ids.#", "2"),
testCheckIfResourceAttrContainsAttr("data.binarylane_load_balancer.test", "server_ids", "binarylane_server.test.0", "id"),
testCheckIfResourceAttrContainsAttr("data.binarylane_load_balancer.test", "server_ids", "binarylane_server.test.1", "id"),
resource.TestCheckResourceAttr("data.binarylane_load_balancer.test", "forwarding_rules.#", "1"),
resource.TestCheckResourceAttr("data.binarylane_load_balancer.test", "forwarding_rules.0.entry_protocol", "https"),
resource.TestCheckResourceAttr("data.binarylane_load_balancer.test", "health_check.path", "/test-health"),
resource.TestCheckResourceAttr("data.binarylane_load_balancer.test", "health_check.protocol", "https"),
resource.TestCheckResourceAttrSet("data.binarylane_load_balancer.test", "ip"),
),
},
},
})
}
@@ -117,15 +184,15 @@ func init() {
loadBalancers := *listResp.JSON200.LoadBalancers
for _, lb := range loadBalancers {
if strings.HasPrefix(*lb.Name, "tf-test-") {
deleteResp, err := client.DeleteLoadBalancersLoadBalancerIdWithResponse(ctx, *lb.Id)
if strings.HasPrefix(lb.Name, "tf-test-") {
deleteResp, err := client.DeleteLoadBalancersLoadBalancerIdWithResponse(ctx, lb.Id)
if err != nil {
return fmt.Errorf("Error deleting load balancer %d for test sweep: %w", *lb.Id, err)
return fmt.Errorf("Error deleting load balancer %d for test sweep: %w", lb.Id, err)
}
if deleteResp.StatusCode() != http.StatusNoContent {
return fmt.Errorf("Unexpected status %d deleting load balancer %d in test sweep: %s", deleteResp.StatusCode(), *lb.Id, deleteResp.Body)
return fmt.Errorf("Unexpected status %d deleting load balancer %d in test sweep: %s", deleteResp.StatusCode(), lb.Id, deleteResp.Body)
}
log.Println("Deleted load balancer during test sweep:", *lb.Id)
log.Println("Deleted load balancer during test sweep:", lb.Id)
}
}
if listResp.JSON200.Links == nil || listResp.JSON200.Links.Pages == nil || listResp.JSON200.Links.Pages.Next == nil {
@@ -139,3 +206,65 @@ func init() {
},
})
}
func primaryInstanceState(s *terraform.State, name string) (*terraform.InstanceState, error) {
ms := s.RootModule()
rs, ok := ms.Resources[name]
if !ok {
return nil, fmt.Errorf("Not found: %s in %s, resources: %v", name, ms.Path, slices.Collect(maps.Keys(ms.Resources)))
}
is := rs.Primary
if is == nil {
return nil, fmt.Errorf("No primary instance: %s in %s", name, ms.Path)
}
return is, nil
}
func testCheckIfResourceAttrContainsAttr(collectionKey, collectionPath, otherResourceKey, otherAttrPath string) resource.TestCheckFunc {
return func(s *terraform.State) error {
collectionState, err := primaryInstanceState(s, collectionKey)
if err != nil {
return err
}
elementState, err := primaryInstanceState(s, otherResourceKey)
if err != nil {
return err
}
if collectionKey == otherResourceKey && collectionPath == otherAttrPath {
return fmt.Errorf(
"comparing self: resource %s attribute %s",
collectionKey,
collectionPath,
)
}
vElement, okElement := elementState.Attributes[otherAttrPath]
if !okElement {
return fmt.Errorf("%s: Attribute %q not set, cannot be contained in %q from %s", otherResourceKey, otherAttrPath, collectionPath, collectionKey)
}
vCollection, okCollection := collectionState.Attributes[collectionPath+".#"]
if !okCollection {
return fmt.Errorf("%s: Attribute %q not a collection, cannot contain %q from %s", collectionKey, collectionPath, otherAttrPath, otherResourceKey)
}
for attrKey, attrValue := range collectionState.Attributes {
if strings.HasPrefix(attrKey, collectionPath+".") &&
!(strings.HasSuffix(attrKey, ".%")) &&
!strings.HasSuffix(attrKey, ".#") &&
attrValue == vElement {
return nil
}
}
return fmt.Errorf(
"%s: Attribute '%s' expected to contain %#v, got %#v",
collectionKey,
collectionPath,
vElement,
vCollection)
}
}
+30
View File
@@ -31,6 +31,8 @@ type serverDataModel struct {
resources.ServerModel
PublicIpv4Addresses types.List `tfsdk:"public_ipv4_addresses"`
PrivateIPv4Addresses types.List `tfsdk:"private_ipv4_addresses"`
PublicIpv6Addresses types.List `tfsdk:"public_ipv6_addresses"`
PrivateIpv6Addresses types.List `tfsdk:"private_ipv6_addresses"`
Permalink types.String `tfsdk:"permalink"`
Memory types.Int32 `tfsdk:"memory"`
Disk types.Int32 `tfsdk:"disk"`
@@ -109,6 +111,7 @@ func (d *serverDataSource) Read(ctx context.Context, req datasource.ReadRequest,
data.Region = types.StringValue(*serverResp.JSON200.Server.Region.Slug)
data.Size = types.StringValue(*serverResp.JSON200.Server.Size.Slug)
data.Backups = types.BoolValue(serverResp.JSON200.Server.NextBackupWindow != nil)
data.Ipv6 = types.BoolValue(len(serverResp.JSON200.Server.Networks.V6) > 0)
data.PortBlocking = types.BoolValue(serverResp.JSON200.Server.Networks.PortBlocking)
data.VpcId = types.Int64PointerValue(serverResp.JSON200.Server.VpcId)
data.Permalink = types.StringValue(*serverResp.JSON200.Server.Permalink)
@@ -162,6 +165,33 @@ func (d *serverDataSource) Read(ctx context.Context, req datasource.ReadRequest,
data.PrivateIPv4Addresses = tfPrivateIpv4Addresses
}
publicIpv6Addresses := []string{}
privateIpv6Addresses := []string{}
for _, v6address := range serverResp.JSON200.Server.Networks.V6 {
if v6address.Type == "public" {
publicIpv6Addresses = append(publicIpv6Addresses, v6address.IpAddress)
} else {
privateIpv6Addresses = append(privateIpv6Addresses, v6address.IpAddress)
}
}
tfPublicIpv6Addresses, diag := types.ListValueFrom(ctx, types.StringType, publicIpv6Addresses)
diags.Append(diag...)
if diag.HasError() {
data.PublicIpv6Addresses = types.ListUnknown(data.PublicIpv6Addresses.ElementType(ctx))
} else {
data.PublicIpv6Addresses = tfPublicIpv6Addresses
}
tfPrivateIpv6Addresses, diag := types.ListValueFrom(ctx, types.StringType, privateIpv6Addresses)
diags.Append(diag...)
if diag.HasError() {
data.PrivateIpv6Addresses = types.ListUnknown(data.PrivateIpv6Addresses.ElementType(ctx))
} else {
data.PrivateIpv6Addresses = tfPrivateIpv6Addresses
}
// Get user data script
userDataResp, err := d.bc.client.GetServersServerIdUserDataWithResponse(ctx, data.Id.ValueInt64())
if err != nil {
@@ -63,7 +63,7 @@ func (r *serverFirewallRulesResource) Schema(ctx context.Context, req resource.S
// Overrides
serverId := resp.Schema.Attributes["server_id"]
resp.Schema.Attributes["server_id"] = &schema.Int64Attribute{
resp.Schema.Attributes["server_id"] = schema.Int64Attribute{
Description: serverId.GetDescription(),
MarkdownDescription: serverId.GetMarkdownDescription(),
Required: true, // Server ID is required to define the firewall rules
@@ -251,7 +251,7 @@ func GetFirewallRulesState(ctx context.Context, firewallRules *[]binarylane.Adva
firewallRulesValue := resources.FirewallRulesValue{}
var firewallRulesValues []resources.FirewallRulesValue
if *firewallRules == nil || len(*firewallRules) == 0 {
if len(*firewallRules) == 0 {
firewallRulesValues = []resources.FirewallRulesValue{}
} else {
for _, rule := range *firewallRules {
+129 -18
View File
@@ -87,7 +87,7 @@ func serverSchema(ctx context.Context) schema.Schema {
// Overrides
id := s.Attributes["id"]
s.Attributes["id"] = &schema.Int64Attribute{
s.Attributes["id"] = schema.Int64Attribute{
Description: id.GetDescription(),
MarkdownDescription: id.GetMarkdownDescription(),
// read only
@@ -101,7 +101,7 @@ func serverSchema(ctx context.Context) schema.Schema {
imageDescription := "The slug of the selected operating system, such as `debian-12`. You can fetch a full list of images from the BinaryLane API."
image := s.Attributes["image"]
s.Attributes["image"] = &schema.StringAttribute{
s.Attributes["image"] = schema.StringAttribute{
Description: imageDescription,
MarkdownDescription: imageDescription,
Required: image.IsRequired(),
@@ -113,7 +113,7 @@ func serverSchema(ctx context.Context) schema.Schema {
}
backupsDescription := "If `true` this will enable two daily backups for the server. By default, backups are disabled."
s.Attributes["backups"] = &schema.BoolAttribute{
s.Attributes["backups"] = schema.BoolAttribute{
Description: backupsDescription,
MarkdownDescription: backupsDescription,
Optional: true,
@@ -122,7 +122,7 @@ func serverSchema(ctx context.Context) schema.Schema {
}
user_data := s.Attributes["user_data"]
s.Attributes["user_data"] = &schema.StringAttribute{
s.Attributes["user_data"] = schema.StringAttribute{
Description: user_data.GetDescription(),
MarkdownDescription: user_data.GetMarkdownDescription(),
Optional: true, // Optional as not all servers have an initialization script
@@ -130,7 +130,7 @@ func serverSchema(ctx context.Context) schema.Schema {
}
vpcId := s.Attributes["vpc_id"]
s.Attributes["vpc_id"] = &schema.Int64Attribute{
s.Attributes["vpc_id"] = schema.Int64Attribute{
Description: vpcId.GetDescription(),
MarkdownDescription: vpcId.GetMarkdownDescription(),
Optional: vpcId.IsOptional(),
@@ -138,7 +138,7 @@ func serverSchema(ctx context.Context) schema.Schema {
}
portBlocking := s.Attributes["port_blocking"]
s.Attributes["port_blocking"] = &schema.BoolAttribute{
s.Attributes["port_blocking"] = schema.BoolAttribute{
Description: portBlocking.GetDescription(),
MarkdownDescription: portBlocking.GetMarkdownDescription(),
Optional: portBlocking.IsOptional(),
@@ -147,7 +147,7 @@ func serverSchema(ctx context.Context) schema.Schema {
}
region := s.Attributes["region"].(schema.StringAttribute)
s.Attributes["region"] = &schema.StringAttribute{
s.Attributes["region"] = schema.StringAttribute{
Description: region.GetDescription(),
MarkdownDescription: region.GetMarkdownDescription(),
Optional: region.IsOptional(),
@@ -160,7 +160,7 @@ func serverSchema(ctx context.Context) schema.Schema {
}
sshKeys := s.Attributes["ssh_keys"]
s.Attributes["ssh_keys"] = &schema.ListAttribute{
s.Attributes["ssh_keys"] = schema.ListAttribute{
ElementType: types.Int64Type,
Description: sshKeys.GetMarkdownDescription(),
MarkdownDescription: sshKeys.GetDescription(),
@@ -174,7 +174,7 @@ func serverSchema(ctx context.Context) schema.Schema {
userDataDescription := "A script or cloud-config YAML file to configure the server. Can only be specified if the OS image supports UserData (i.e. not Windows)." +
" See more: https://cloudinit.readthedocs.io/en/latest/explanation/format.html#user-data-script"
userData := s.Attributes["user_data"]
s.Attributes["user_data"] = &schema.StringAttribute{
s.Attributes["user_data"] = schema.StringAttribute{
Description: userDataDescription,
MarkdownDescription: userDataDescription,
Required: userData.IsRequired(),
@@ -190,7 +190,7 @@ func serverSchema(ctx context.Context) schema.Schema {
"If this is provided the specified or default remote user's account password will be set to this value. " +
"Only valid if the server supports password change actions. If omitted and the server supports password " +
"change actions a random password will be generated and emailed to the account email address."
s.Attributes["password"] = &schema.StringAttribute{
s.Attributes["password"] = schema.StringAttribute{
Description: pwDescription,
MarkdownDescription: pwDescription,
Optional: true, // Password optional, if not set will be emailed to user
@@ -199,7 +199,7 @@ func serverSchema(ctx context.Context) schema.Schema {
}
publicIpv4CountDescription := "The number of public IPv4 addresses to assign to the server."
s.Attributes["public_ipv4_count"] = &schema.Int32Attribute{
s.Attributes["public_ipv4_count"] = schema.Int32Attribute{
Description: publicIpv4CountDescription,
MarkdownDescription: publicIpv4CountDescription,
Required: true,
@@ -212,7 +212,7 @@ func serverSchema(ctx context.Context) schema.Schema {
}
publicIpv4AddressesDescription := "The public IPv4 addresses assigned to the server."
s.Attributes["public_ipv4_addresses"] = &schema.ListAttribute{
s.Attributes["public_ipv4_addresses"] = schema.ListAttribute{
Description: publicIpv4AddressesDescription,
MarkdownDescription: publicIpv4AddressesDescription,
ElementType: types.StringType,
@@ -229,7 +229,7 @@ func serverSchema(ctx context.Context) schema.Schema {
"to incorrect network configuration. When `source_and_destination_check` is `false`, your Cloud Server will be able " +
"to send and receive packets addressed to any server. This is typically used when you want to use " +
"your Cloud Server as a VPN endpoint, a NAT server to provide internet access, or IP forwarding."
s.Attributes["source_and_destination_check"] = &schema.BoolAttribute{
s.Attributes["source_and_destination_check"] = schema.BoolAttribute{
Description: sourceDestCheckDescription,
MarkdownDescription: sourceDestCheckDescription,
Optional: true,
@@ -243,7 +243,7 @@ func serverSchema(ctx context.Context) schema.Schema {
}
privateIpv4AddressesDescription := "The private IPv4 addresses assigned to the server."
s.Attributes["private_ipv4_addresses"] = &schema.ListAttribute{
s.Attributes["private_ipv4_addresses"] = schema.ListAttribute{
Description: privateIpv4AddressesDescription,
MarkdownDescription: privateIpv4AddressesDescription,
ElementType: types.StringType,
@@ -256,7 +256,41 @@ func serverSchema(ctx context.Context) schema.Schema {
},
}
s.Attributes["permalink"] = &schema.StringAttribute{
ipv6Description := "If `true` this will add a public and private IPv6 address to the server. By default, IPv6 is disabled."
s.Attributes["ipv6"] = schema.BoolAttribute{
Description: ipv6Description,
MarkdownDescription: ipv6Description,
Optional: true,
Computed: true,
Default: booldefault.StaticBool(false), // Add default to ipv6
}
publicIpv6AddressesDescription := "The public IPv6 addresses assigned to the server."
s.Attributes["public_ipv6_addresses"] = schema.ListAttribute{
Description: publicIpv6AddressesDescription,
MarkdownDescription: publicIpv6AddressesDescription,
ElementType: types.StringType,
// read only
Optional: false,
Required: false,
Computed: true,
}
privateIpv6AddressesDescription := "The private IPv6 addresses assigned to the server."
s.Attributes["private_ipv6_addresses"] = schema.ListAttribute{
Description: privateIpv6AddressesDescription,
MarkdownDescription: privateIpv6AddressesDescription,
ElementType: types.StringType,
// read only
Optional: false,
Required: false,
Computed: true,
PlanModifiers: []planmodifier.List{
listplanmodifier.UseStateForUnknown(),
},
}
s.Attributes["permalink"] = schema.StringAttribute{
Description: "A randomly generated two-word identifier assigned to servers in regions that support this feature",
MarkdownDescription: "A randomly generated two-word identifier assigned to servers in regions that support this feature",
// read only
@@ -271,7 +305,7 @@ func serverSchema(ctx context.Context) schema.Schema {
pwChangeDescription := "If this is true then the `password` attribute can be changed with Terraform. " +
"If this is false then the `password` attribute can only be replaced with a null/empty value, which will clear " +
"the root/administrator password allowing the password to be changed via the web console."
s.Attributes["password_change_supported"] = &schema.BoolAttribute{
s.Attributes["password_change_supported"] = schema.BoolAttribute{
Description: pwChangeDescription,
MarkdownDescription: pwChangeDescription,
// read only
@@ -293,7 +327,7 @@ func serverSchema(ctx context.Context) schema.Schema {
- \> 16384 MB must be a multiple of 2048
- \> 24576 MB must be a multiple of 4096`
s.Attributes["memory"] = &schema.Int32Attribute{
s.Attributes["memory"] = schema.Int32Attribute{
Description: memoryDescription + memoryValidValues,
MarkdownDescription: memoryDescription + memoryValidValuesMarkdown,
Optional: true,
@@ -316,7 +350,7 @@ func serverSchema(ctx context.Context) schema.Schema {
- \> 60 GB must be a multiple of 10
- \> 200 GB must be a multiple of 100`
s.Attributes["disk"] = &schema.Int32Attribute{
s.Attributes["disk"] = schema.Int32Attribute{
Description: diskDescription + diskValidValues,
MarkdownDescription: diskDescription + diskValidValuesMarkdown,
Optional: true,
@@ -414,6 +448,16 @@ func (r *serverResource) ModifyPlan(ctx context.Context, req resource.ModifyPlan
)
}
if !plan.Ipv6.Equal(state.Ipv6) {
if plan.Ipv6.ValueBool() {
plan.PublicIpv6Addresses = types.ListUnknown(state.PublicIpv6Addresses.ElementType(ctx))
plan.PrivateIpv6Addresses = types.ListUnknown(state.PrivateIpv6Addresses.ElementType(ctx))
} else {
plan.PublicIpv6Addresses = types.ListNull(state.PublicIpv6Addresses.ElementType(ctx))
plan.PrivateIpv6Addresses = types.ListNull(state.PrivateIpv6Addresses.ElementType(ctx))
}
}
// Use state for unknown disk/memory values, as long as server size is the same
if (plan.Memory.IsNull() || plan.Memory.IsUnknown()) && plan.Size.Equal(state.Size) {
plan.Memory = state.Memory
@@ -527,6 +571,7 @@ func (r *serverResource) Create(ctx context.Context, req resource.CreateRequest,
Ipv4Addresses: data.PublicIpv4Count.ValueInt32Pointer(),
},
Backups: data.Backups.ValueBoolPointer(),
Ipv6: data.Ipv6.ValueBoolPointer(),
}
if !data.Memory.IsNull() && !data.Memory.IsUnknown() {
@@ -584,6 +629,7 @@ func (r *serverResource) Create(ctx context.Context, req resource.CreateRequest,
data.Region = types.StringValue(*serverResp.JSON200.Server.Region.Slug)
data.Size = types.StringValue(*serverResp.JSON200.Server.Size.Slug)
data.Backups = types.BoolValue(serverResp.JSON200.Server.NextBackupWindow != nil)
data.Ipv6 = types.BoolValue(len(serverResp.JSON200.Server.Networks.V6) > 0)
data.PortBlocking = types.BoolValue(serverResp.JSON200.Server.Networks.PortBlocking)
data.VpcId = types.Int64PointerValue(serverResp.JSON200.Server.VpcId)
data.Permalink = types.StringValue(*serverResp.JSON200.Server.Permalink)
@@ -890,6 +936,43 @@ func (r *serverResource) Update(ctx context.Context, req resource.UpdateRequest,
}
}
// Change ipv6
if !plan.Ipv6.Equal(state.Ipv6) {
ipv6Resp, err := r.bc.client.PostServersServerIdActionsChangeIpv6WithResponse(
ctx,
state.Id.ValueInt64(),
binarylane.PostServersServerIdActionsChangeIpv6JSONRequestBody{
Type: "change_ipv6",
Enabled: plan.Ipv6.ValueBool(),
},
)
if err != nil {
resp.Diagnostics.AddError("Error changing IPv6", err.Error())
return
}
err = r.waitForServerAction(ctx, state.Id.ValueInt64(), *ipv6Resp.JSON200.Action.Id)
if err != nil {
resp.Diagnostics.AddError("Error waiting for changing IPv6", err.Error())
return
}
state.Ipv6 = plan.Ipv6
state.PublicIpv6Addresses = plan.PublicIpv6Addresses
state.PrivateIpv6Addresses = plan.PrivateIpv6Addresses
if state.PublicIpv6Addresses.IsUnknown() || state.PrivateIpv6Addresses.IsUnknown() || listContainsUnknown(ctx, state.PublicIpv6Addresses) || listContainsUnknown(ctx, state.PrivateIpv6Addresses) {
refreshNeeded = true
}
// Save updated data into Terraform state
resp.Diagnostics.Append(resp.State.Set(ctx, &state)...)
if resp.Diagnostics.HasError() {
return
}
}
// Rebuild operation
if !plan.SshKeys.Equal(state.SshKeys) || !plan.UserData.IsNull() && !plan.UserData.Equal(state.UserData) {
var rebuildReq *binarylane.PostServersServerIdActionsRebuildJSONRequestBody
@@ -1258,6 +1341,7 @@ func (r *serverResource) fetchServerResourceState(ctx context.Context, state *se
state.Memory = types.Int32Value(*serverResp.JSON200.Server.Memory)
state.Disk = types.Int32Value(*serverResp.JSON200.Server.Disk)
state.Backups = types.BoolValue(serverResp.JSON200.Server.NextBackupWindow != nil)
state.Ipv6 = types.BoolValue(len(serverResp.JSON200.Server.Networks.V6) > 0)
advFeat := *serverResp.JSON200.Server.AdvancedFeatures.EnabledAdvancedFeatures
state.AdvancedFeatures, diags = resources.NewAdvancedFeaturesValue(
@@ -1307,6 +1391,33 @@ func (r *serverResource) fetchServerResourceState(ctx context.Context, state *se
state.PrivateIPv4Addresses = tfPrivateIpv4Addresses
}
publicIpv6Addresses := []string{}
privateIpv6Addresses := []string{}
for _, v6address := range serverResp.JSON200.Server.Networks.V6 {
if v6address.Type == "public" {
publicIpv6Addresses = append(publicIpv6Addresses, v6address.IpAddress)
} else {
privateIpv6Addresses = append(privateIpv6Addresses, v6address.IpAddress)
}
}
tfPublicIpv6Addresses, diag := types.ListValueFrom(ctx, types.StringType, publicIpv6Addresses)
diags.Append(diag...)
if diag.HasError() || tfPublicIpv6Addresses.IsNull() {
state.PublicIpv6Addresses = types.ListUnknown(state.PublicIpv6Addresses.ElementType(ctx))
} else {
state.PublicIpv6Addresses = tfPublicIpv6Addresses
}
tfPrivateIpv6Addresses, diag := types.ListValueFrom(ctx, types.StringType, privateIpv6Addresses)
diags.Append(diag...)
if diag.HasError() || tfPrivateIpv6Addresses.IsNull() {
state.PrivateIpv6Addresses = types.ListUnknown(state.PrivateIpv6Addresses.ElementType(ctx))
} else {
state.PrivateIpv6Addresses = tfPrivateIpv6Addresses
}
return diags
}
@@ -104,6 +104,8 @@ echo "Hello World" > /var/tmp/output.txt
resource.TestCheckResourceAttr("binarylane_server.test", "advanced_features.cloud_init", "true"),
resource.TestCheckResourceAttr("binarylane_server.test", "advanced_features.qemu_guest_agent", "false"),
resource.TestCheckResourceAttr("binarylane_server.test", "advanced_features.uefi_boot", "false"),
resource.TestCheckResourceAttr("binarylane_server.test", "ipv6", "false"),
resource.TestCheckResourceAttr("binarylane_server.test", "public_ipv6_addresses.#", "0"),
// Verify data source values
resource.TestCheckResourceAttrPair("data.binarylane_server.test", "id", "binarylane_server.test", "id"),
@@ -130,6 +132,8 @@ echo "Hello World" > /var/tmp/output.txt
resource.TestCheckResourceAttr("data.binarylane_server.test", "advanced_features.cloud_init", "true"),
resource.TestCheckResourceAttr("data.binarylane_server.test", "advanced_features.qemu_guest_agent", "false"),
resource.TestCheckResourceAttr("data.binarylane_server.test", "advanced_features.uefi_boot", "false"),
resource.TestCheckResourceAttr("data.binarylane_server.test", "ipv6", "false"),
resource.TestCheckResourceAttr("data.binarylane_server.test", "public_ipv6_addresses.#", "0"),
),
},
// Test import by ID
@@ -180,6 +184,7 @@ resource "binarylane_server" "test" {
advanced_features = {
emulated_hyperv = true
}
ipv6 = true
# source_and_destination_check = null # defaults to null
# backups = false # defaults to false
@@ -214,6 +219,9 @@ echo "Hello Whitespace" > /var/tmp/output.txt
`),
resource.TestCheckResourceAttr("binarylane_server.test", "ipv6", "true"),
resource.TestCheckResourceAttr("binarylane_server.test", "public_ipv6_addresses.#", "1"),
resource.TestCheckResourceAttr("binarylane_server.test", "private_ipv6_addresses.#", "1"),
),
},
// Change password testing (Cannot run at same time as Rebuild operation, so it has it's own test)
+1 -1
View File
@@ -82,7 +82,7 @@ func (d *sshKeyDataSource) Schema(ctx context.Context, req datasource.SchemaRequ
}
fingerprintDescription := "The fingerprint of the SSH key."
resp.Schema.Attributes["fingerprint"] = &schema.StringAttribute{
resp.Schema.Attributes["fingerprint"] = schema.StringAttribute{
Description: fingerprintDescription,
MarkdownDescription: fingerprintDescription,
Optional: false,
+1 -1
View File
@@ -105,7 +105,7 @@ func (r *sshKeyResource) Schema(ctx context.Context, req resource.SchemaRequest,
}
fingerprintDescription := "The fingerprint of the SSH key."
resp.Schema.Attributes["fingerprint"] = &schema.StringAttribute{
resp.Schema.Attributes["fingerprint"] = schema.StringAttribute{
Description: fingerprintDescription,
MarkdownDescription: fingerprintDescription,
Optional: false,
+41 -2
View File
@@ -127,6 +127,45 @@ func convertResourceAttrToDataSourceAttr(name string, attribute r_schema.Attribu
}, nil
default:
if t, isSet := attribute.(r_schema.SetNestedAttribute); isSet {
nestedObjectAttrs := make(map[string]d_schema.Attribute)
for name, attribute := range t.NestedObject.Attributes {
nestedAttribute, err := convertResourceAttrToDataSourceAttr(name, attribute, required, optional)
if err != nil {
return nil, err
}
nestedObjectAttrs[name] = nestedAttribute
}
return d_schema.SetNestedAttribute{
NestedObject: d_schema.NestedAttributeObject{
Attributes: nestedObjectAttrs,
CustomType: t.NestedObject.CustomType,
Validators: t.NestedObject.Validators,
},
CustomType: t.CustomType,
Description: attribute.GetDescription(),
Required: required,
Optional: optional,
Computed: !required,
Sensitive: attribute.IsSensitive(),
MarkdownDescription: attribute.GetMarkdownDescription(),
DeprecationMessage: attribute.GetDeprecationMessage(),
}, nil
}
if t, isSet := attribute.GetType().(types.SetType); isSet {
return d_schema.SetAttribute{
ElementType: t.ElemType,
Description: attribute.GetDescription(),
Required: required,
Optional: optional,
Computed: !required,
Sensitive: attribute.IsSensitive(),
MarkdownDescription: attribute.GetMarkdownDescription(),
DeprecationMessage: attribute.GetDeprecationMessage(),
}, nil
}
if t, isList := attribute.(r_schema.ListNestedAttribute); isList {
nestedObjectAttrs := make(map[string]d_schema.Attribute)
for name, attribute := range t.NestedObject.Attributes {
@@ -136,13 +175,13 @@ func convertResourceAttrToDataSourceAttr(name string, attribute r_schema.Attribu
}
nestedObjectAttrs[name] = nestedAttribute
}
return d_schema.ListNestedAttribute{
NestedObject: d_schema.NestedAttributeObject{
Attributes: nestedObjectAttrs,
CustomType: t.NestedObject.CustomType,
Validators: t.NestedObject.Validators,
},
CustomType: t.CustomType,
Description: attribute.GetDescription(),
Required: required,
Optional: optional,
@@ -165,6 +204,7 @@ func convertResourceAttrToDataSourceAttr(name string, attribute r_schema.Attribu
DeprecationMessage: attribute.GetDeprecationMessage(),
}, nil
}
if t, isObject := attribute.(r_schema.SingleNestedAttribute); isObject {
attributeTypes := make(map[string]attr.Type, len(t.GetAttributes()))
for name, attribute := range t.GetAttributes() {
@@ -183,7 +223,6 @@ func convertResourceAttrToDataSourceAttr(name string, attribute r_schema.Attribu
AttributeTypes: attributeTypes,
}, nil
}
if t, isObject := attribute.GetType().(types.ObjectType); isObject {
return d_schema.ObjectAttribute{
AttributeTypes: t.AttrTypes,
+17 -1
View File
@@ -12,6 +12,9 @@ import (
"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringdefault"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-log/tflog"
)
@@ -60,7 +63,7 @@ func (r *vpcResource) Schema(ctx context.Context, req resource.SchemaRequest, re
// Overrides
id := resp.Schema.Attributes["id"]
resp.Schema.Attributes["id"] = &schema.Int64Attribute{
resp.Schema.Attributes["id"] = schema.Int64Attribute{
Description: id.GetDescription(),
MarkdownDescription: id.GetMarkdownDescription(),
// read only
@@ -68,6 +71,19 @@ func (r *vpcResource) Schema(ctx context.Context, req resource.SchemaRequest, re
Required: false,
Computed: true,
}
ipRange := resp.Schema.Attributes["ip_range"]
resp.Schema.Attributes["ip_range"] = schema.StringAttribute{
Description: ipRange.GetDescription(),
MarkdownDescription: ipRange.GetMarkdownDescription(),
Required: false,
Computed: true,
Optional: true,
PlanModifiers: []planmodifier.String{
stringplanmodifier.RequiresReplace(),
},
Default: stringdefault.StaticString("10.240.0.0/16"),
}
}
func (r *vpcResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
@@ -47,7 +47,7 @@ func (d *vpcRouteEntriesDataSource) Schema(ctx context.Context, req datasource.S
// Overrides
vpcId := resp.Schema.Attributes["vpc_id"]
resp.Schema.Attributes["vpc_id"] = &schema.Int64Attribute{
resp.Schema.Attributes["vpc_id"] = schema.Int64Attribute{
Description: vpcId.GetDescription(),
MarkdownDescription: vpcId.GetMarkdownDescription(),
Required: true, // vpc_id is required to define the route entries
@@ -55,7 +55,7 @@ func (d *vpcRouteEntriesDataSource) Schema(ctx context.Context, req datasource.S
vpcRouteEntries := resp.Schema.Attributes["route_entries"].(schema.ListNestedAttribute)
vpcRouteEntriesDescription := "The route entries that control how network traffic is directed through the VPC environment."
resp.Schema.Attributes["route_entries"] = &schema.ListNestedAttribute{
resp.Schema.Attributes["route_entries"] = schema.ListNestedAttribute{
Description: vpcRouteEntriesDescription,
NestedObject: schema.NestedAttributeObject{
CustomType: vpcRouteEntries.NestedObject.CustomType,
@@ -48,7 +48,7 @@ func (r *vpcRouteEntriesResource) Schema(ctx context.Context, req resource.Schem
// Overrides
vpcId := resp.Schema.Attributes["vpc_id"]
resp.Schema.Attributes["vpc_id"] = &schema.Int64Attribute{
resp.Schema.Attributes["vpc_id"] = schema.Int64Attribute{
Description: vpcId.GetDescription(),
MarkdownDescription: vpcId.GetMarkdownDescription(),
Required: true, // vpc_id is required to define the route entries
@@ -246,7 +246,7 @@ func GetRouteEntriesState(ctx context.Context, routeEntries *[]binarylane.RouteE
routeEntriesValue := resources.RouteEntriesValue{}
var routeEntriesValues []resources.RouteEntriesValue
if *routeEntries == nil || len(*routeEntries) == 0 {
if len(*routeEntries) == 0 {
routeEntriesValues = []resources.RouteEntriesValue{}
} else {
for _, route := range *routeEntries {
@@ -26,8 +26,8 @@ func LoadBalancerResourceSchema(ctx context.Context) schema.Schema {
Attributes: map[string]schema.Attribute{
"entry_protocol": schema.StringAttribute{
Required: true,
Description: "The protocol that traffic must match for the load balancer to forward it. Valid values are \"http\" and \"https\".",
MarkdownDescription: "The protocol that traffic must match for the load balancer to forward it. Valid values are \"http\" and \"https\".",
Description: "The protocol that traffic must match for this load balancer to forward traffic according to this rule.\n\n| Value | Description |\n| ----- | ----------- |\n| http | The load balancer will forward HTTP traffic that matches this rule. |\n| https | The load balancer will forward HTTPS traffic that matches this rule. |\n\n",
MarkdownDescription: "The protocol that traffic must match for this load balancer to forward traffic according to this rule.\n\n| Value | Description |\n| ----- | ----------- |\n| http | The load balancer will forward HTTP traffic that matches this rule. |\n| https | The load balancer will forward HTTPS traffic that matches this rule. |\n\n",
Validators: []validator.String{
stringvalidator.OneOf(
"http",
@@ -95,7 +95,7 @@ func LoadBalancerResourceSchema(ctx context.Context) schema.Schema {
Description: "Leave null to create an anycast load balancer.",
MarkdownDescription: "Leave null to create an anycast load balancer.",
},
"server_ids": schema.ListAttribute{
"server_ids": schema.SetAttribute{
ElementType: types.Int64Type,
Optional: true,
Computed: true,
@@ -112,7 +112,7 @@ type LoadBalancerModel struct {
Id types.Int64 `tfsdk:"id"`
Name types.String `tfsdk:"name"`
Region types.String `tfsdk:"region"`
ServerIds types.List `tfsdk:"server_ids"`
ServerIds types.Set `tfsdk:"server_ids"`
}
var _ basetypes.ObjectTypable = ForwardingRulesType{}
@@ -105,6 +105,12 @@ func ServerResourceSchema(ctx context.Context) schema.Schema {
Description: "The slug of the selected operating system.",
MarkdownDescription: "The slug of the selected operating system.",
},
"ipv6": schema.BoolAttribute{
Optional: true,
Computed: true,
Description: "If true this will enable IPv6 for this server.",
MarkdownDescription: "If true this will enable IPv6 for this server.",
},
"name": schema.StringAttribute{
Optional: true,
Computed: true,
@@ -164,6 +170,7 @@ type ServerModel struct {
Backups types.Bool `tfsdk:"backups"`
Id types.Int64 `tfsdk:"id"`
Image types.String `tfsdk:"image"`
Ipv6 types.Bool `tfsdk:"ipv6"`
Name types.String `tfsdk:"name"`
PortBlocking types.Bool `tfsdk:"port_blocking"`
Region types.String `tfsdk:"region"`
+68 -32
View File
@@ -8,7 +8,7 @@
"url": "https://support.binarylane.com.au",
"email": "support@binarylane.com.au"
},
"version": "0.32.0",
"version": "0.33.0",
"x-logo": {
"url": "https://www.binarylane.com.au/res/images/binarylane/logo.png",
"backgroundColor": "#000000",
@@ -7590,7 +7590,7 @@
"forwarding_rules": {
"type": "array",
"items": {
"$ref": "#/components/schemas/ForwardingRule"
"$ref": "#/components/schemas/ForwardingRuleRequest"
},
"description": "The rules that control which traffic the load balancer will forward to servers in the pool. Leave null to accept a default \"HTTP\" only forwarding rule.",
"nullable": true,
@@ -7601,7 +7601,7 @@
"health_check": {
"allOf": [
{
"$ref": "#/components/schemas/HealthCheck"
"$ref": "#/components/schemas/HealthCheckRequest"
}
],
"description": "The rules that determine which servers are considered 'healthy' and in the server pool for the load balancer. Leave this null to accept appropriate defaults based on the forwarding_rules.",
@@ -8542,6 +8542,25 @@
}
}
},
"ForwardingRuleRequest": {
"required": [
"entry_protocol"
],
"type": "object",
"properties": {
"entry_protocol": {
"allOf": [
{
"$ref": "#/components/schemas/LoadBalancerRuleProtocol"
}
],
"description": "The protocol that traffic must match for this load balancer to forward traffic according to this rule.\n\n| Value | Description |\n| ----- | ----------- |\n| http | The load balancer will forward HTTP traffic that matches this rule. |\n| https | The load balancer will forward HTTPS traffic that matches this rule. |\n\n",
"x-oapi-codegen-extra-tags": {
"tfsdk": "entry_protocol"
}
}
}
},
"ForwardingRulesRequest": {
"required": [
"forwarding_rules"
@@ -8551,13 +8570,44 @@
"forwarding_rules": {
"type": "array",
"items": {
"$ref": "#/components/schemas/ForwardingRule"
"$ref": "#/components/schemas/ForwardingRuleRequest"
},
"description": "The rules that control which traffic the load balancer will forward to servers in the pool."
}
}
},
"HealthCheck": {
"required": [
"path",
"protocol"
],
"type": "object",
"properties": {
"protocol": {
"allOf": [
{
"$ref": "#/components/schemas/HealthCheckProtocol"
}
],
"description": "The protocol used for the health check.\n\n| Value | Description |\n| ----- | ----------- |\n| http | The health check will be performed via HTTP. |\n| https | The health check will be performed via HTTPS. |\n| both | The health check will be performed via both HTTP and HTTPS. Failing a health check on one protocol will remove the server from the pool of servers only for that protocol. |\n\n"
},
"path": {
"minLength": 1,
"type": "string",
"description": "The path to the health check endpoint."
}
}
},
"HealthCheckProtocol": {
"type": "string",
"description": "\n| Value | Description |\n| ----- | ----------- |\n| http | The health check will be performed via HTTP. |\n| https | The health check will be performed via HTTPS. |\n| both | The health check will be performed via both HTTP and HTTPS. Failing a health check on one protocol will remove the server from the pool of servers only for that protocol. |\n\n",
"x-enum-descriptions": [
"The health check will be performed via HTTP.",
"The health check will be performed via HTTPS.",
"The health check will be performed via both HTTP and HTTPS. Failing a health check on one protocol will remove the server from the pool of servers only for that protocol."
]
},
"HealthCheckRequest": {
"type": "object",
"properties": {
"protocol": {
@@ -8577,15 +8627,6 @@
}
}
},
"HealthCheckProtocol": {
"type": "string",
"description": "\n| Value | Description |\n| ----- | ----------- |\n| http | The health check will be performed via HTTP. |\n| https | The health check will be performed via HTTPS. |\n| both | The health check will be performed via both HTTP and HTTPS. Failing a health check on one protocol will remove the server from the pool of servers only for that protocol. |\n\n",
"x-enum-descriptions": [
"The health check will be performed via HTTP.",
"The health check will be performed via HTTPS.",
"The health check will be performed via both HTTP and HTTPS. Failing a health check on one protocol will remove the server from the pool of servers only for that protocol."
]
},
"Host": {
"required": [
"display_name"
@@ -9295,6 +9336,7 @@
},
"LicensedSoftware": {
"required": [
"incompatible",
"licence_count",
"software"
],
@@ -9312,6 +9354,10 @@
"type": "integer",
"description": "The current licence count for the software.",
"format": "int32"
},
"incompatible": {
"type": "boolean",
"description": "Software that is incompatible with the server will be automatically removed at the next plan change.\nServers may have incompatible software due to changes made by support. Software is not incompatible merely because it is disabled;\ndisabled software may be retained by servers that already have it, incompatible software will be removed."
}
}
},
@@ -9380,21 +9426,18 @@
"type": "integer",
"description": "The ID of the load balancer.",
"format": "int64",
"readOnly": true,
"x-cli-format": 1
},
"name": {
"minLength": 1,
"type": "string",
"description": "The hostname of the load balancer.",
"readOnly": true,
"x-cli-format": 2
},
"ip": {
"minLength": 1,
"type": "string",
"description": "The IPv4 address of the load balancer.",
"readOnly": true,
"x-cli-format": 4
},
"status": {
@@ -9403,21 +9446,19 @@
"$ref": "#/components/schemas/LoadBalancerStatus"
}
],
"readOnly": true
"description": "The current status of the load balancer.\n\n| Value | Description |\n| ----- | ----------- |\n| new | The load balancer is currently being built and is not ready to accept connections. |\n| active | The load balancer is available. |\n| errored | The load balancer is in an errored state. |\n\n"
},
"created_at": {
"type": "string",
"description": "The date and time in ISO8601 format of the creation of the load balancer.",
"format": "date-time",
"readOnly": true
"format": "date-time"
},
"forwarding_rules": {
"type": "array",
"items": {
"$ref": "#/components/schemas/ForwardingRule"
},
"description": "The rules that control which traffic the load balancer will forward to servers in the pool.",
"readOnly": true
"description": "The rules that control which traffic the load balancer will forward to servers in the pool."
},
"health_check": {
"allOf": [
@@ -9426,7 +9467,6 @@
}
],
"description": "The rules that determine which servers are considered 'healthy' and in the server pool for the load balancer.",
"readOnly": true,
"x-oapi-codegen-extra-tags": {
"tfsdk": "health_check"
}
@@ -9439,7 +9479,6 @@
],
"description": "The region the load balancer is located in. If this value is null the load balancer is an 'AnyCast' load balancer.",
"nullable": true,
"readOnly": true,
"x-cli-format": 3
},
"server_ids": {
@@ -9448,8 +9487,7 @@
"type": "integer",
"format": "int64"
},
"description": "The server IDs of the servers that are currently in the load balancer pool (regardless of their current 'health').",
"readOnly": true
"description": "The server IDs of the servers that are currently in the load balancer pool (regardless of their current 'health')."
}
}
},
@@ -9467,8 +9505,7 @@
"type": "string"
},
"description": "The slugs of regions where this load balancer option is available. If this is an Anycast load balancer option this will be null.",
"nullable": true,
"readOnly": true
"nullable": true
},
"anycast": {
"type": "boolean",
@@ -9478,8 +9515,7 @@
"price_monthly": {
"type": "number",
"description": "Monthly Price in AU$.",
"format": "double",
"readOnly": true
"format": "double"
},
"price_hourly": {
"type": "number",
@@ -10237,7 +10273,7 @@
"$ref": "#/components/schemas/ChangeLicenses"
}
],
"description": "This may be left null to keep the current licenses for the server. If this is provided any licenses that are not included will be removed.",
"description": "This may be left null to keep the current licenses for the server. If this is provided any licenses that are not included will be removed. Any licences that are invalid will be removed regardless, see the documentation for `servers/{server_id}/software` for more information.",
"nullable": true
},
"pre_action_backup": {
@@ -12290,7 +12326,7 @@
"forwarding_rules": {
"type": "array",
"items": {
"$ref": "#/components/schemas/ForwardingRule"
"$ref": "#/components/schemas/ForwardingRuleRequest"
},
"description": "The rules that control which traffic the load balancer will forward to servers in the pool. Leave null to accept a default \"HTTP\" only forwarding rule.",
"nullable": true
@@ -12298,7 +12334,7 @@
"health_check": {
"allOf": [
{
"$ref": "#/components/schemas/HealthCheck"
"$ref": "#/components/schemas/HealthCheckRequest"
}
],
"description": "The rules that determine which servers are considered 'healthy' and in the server pool for the load balancer. Leave this null to accept appropriate defaults based on the forwarding_rules.",
+11 -3
View File
@@ -712,7 +712,7 @@
"name": "entry_protocol",
"string": {
"computed_optional_required": "required",
"description": "The protocol that traffic must match for the load balancer to forward it. Valid values are \"http\" and \"https\".",
"description": "The protocol that traffic must match for this load balancer to forward traffic according to this rule.\n\n| Value | Description |\n| ----- | ----------- |\n| http | The load balancer will forward HTTP traffic that matches this rule. |\n| https | The load balancer will forward HTTPS traffic that matches this rule. |\n\n",
"validators": [
{
"custom": {
@@ -798,7 +798,7 @@
},
{
"name": "server_ids",
"list": {
"set": {
"computed_optional_required": "computed_optional",
"element_type": {
"int64": {}
@@ -834,6 +834,13 @@
"description": "The slug of the selected operating system."
}
},
{
"name": "ipv6",
"bool": {
"computed_optional_required": "computed_optional",
"description": "If true this will enable IPv6 for this server."
}
},
{
"name": "name",
"string": {
@@ -1309,5 +1316,6 @@
}
}
],
"version": "0.1"
"version": "0.1",
"$schema": "https://raw.githubusercontent.com/hashicorp/terraform-plugin-codegen-spec/main/spec/v0.1/schema.json"
}
-1
View File
@@ -40,7 +40,6 @@ resources:
default will be deployed (assuming the operating system supports SSH Keys). Submit an empty list to
disable deployment of default keys.
ignores:
- ipv6
- licenses
- links
- server
+20 -2
View File
@@ -2,6 +2,24 @@
GENERATOR_CONFIG=$(dirname "$0")/../provider_code_spec.json
# Advanced features configuration
ADVANCED_FEATURES_CONFIG=$(dirname "$0")/data/advanced_features.json
# Add JSON schema
cat <<<$(jq --tab '. + {"$schema": "https://raw.githubusercontent.com/hashicorp/terraform-plugin-codegen-spec/main/spec/v0.1/schema.json"}' $GENERATOR_CONFIG) >$GENERATOR_CONFIG
# Server configuration
ADVANCED_FEATURES_CONFIG=$(dirname "$0")/data/server_advanced_features.json
cat <<<$(jq --tab --slurpfile adv_feat_cfg $ADVANCED_FEATURES_CONFIG '.resources[1].schema.attributes |= . + $adv_feat_cfg' $GENERATOR_CONFIG) >$GENERATOR_CONFIG
# Use set instead of list for server_ids in load_balancer resource
jq --tab '
.resources |= map(
if .name == "load_balancer" then
.schema.attributes |= map(
if .name == "server_ids" then
with_entries(.key |= gsub("list"; "set"))
else .
end
)
else .
end
)
' "$GENERATOR_CONFIG" >"$GENERATOR_CONFIG.tmp" && mv "$GENERATOR_CONFIG.tmp" "$GENERATOR_CONFIG"
+1
View File
@@ -59,6 +59,7 @@ cat <<<$(jq '.components.schemas.AdvancedFirewallRuleRequest.properties.source_a
## Load Balancer
cat <<<$(jq '.components.schemas.CreateLoadBalancerRequest.properties.forwarding_rules += {"x-oapi-codegen-extra-tags": {"tfsdk": "forwarding_rules"}}' $OPENAPI_FILE) >$OPENAPI_FILE
cat <<<$(jq '.components.schemas.ForwardingRule.properties.entry_protocol += {"x-oapi-codegen-extra-tags": {"tfsdk": "entry_protocol"}}' $OPENAPI_FILE) >$OPENAPI_FILE
cat <<<$(jq '.components.schemas.ForwardingRuleRequest.properties.entry_protocol += {"x-oapi-codegen-extra-tags": {"tfsdk": "entry_protocol"}}' $OPENAPI_FILE) >$OPENAPI_FILE
cat <<<$(jq '.components.schemas.LoadBalancer.properties.health_check += {"x-oapi-codegen-extra-tags": {"tfsdk": "health_check"}}' $OPENAPI_FILE) >$OPENAPI_FILE
cat <<<$(jq '.components.schemas.HealthCheckProtocol |= del(.enum)' $OPENAPI_FILE) >$OPENAPI_FILE