Compare commits

..

24 Commits

Author SHA1 Message Date
Oscar Hermoso 7f5bae6b15 💾 allow customising server memory and disk (#52) 2024-12-08 17:09:54 +08:00
Oscar Hermoso 4ef9df6edf 🧁 allow update of server vpc_id without recreating resource, update api (#51) 2024-12-08 08:20:21 +08:00
dependabot[bot] 547763d639 🐹 Bump github.com/hashicorp/terraform-plugin-docs (#49)
Bumps the minor-patch group with 1 update: [github.com/hashicorp/terraform-plugin-docs](https://github.com/hashicorp/terraform-plugin-docs).


Updates `github.com/hashicorp/terraform-plugin-docs` from 0.20.0 to 0.20.1
- [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.20.0...v0.20.1)

---
updated-dependencies:
- dependency-name: github.com/hashicorp/terraform-plugin-docs
  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>
2024-11-29 07:22:41 +08:00
Oscar Hermoso f5fecdd69c 👯 consistent headings/curl summary for parameters in README 2024-11-22 10:40:17 +08:00
dependabot[bot] cd85f67e28 🐹 Bump github.com/hashicorp/terraform-plugin-testing (#47)
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.10.0 to 1.11.0
- [Release notes](https://github.com/hashicorp/terraform-plugin-testing/releases)
- [Changelog](https://github.com/hashicorp/terraform-plugin-testing/blob/main/CHANGELOG.md)
- [Commits](https://github.com/hashicorp/terraform-plugin-testing/compare/v1.10.0...v1.11.0)

---
updated-dependencies:
- dependency-name: github.com/hashicorp/terraform-plugin-testing
  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>
2024-11-22 10:12:43 +08:00
Oscar Hermoso 50d06b967b 🐣 source_and_destination_check for server resource (#48)
* 🐣 source_and_destination_check for server resource

* Ensure default values are handled correctly
2024-11-22 10:12:22 +08:00
Oscar Hermoso e6c50a470d 🔧 rebuild server when ssh_keys, image or user_data changes (#44) 2024-11-17 15:28:41 +08:00
Oscar Hermoso 2bc281d177 🐙 fix server import for public_ipv4_count (#43) 2024-11-13 22:22:10 +08:00
Oscar Hermoso 2a6ba27340 🎛 Replace wait_for_create with timeouts, support resize & change ips (#41) 2024-11-10 13:38:29 +08:00
dependabot[bot] fecd42d4a9 🐹 Bump github.com/hashicorp/terraform-plugin-docs (#39)
Bumps the minor-patch group with 1 update: [github.com/hashicorp/terraform-plugin-docs](https://github.com/hashicorp/terraform-plugin-docs).


Updates `github.com/hashicorp/terraform-plugin-docs` from 0.19.4 to 0.20.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.19.4...v0.20.0)

---
updated-dependencies:
- dependency-name: github.com/hashicorp/terraform-plugin-docs
  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>
2024-11-10 07:18:23 +08:00
dependabot[bot] c5a44b7694 🐈 Bump goreleaser/goreleaser-action in the minor-patch group (#40)
Bumps the minor-patch group with 1 update: [goreleaser/goreleaser-action](https://github.com/goreleaser/goreleaser-action).


Updates `goreleaser/goreleaser-action` from 6.0.0 to 6.1.0
- [Release notes](https://github.com/goreleaser/goreleaser-action/releases)
- [Commits](https://github.com/goreleaser/goreleaser-action/compare/286f3b13b1b49da4ac219696163fb8c1c93e1200...9ed2f89a662bf1735a48bc8557fd212fa902bebf)

---
updated-dependencies:
- dependency-name: goreleaser/goreleaser-action
  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>
2024-11-10 07:16:58 +08:00
Oscar Hermoso 2c639837ef 💁 support updates for server resource - currently rename, or replace (#38) 2024-11-03 11:02:15 +08:00
Oscar Hermoso 200b2ee3a1 📠 Make public_ipv4_count a mandatory attribute on the server resource (#36) 2024-11-03 06:42:41 +08:00
Oscar Hermoso a135bceee8 🧽 remove retries from create operations, BL has fixed underlying bug (#35) 2024-11-03 06:06:32 +08:00
dependabot[bot] 103f4cc2b0 🐈 Bump crazy-max/ghaction-import-gpg in the minor-patch group (#33)
Bumps the minor-patch group with 1 update: [crazy-max/ghaction-import-gpg](https://github.com/crazy-max/ghaction-import-gpg).


Updates `crazy-max/ghaction-import-gpg` from 6.1.0 to 6.2.0
- [Release notes](https://github.com/crazy-max/ghaction-import-gpg/releases)
- [Commits](https://github.com/crazy-max/ghaction-import-gpg/compare/01dd5d3ca463c7f10f7f4f7b4f177225ac661ee4...cb9bde2e2525e640591a934b1fd28eef1dcaf5e5)

---
updated-dependencies:
- dependency-name: crazy-max/ghaction-import-gpg
  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>
2024-11-03 05:39:38 +08:00
dependabot[bot] db948a103c 🐹 Bump the minor-patch group with 3 updates (#34)
Bumps the minor-patch group with 3 updates: [github.com/hashicorp/terraform-plugin-framework](https://github.com/hashicorp/terraform-plugin-framework), [github.com/hashicorp/terraform-plugin-framework-validators](https://github.com/hashicorp/terraform-plugin-framework-validators) and [github.com/hashicorp/terraform-plugin-go](https://github.com/hashicorp/terraform-plugin-go).


Updates `github.com/hashicorp/terraform-plugin-framework` from 1.12.0 to 1.13.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.12.0...v1.13.0)

Updates `github.com/hashicorp/terraform-plugin-framework-validators` from 0.14.0 to 0.15.0
- [Release notes](https://github.com/hashicorp/terraform-plugin-framework-validators/releases)
- [Changelog](https://github.com/hashicorp/terraform-plugin-framework-validators/blob/main/CHANGELOG.md)
- [Commits](https://github.com/hashicorp/terraform-plugin-framework-validators/compare/v0.14.0...v0.15.0)

Updates `github.com/hashicorp/terraform-plugin-go` from 0.24.0 to 0.25.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.24.0...v0.25.0)

---
updated-dependencies:
- dependency-name: github.com/hashicorp/terraform-plugin-framework
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: minor-patch
- dependency-name: github.com/hashicorp/terraform-plugin-framework-validators
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: minor-patch
- dependency-name: github.com/hashicorp/terraform-plugin-go
  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>
2024-11-03 05:39:19 +08:00
Oscar Hermoso e18d2424d0 📼 ensure that load balancer always sets model state for health checks (#32) 2024-10-25 10:39:11 +08:00
dependabot[bot] e1aac7ec1f 🐹 Bump github.com/hashicorp/terraform-plugin-framework-validators (#31)
Bumps the minor-patch group with 1 update: [github.com/hashicorp/terraform-plugin-framework-validators](https://github.com/hashicorp/terraform-plugin-framework-validators).


Updates `github.com/hashicorp/terraform-plugin-framework-validators` from 0.13.0 to 0.14.0
- [Release notes](https://github.com/hashicorp/terraform-plugin-framework-validators/releases)
- [Changelog](https://github.com/hashicorp/terraform-plugin-framework-validators/blob/main/CHANGELOG.md)
- [Commits](https://github.com/hashicorp/terraform-plugin-framework-validators/compare/v0.13.0...v0.14.0)

---
updated-dependencies:
- dependency-name: github.com/hashicorp/terraform-plugin-framework-validators
  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>
2024-10-18 09:50:08 +08:00
Oscar Hermoso 6c3520bbda ⭕ Retry if Servers, SSH Keys, or Load Balancer creation returns 500 response (#29)
* ⭕ retry on failed create of server, load balancer, and SSH key

* 🧹 sweepers for test resources

* 🧹 sweepers, but now they're working
2024-10-13 08:48:12 +08:00
dependabot[bot] 22ea042e33 Bump hashicorp/setup-terraform from 2 to 3 (#23)
Bumps [hashicorp/setup-terraform](https://github.com/hashicorp/setup-terraform) from 2 to 3.
- [Release notes](https://github.com/hashicorp/setup-terraform/releases)
- [Changelog](https://github.com/hashicorp/setup-terraform/blob/main/CHANGELOG.md)
- [Commits](https://github.com/hashicorp/setup-terraform/compare/v2...v3)

---
updated-dependencies:
- dependency-name: hashicorp/setup-terraform
  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>
2024-10-13 08:47:41 +08:00
dependabot[bot] b63f052a9f Bump actions/checkout from 3 to 4 (#22)
Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4.
- [Release notes](https://github.com/actions/checkout/releases)
- [Commits](https://github.com/actions/checkout/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/checkout
  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>
2024-10-10 16:37:09 +08:00
Oscar Hermoso a5731e0a12 🧲 Fix README link to examples/README.md 2024-10-05 08:34:22 +08:00
Oscar Hermoso e5450d9f27 🐒 Fix SSH key logging, types (#28)
* 🐒 Fix SSH key logging, import type

* 💱 Ignore comments in go generate git diff
2024-10-04 13:10:14 +08:00
dependabot[bot] 53b1643f30 🐹 Bump github.com/oapi-codegen/oapi-codegen/v2 in the minor-patch group (#27)
Bumps the minor-patch group with 1 update: [github.com/oapi-codegen/oapi-codegen/v2](https://github.com/oapi-codegen/oapi-codegen).


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

---
updated-dependencies:
- dependency-name: github.com/oapi-codegen/oapi-codegen/v2
  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>
2024-10-04 12:15:54 +08:00
37 changed files with 1713 additions and 1583 deletions
+6
View File
@@ -1,2 +1,8 @@
TF_ACC=1
BINARYLANE_API_TOKEN=
# Uncomment to enable debug logging (will dump request bodies)
# TF_LOG=DEBUG
# Uncomment to disable the Go cache when testing, useful for flaky tests
# GOCACHE=off
+2 -2
View File
@@ -32,13 +32,13 @@ jobs:
go-version-file: 'go.mod'
cache: true
- name: Import GPG key
uses: crazy-max/ghaction-import-gpg@01dd5d3ca463c7f10f7f4f7b4f177225ac661ee4 # v6.1.0
uses: crazy-max/ghaction-import-gpg@cb9bde2e2525e640591a934b1fd28eef1dcaf5e5 # v6.2.0
id: import_gpg
with:
gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }}
passphrase: ${{ secrets.PASSPHRASE }}
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@286f3b13b1b49da4ac219696163fb8c1c93e1200 # v6.0.0
uses: goreleaser/goreleaser-action@9ed2f89a662bf1735a48bc8557fd212fa902bebf # v6.1.0
with:
args: release --clean
env:
+10 -4
View File
@@ -23,18 +23,18 @@ 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@v3
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version-file: 'go.mod'
- uses: hashicorp/setup-terraform@v2
- uses: hashicorp/setup-terraform@v3
with:
terraform_version: '1.5.*'
terraform_wrapper: false
- name: Check if generated files are up to date
run: |
go generate
git diff --color --exit-code
git diff --color --exit-code --ignore-matching-lines='//'
if [ $? -ne 0 ]; then
echo "generated files are not up to date, please run 'go generate' and commit the changes" >&2
exit 1
@@ -44,11 +44,17 @@ jobs:
env:
TF_ACC: '1'
BINARYLANE_API_TOKEN: ${{ secrets.BINARYLANE_API_TOKEN }}
- name: Run sweepers
if: failure()
run: go test -v ./internal/provider/... -sweep=all
env:
TF_ACC: '1'
BINARYLANE_API_TOKEN: ${{ secrets.BINARYLANE_API_TOKEN }}
# unit:
# name: Unit Tests
# runs-on: ubuntu-latest
# steps:
# - uses: actions/checkout@v3
# - uses: actions/checkout@v4
# - uses: actions/setup-go@v5
# with:
# go-version-file: 'go.mod'
+6
View File
@@ -41,6 +41,12 @@ eval export $(cat .env)
go test -v ./internal/provider/...
```
To run Sweepers:
```sh
go test -v ./internal/provider/... -sweep=all
```
### Update modules
```sh
+35 -26
View File
@@ -1,12 +1,13 @@
# terraform-provider-binarylane
See the examples in the [examples directory](./examples/basic/README.md).
See the [documentation on the Terraform Registry](https://registry.terraform.io/providers/oscarhermoso/binarylane/latest), or see [examples in the `examples` directory](./examples/README.md).
```terraform
resource "binarylane_server" "example" {
region = "per"
image = "ubuntu-24.04"
size = "std-min"
region = "per"
image = "ubuntu-24.04"
size = "std-min"
public_ipv4_count = 1
}
```
@@ -38,9 +39,35 @@ Planned features:
- [ ] Virtual Private Cloud
- [ ] Kubernetes
## Parameters
## Server parameters
Images:
### Regions
<details>
<summary>curl for regions</summary>
```sh
curl -X GET "https://api.binarylane.com.au/v2/regions" \
-H "Authorization: Bearer $BINARYLANE_API_TOKEN" > tmp/regions.json
jq '[ .regions[] | .slug ] | sort' tmp/regions.json
```
</details>
```json
[
"bne",
"mel",
"per",
"sin",
"syd"
]
```
### Images
<details>
<summary>curl for images</summary>
```sh
curl -X GET "https://api.binarylane.com.au/v2/images?type=distribution&&page=1&per_page=200" \
@@ -48,6 +75,7 @@ curl -X GET "https://api.binarylane.com.au/v2/images?type=distribution&&page=1&p
jq '[ .images[] | .slug ] | sort' tmp/images.json
```
</details>
```json
[
@@ -77,29 +105,10 @@ jq '[ .images[] | .slug ] | sort' tmp/images.json
]
```
Regions:
```sh
curl -X GET "https://api.binarylane.com.au/v2/regions" \
-H "Authorization: Bearer $BINARYLANE_API_TOKEN" > tmp/regions.json
jq '[ .regions[] | .slug ] | sort' tmp/regions.json
```
```json
[
"bne",
"mel",
"per",
"sin",
"syd"
]
```
### Sizes
<details>
<summary>VM size</summary>
<summary>curl for sizes</summary>
```sh
curl -X GET "https://api.binarylane.com.au/v2/sizes" \
+2
View File
@@ -22,7 +22,9 @@ Provides a Binary Lane Server data source. This can be used to read existing ser
### Read-Only
- `backups` (Boolean) If true this will enable two daily backups for the server. `options.daily_backups` will override this value if provided. Setting this to false has no effect.
- `disk` (Number) The amount of storage in GB assigned to the server.
- `image` (String) The slug of the selected operating system.
- `memory` (Number) The amount of memory in MB assigned to the server.
- `name` (String) The hostname of your server, such as vps01.yourcompany.com. If not provided, the server will be created with a random name.
- `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.
+9
View File
@@ -25,6 +25,7 @@ description: |-
- `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.
- `timeouts` (Attributes) (see [below for nested schema](#nestedatt--timeouts))
### Read-Only
@@ -45,3 +46,11 @@ Optional:
- `path` (String) Leave null to accept the default '/' path.
- `protocol` (String) Leave null to accept the default HTTP protocol.
<a id="nestedatt--timeouts"></a>
### Nested Schema for `timeouts`
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).
+26 -2
View File
@@ -18,24 +18,48 @@ Provides a Binary Lane Server resource. This can be used to create and delete se
### Required
- `image` (String) The slug of the selected operating system.
- `public_ipv4_count` (Number) The number of public IPv4 addresses to assign to the server. If this is not provided, the server will be created with the default number of public IPv4 addresses.
- `region` (String) The slug of the selected region.
- `size` (String) The slug of the selected size.
### Optional
- `backups` (Boolean) If true this will enable two daily backups for the server. `options.daily_backups` will override this value if provided. Setting this to false has no effect.
- `disk` (Number) The total storage in GB for this server. If specified this is the absolute value, not just the additional storage above what is included in the size.
Leave null to accept the default for the size if this is a new server or a resize to a different base size,
or to keep the current value if this a resize with the same base size but different options. Valid values:
- must be a multiple of 5
- \> 60GB must be a multiple of 10
- \> 200GB must be a multiple of 100
- `memory` (Number) The total memory in MB for this server. If specified this is the absolute value, not just the
additional memory above what is included in the size. Leave null to accept the default for the size if this is a new
server or a resize to a different base size, or to keep the current value if this a resize with the same base size
but different options. Valid values:
- must be a multiple of 128
- \> 2048MB must be a multiple of 1024
- \> 16384MB must be a multiple of 2048
- \> 24576MB must be a multiple of 4096
- `name` (String) The hostname of your server, such as vps01.yourcompany.com. If not provided, the server will be created with a random name.
- `password` (String, Sensitive) 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.
- `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.
- `public_ipv4_count` (Number) The number of public IPv4 addresses to assign to the server. If this is not provided, the server will be created with the default number of public IPv4 addresses.
- `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.
- `ssh_keys` (List of Number) This is a list of SSH key ids. If this is null or not provided, any SSH keys that have been marked as default will be deployed (assuming the operating system supports SSH Keys). Submit an empty list to disable deployment of default keys.
- `timeouts` (Attributes) (see [below for nested schema](#nestedatt--timeouts))
- `user_data` (String) If provided this will be used to initialise the new server. This must be left null if the Image does not support UserData, see DistributionInfo.Features for more information.
- `vpc_id` (Number) Leave null to use default (public) network for the selected region.
- `wait_for_create` (Number) The number of seconds to wait for the server to be created, after which, a timeout error will be reported. If `wait_seconds` is left empty or set to 0, Terraform will succeed without waiting for the server creation to complete.
### Read-Only
- `id` (Number) The ID of the server to fetch.
- `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.
- `public_ipv4_addresses` (List of String) The public IPv4 addresses assigned to the server.
<a id="nestedatt--timeouts"></a>
### Nested Schema for `timeouts`
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).
+5 -5
View File
@@ -11,10 +11,10 @@ provider "binarylane" {
}
resource "binarylane_server" "example" {
name = "tf-example-basic"
region = "per" # or "syd", "mel", "bne", "sin"
image = "ubuntu-24.04"
size = "std-min" # 1 VPCU, 1 GB Memory, 20 GB NVME Storage, 1000 GB Data Transfer
name = "tf-example-basic"
region = "per" # or "syd", "mel", "bne", "sin"
image = "ubuntu-24.04"
size = "std-min" # 1 VPCU, 1 GB Memory, 20 GB NVME Storage, 1000 GB Data Transfer
public_ipv4_count = 1
# Password will be generated automatically and mailed to the account holder
}
-5
View File
@@ -1,10 +1,5 @@
#cloud-config
bootcmd:
# By default, the provider won't wait for the server installation to complete.
#
# If you want Terraform to wait until the server has fully provisioned, set
# the `wait_for_create` attribute on the `binarylane_server` resource.
#
# If you have additional installation steps that need to be awaited, define
# these in the `bootcmd` section and they will also be awaited.
#
+6 -6
View File
@@ -9,10 +9,10 @@ terraform {
provider "binarylane" {}
resource "binarylane_server" "example" {
name = "tf-cloud-init-example"
region = "per"
image = "ubuntu-24.04"
size = "std-min"
user_data = file("./cloud-config.yml")
wait_for_create = 300 # 5 mins
name = "tf-cloud-init-example"
region = "per"
image = "ubuntu-24.04"
size = "std-min"
user_data = file("./cloud-config.yml")
public_ipv4_count = 1
}
-2
View File
@@ -53,7 +53,6 @@ resource "binarylane_server" "server" {
vpc_id = binarylane_vpc.example.id
public_ipv4_count = 1
user_data = sensitive(data.cloudinit_config.server.rendered)
wait_for_create = 60 # Must wait for the server to be ready before creating firewall rules
}
data "external" "kubeconfig" {
@@ -107,7 +106,6 @@ resource "binarylane_server" "agent" {
vpc_id = binarylane_vpc.example.id
public_ipv4_count = 1
user_data = sensitive(data.cloudinit_config.agent.rendered)
wait_for_create = 60 # Must wait for the server to be ready before creating firewall rules
}
# Virtual Private Cloud Routing
+6 -6
View File
@@ -9,10 +9,10 @@ terraform {
provider "binarylane" {}
resource "binarylane_server" "example" {
name = "tf-nix-example"
region = "per"
image = "debian-12"
size = "std-min"
user_data = file("./cloud-config.yml")
wait_for_create = 300 # 5 mins
name = "tf-nix-example"
region = "per"
image = "debian-12"
size = "std-min"
user_data = file("./cloud-config.yml")
public_ipv4_count = 1
}
+6 -5
View File
@@ -28,11 +28,12 @@ resource "binarylane_ssh_key" "example" {
}
resource "binarylane_server" "example" {
name = "tf-example-ssh"
region = "per"
image = "ubuntu-24.04"
size = "std-min"
ssh_keys = [binarylane_ssh_key.example.id]
name = "tf-example-ssh"
region = "per"
image = "ubuntu-24.04"
size = "std-min"
ssh_keys = [binarylane_ssh_key.example.id]
public_ipv4_count = 1
# If you are using a global default SSH key, you need to explicitly wait for
# it to be created before creating the server.
+7 -6
View File
@@ -35,12 +35,13 @@ resource "binarylane_server" "db" {
# VPN server
resource "binarylane_server" "vpn" {
name = "tf-example-vpc-vpn"
region = "per"
image = "ubuntu-24.04"
size = "std-min"
vpc_id = binarylane_vpc.example.id
public_ipv4_count = 1
name = "tf-example-vpc-vpn"
region = "per"
image = "ubuntu-24.04"
size = "std-min"
vpc_id = binarylane_vpc.example.id
public_ipv4_count = 1
source_and_destination_check = false
}
resource "binarylane_vpc_route_entries" "example" {
+29 -27
View File
@@ -6,13 +6,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.19.4
github.com/hashicorp/terraform-plugin-framework v1.12.0
github.com/hashicorp/terraform-plugin-framework-validators v0.13.0
github.com/hashicorp/terraform-plugin-go v0.24.0
github.com/hashicorp/terraform-plugin-docs v0.20.1
github.com/hashicorp/terraform-plugin-framework v1.13.0
github.com/hashicorp/terraform-plugin-framework-timeouts v0.4.1
github.com/hashicorp/terraform-plugin-framework-validators v0.15.0
github.com/hashicorp/terraform-plugin-go v0.25.0
github.com/hashicorp/terraform-plugin-log v0.9.0
github.com/hashicorp/terraform-plugin-testing v1.10.0
github.com/oapi-codegen/oapi-codegen/v2 v2.3.0
github.com/hashicorp/terraform-plugin-testing v1.11.0
github.com/oapi-codegen/oapi-codegen/v2 v2.4.1
github.com/oapi-codegen/runtime v1.1.1
)
@@ -29,16 +30,16 @@ 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.6.1 // indirect
github.com/bmatcuk/doublestar/v4 v4.7.1 // indirect
github.com/buger/jsonparser v1.1.1 // indirect
github.com/cloudflare/circl v1.3.7 // indirect
github.com/dprotaso/go-yit v0.0.0-20220510233725-9ba8df137936 // indirect
github.com/fatih/color v1.17.0 // 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.124.0 // indirect
github.com/go-openapi/jsonpointer v0.20.2 // indirect
github.com/go-openapi/swag v0.22.8 // indirect
github.com/getkin/kin-openapi v0.127.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
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/uuid v1.6.0 // indirect
@@ -49,23 +50,23 @@ require (
github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 // 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.1 // indirect
github.com/hashicorp/go-plugin v1.6.2 // 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.8.0 // indirect
github.com/hashicorp/hcl/v2 v2.21.0 // indirect
github.com/hashicorp/hc-install v0.9.0 // indirect
github.com/hashicorp/hcl/v2 v2.23.0 // indirect
github.com/hashicorp/logutils v1.0.0 // indirect
github.com/hashicorp/terraform-exec v0.21.0 // indirect
github.com/hashicorp/terraform-json v0.22.1 // indirect
github.com/hashicorp/terraform-json v0.23.0 // indirect
github.com/hashicorp/terraform-plugin-codegen-spec v0.2.0 // indirect
github.com/hashicorp/terraform-plugin-sdk/v2 v2.34.0 // indirect
github.com/hashicorp/terraform-plugin-sdk/v2 v2.35.0 // indirect
github.com/hashicorp/terraform-registry-address v0.2.3 // indirect
github.com/hashicorp/terraform-svchost v0.1.1 // indirect
github.com/hashicorp/yamux v0.1.2 // indirect
github.com/huandu/xstrings v1.4.0 // indirect
github.com/imdario/mergo v0.3.16 // indirect
github.com/invopop/yaml v0.2.0 // indirect
github.com/invopop/yaml v0.3.1 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
@@ -84,6 +85,7 @@ 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/spf13/cast v1.5.1 // indirect
github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect
github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect
@@ -93,22 +95,22 @@ require (
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
github.com/yuin/goldmark v1.7.1 // indirect
github.com/yuin/goldmark v1.7.7 // indirect
github.com/yuin/goldmark-meta v1.1.0 // indirect
github.com/zclconf/go-cty v1.15.0 // indirect
go.abhg.dev/goldmark/frontmatter v0.2.0 // indirect
golang.org/x/crypto v0.27.0 // indirect
golang.org/x/crypto v0.29.0 // indirect
golang.org/x/exp v0.0.0-20240409090435-93d18d7e34b8 // indirect
golang.org/x/mod v0.19.0 // indirect
golang.org/x/net v0.29.0 // indirect
golang.org/x/sync v0.8.0 // indirect
golang.org/x/sys v0.25.0 // indirect
golang.org/x/text v0.18.0 // indirect
golang.org/x/mod v0.21.0 // indirect
golang.org/x/net v0.30.0 // indirect
golang.org/x/sync v0.9.0 // indirect
golang.org/x/sys v0.27.0 // indirect
golang.org/x/text v0.20.0 // indirect
golang.org/x/tools v0.22.0 // indirect
google.golang.org/appengine v1.6.8 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240924160255-9d4c2d233b61 // indirect
google.golang.org/grpc v1.67.0 // indirect
google.golang.org/protobuf v1.34.2 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 // indirect
google.golang.org/grpc v1.67.1 // indirect
google.golang.org/protobuf v1.35.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
+60 -57
View File
@@ -30,8 +30,8 @@ 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.6.1 h1:FH9SifrbvJhnlQpztAx++wlkk70QBf0iBWDwNy7PA4I=
github.com/bmatcuk/doublestar/v4 v4.6.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
github.com/bmatcuk/doublestar/v4 v4.7.1 h1:fdDeAqgT47acgwd9bd9HxJRDmc9UAmPpc+2m0CXv75Q=
github.com/bmatcuk/doublestar/v4 v4.7.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
github.com/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/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs=
@@ -55,26 +55,26 @@ github.com/dprotaso/go-yit v0.0.0-20220510233725-9ba8df137936/go.mod h1:ttYvX5ql
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4=
github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI=
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
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.124.0 h1:VSFNMB9C9rTKBnQ/fpyDU8ytMTr4dWI9QovSKj9kz/M=
github.com/getkin/kin-openapi v0.124.0/go.mod h1:wb1aSZA/iWmorQP9KTAS/phLj/t17B5jT7+fS8ed9NM=
github.com/getkin/kin-openapi v0.127.0 h1:Mghqi3Dhryf3F8vR370nN67pAERW+3a95vomb3MAREY=
github.com/getkin/kin-openapi v0.127.0/go.mod h1:OZrfXzUfGrNbsKj+xmFBx6E5c6yH3At/tAKSc2UszXM=
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU=
github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow=
github.com/go-git/go-git/v5 v5.12.0 h1:7Md+ndsjrzZxbddRDZjF14qK+NN56sy6wkqaVrjZtys=
github.com/go-git/go-git/v5 v5.12.0/go.mod h1:FTM9VKtnI2m65hNI/TenDDDnUf2Q9FHnXYjuz9i5OEY=
github.com/go-openapi/jsonpointer v0.20.2 h1:mQc3nmndL8ZBzStEo3JYF8wzmeWffDH4VbXz58sAx6Q=
github.com/go-openapi/jsonpointer v0.20.2/go.mod h1:bHen+N0u1KEO3YlmqOjTT9Adn1RfD91Ar825/PuiRVs=
github.com/go-openapi/swag v0.22.8 h1:/9RjDSQ0vbFR+NyjGMkFTsA1IA0fmhKSThmfGZjicbw=
github.com/go-openapi/swag v0.22.8/go.mod h1:6QT22icPLEqAM/z/TChgb4WAveCHF92+2gF0CNjHpPI=
github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=
github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM=
github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
@@ -120,8 +120,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.1 h1:P7MR2UP6gNKGPp+y7EZw2kOiq4IR9WiqLvp0XOsVdwI=
github.com/hashicorp/go-plugin v1.6.1/go.mod h1:XPHFku2tFo3o3QKFgSYo+cghcUhw1NA1hZyMK0PWAw0=
github.com/hashicorp/go-plugin v1.6.2 h1:zdGAEd0V1lCaU0u+MxWQhtSDQmahpkwOun8U8EiRVog=
github.com/hashicorp/go-plugin v1.6.2/go.mod h1:CkgLQ5CZqNmdL9U9JzM532t8ZiYQ35+pj3b1FD37R0Q=
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=
@@ -129,36 +129,38 @@ github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/C
github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY=
github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/hc-install v0.8.0 h1:LdpZeXkZYMQhoKPCecJHlKvUkQFixN/nvyR1CdfOLjI=
github.com/hashicorp/hc-install v0.8.0/go.mod h1:+MwJYjDfCruSD/udvBmRB22Nlkwwkwf5sAB6uTIhSaU=
github.com/hashicorp/hcl/v2 v2.21.0 h1:lve4q/o/2rqwYOgUg3y3V2YPyD1/zkCLGjIV74Jit14=
github.com/hashicorp/hcl/v2 v2.21.0/go.mod h1:62ZYHrXgPoX8xBnzl8QzbWq4dyDsDtfCRgIq1rbJEvA=
github.com/hashicorp/hc-install v0.9.0 h1:2dIk8LcvANwtv3QZLckxcjyF5w8KVtiMxu6G6eLhghE=
github.com/hashicorp/hc-install v0.9.0/go.mod h1:+6vOP+mf3tuGgMApVYtmsnDoKWMDcFXeTxCACYZ8SFg=
github.com/hashicorp/hcl/v2 v2.23.0 h1:Fphj1/gCylPxHutVSEOf2fBOh1VE4AuLV7+kbJf3qos=
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.21.0 h1:uNkLAe95ey5Uux6KJdua6+cv8asgILFVWkd/RG0D2XQ=
github.com/hashicorp/terraform-exec v0.21.0/go.mod h1:1PPeMYou+KDUSSeRE9szMZ/oHf4fYUmB923Wzbq1ICg=
github.com/hashicorp/terraform-json v0.22.1 h1:xft84GZR0QzjPVWs4lRUwvTcPnegqlyS7orfb5Ltvec=
github.com/hashicorp/terraform-json v0.22.1/go.mod h1:JbWSQCLFSXFFhg42T7l9iJwdGXBYV8fmmD6o/ML4p3A=
github.com/hashicorp/terraform-json v0.23.0 h1:sniCkExU4iKtTADReHzACkk8fnpQXrdD2xoR+lppBkI=
github.com/hashicorp/terraform-json v0.23.0/go.mod h1:MHdXbBAbSg0GvzuWazEGKAn/cyNfIB7mN6y7KJN6y2c=
github.com/hashicorp/terraform-plugin-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.19.4 h1:G3Bgo7J22OMtegIgn8Cd/CaSeyEljqjH3G39w28JK4c=
github.com/hashicorp/terraform-plugin-docs v0.19.4/go.mod h1:4pLASsatTmRynVzsjEhbXZ6s7xBlUw/2Kt0zfrq8HxA=
github.com/hashicorp/terraform-plugin-framework v1.12.0 h1:7HKaueHPaikX5/7cbC1r9d1m12iYHY+FlNZEGxQ42CQ=
github.com/hashicorp/terraform-plugin-framework v1.12.0/go.mod h1:N/IOQ2uYjW60Jp39Cp3mw7I/OpC/GfZ0385R0YibmkE=
github.com/hashicorp/terraform-plugin-framework-validators v0.13.0 h1:bxZfGo9DIUoLLtHMElsu+zwqI4IsMZQBRRy4iLzZJ8E=
github.com/hashicorp/terraform-plugin-framework-validators v0.13.0/go.mod h1:wGeI02gEhj9nPANU62F2jCaHjXulejm/X+af4PdZaNo=
github.com/hashicorp/terraform-plugin-go v0.24.0 h1:2WpHhginCdVhFIrWHxDEg6RBn3YaWzR2o6qUeIEat2U=
github.com/hashicorp/terraform-plugin-go v0.24.0/go.mod h1:tUQ53lAsOyYSckFGEefGC5C8BAaO0ENqzFd3bQeuYQg=
github.com/hashicorp/terraform-plugin-docs v0.20.1 h1:Fq7E/HrU8kuZu3hNliZGwloFWSYfWEOWnylFhYQIoys=
github.com/hashicorp/terraform-plugin-docs v0.20.1/go.mod h1:Yz6HoK7/EgzSrHPB9J/lWFzwl9/xep2OPnc5jaJDV90=
github.com/hashicorp/terraform-plugin-framework v1.13.0 h1:8OTG4+oZUfKgnfTdPTJwZ532Bh2BobF4H+yBiYJ/scw=
github.com/hashicorp/terraform-plugin-framework v1.13.0/go.mod h1:j64rwMGpgM3NYXTKuxrCnyubQb/4VKldEKlcG8cvmjU=
github.com/hashicorp/terraform-plugin-framework-timeouts v0.4.1 h1:gm5b1kHgFFhaKFhm4h2TgvMUlNzFAtUqlcOWnWPm+9E=
github.com/hashicorp/terraform-plugin-framework-timeouts v0.4.1/go.mod h1:MsjL1sQ9L7wGwzJ5RjcI6FzEMdyoBnw+XK8ZnOvQOLY=
github.com/hashicorp/terraform-plugin-framework-validators v0.15.0 h1:RXMmu7JgpFjnI1a5QjMCBb11usrW2OtAG+iOTIj5c9Y=
github.com/hashicorp/terraform-plugin-framework-validators v0.15.0/go.mod h1:Bh89/hNmqsEWug4/XWKYBwtnw3tbz5BAy1L1OgvbIaY=
github.com/hashicorp/terraform-plugin-go v0.25.0 h1:oi13cx7xXA6QciMcpcFi/rwA974rdTxjqEhXJjbAyks=
github.com/hashicorp/terraform-plugin-go v0.25.0/go.mod h1:+SYagMYadJP86Kvn+TGeV+ofr/R3g4/If0O5sO96MVw=
github.com/hashicorp/terraform-plugin-log v0.9.0 h1:i7hOA+vdAItN1/7UrfBqBwvYPQ9TFvymaRGZED3FCV0=
github.com/hashicorp/terraform-plugin-log v0.9.0/go.mod h1:rKL8egZQ/eXSyDqzLUuwUYLVdlYeamldAHSxjUFADow=
github.com/hashicorp/terraform-plugin-sdk/v2 v2.34.0 h1:kJiWGx2kiQVo97Y5IOGR4EMcZ8DtMswHhUuFibsCQQE=
github.com/hashicorp/terraform-plugin-sdk/v2 v2.34.0/go.mod h1:sl/UoabMc37HA6ICVMmGO+/0wofkVIRxf+BMb/dnoIg=
github.com/hashicorp/terraform-plugin-testing v1.10.0 h1:2+tmRNhvnfE4Bs8rB6v58S/VpqzGC6RCh9Y8ujdn+aw=
github.com/hashicorp/terraform-plugin-testing v1.10.0/go.mod h1:iWRW3+loP33WMch2P/TEyCxxct/ZEcCGMquSLSCVsrc=
github.com/hashicorp/terraform-plugin-sdk/v2 v2.35.0 h1:wyKCCtn6pBBL46c1uIIBNUOWlNfYXfXpVo16iDyLp8Y=
github.com/hashicorp/terraform-plugin-sdk/v2 v2.35.0/go.mod h1:B0Al8NyYVr8Mp/KLwssKXG1RqnTk7FySqSn4fRuLNgw=
github.com/hashicorp/terraform-plugin-testing v1.11.0 h1:MeDT5W3YHbONJt2aPQyaBsgQeAIckwPX41EUHXEn29A=
github.com/hashicorp/terraform-plugin-testing v1.11.0/go.mod h1:WNAHQ3DcgV/0J+B15WTE6hDvxcUdkPPpnB1FR3M910U=
github.com/hashicorp/terraform-registry-address v0.2.3 h1:2TAiKJ1A3MAkZlH1YI/aTVcLZRu7JseiXNRHbOAyoTI=
github.com/hashicorp/terraform-registry-address v0.2.3/go.mod h1:lFHA76T8jfQteVfT7caREqguFrW3c4MFSPhZB7HHgUM=
github.com/hashicorp/terraform-svchost v0.1.1 h1:EZZimZ1GxdqFRinZ1tpJwVxxt49xc/S52uzrw4x0jKQ=
@@ -173,8 +175,8 @@ github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
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/invopop/yaml v0.2.0 h1:7zky/qH+O0DwAyoobXUqvVBwgBFRxKoQ/3FjcVpjTMY=
github.com/invopop/yaml v0.2.0/go.mod h1:2XuRLgs/ouIrW3XNzuNj7J3Nvu/Dig5MXvbCEdiBN3Q=
github.com/invopop/yaml v0.3.1 h1:f0+ZpmhfBSS4MhG+4HYseMdJhoeeopbSKbq5Rpeelso=
github.com/invopop/yaml v0.3.1/go.mod h1:PMOp3nn4/12yEZUFfmOuNHJsZToEEOwoWsT+D81KkeA=
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=
@@ -221,8 +223,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.3.0 h1:rICjNsHbPP1LttefanBPnwsSwl09SqhCO7Ee623qR84=
github.com/oapi-codegen/oapi-codegen/v2 v2.3.0/go.mod h1:4k+cJeSq5ntkwlcpQSxLxICCxQzCL772o30PxdibRt4=
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/runtime v1.1.1 h1:EXLHh0DXIJnWhdRPN2w4MXAzFyE4CskzhNLUmtpMYro=
github.com/oapi-codegen/runtime v1.1.1/go.mod h1:SK9X900oXmPWilYR5/WKPzt3Kqxn/uS/+lbpREv+eCg=
github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA=
@@ -254,8 +256,8 @@ github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSg
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.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
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/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=
@@ -264,6 +266,8 @@ 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.2.2 h1:Iug2P4fLmDw9f41PB6thxUkNUkJzB5i+1/exaj40L3A=
github.com/skeema/knownhosts v1.2.2/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo=
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/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=
@@ -300,8 +304,8 @@ github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yuin/goldmark v1.7.1 h1:3bajkSilaCbjdKVsKdZjZCLBNPL9pYzrCakKaf4U49U=
github.com/yuin/goldmark v1.7.1/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
github.com/yuin/goldmark v1.7.7 h1:5m9rrB1sW3JUMToKFQfb+FGt1U7r57IHu5GrYrG2nqU=
github.com/yuin/goldmark v1.7.7/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
github.com/yuin/goldmark-meta v1.1.0 h1:pWw+JLHGZe8Rk0EGsMVssiNb/AaPMHfSRszZeUeiOUc=
github.com/yuin/goldmark-meta v1.1.0/go.mod h1:U4spWENafuA7Zyg+Lj5RqK/MF+ovMYtBvXi1lBb2VP0=
github.com/zclconf/go-cty v1.15.0 h1:tTCRWxsexYUmtt/wVxgDClUe+uQusuI443uL6e+5sXQ=
@@ -315,14 +319,14 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
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.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ=
golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg=
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.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8=
golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0=
golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
golang.org/x/net v0.0.0-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=
@@ -333,14 +337,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.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo=
golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0=
golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU=
golang.org/x/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.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ=
golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
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=
@@ -366,8 +370,8 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/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=
@@ -378,8 +382,8 @@ 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.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug=
golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4=
golang.org/x/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=
@@ -393,10 +397,10 @@ golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8T
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-20240924160255-9d4c2d233b61 h1:N9BgCIAUvn/M+p4NJccWPWb3BWh88+zyL0ll9HgbEeM=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240924160255-9d4c2d233b61/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
google.golang.org/grpc v1.67.0 h1:IdH9y6PF5MPSdAntIcpjQ+tXO41pcQsfZV2RxtQgVcw=
google.golang.org/grpc v1.67.0/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA=
google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 h1:zciRKQ4kBpFgpfC5QQCVtnnNAcLIqweL7plyZRQHVpI=
google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI=
google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E=
google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA=
google.golang.org/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=
@@ -405,8 +409,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.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
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=
@@ -425,6 +429,5 @@ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20191026110619-0b21df46bc1d/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+64
View File
@@ -0,0 +1,64 @@
package binarylane
import (
"context"
"errors"
"fmt"
"net/http"
"net/http/httputil"
"os"
"github.com/deepmap/oapi-codegen/pkg/securityprovider"
"github.com/hashicorp/terraform-plugin-log/tflog"
)
func NewClientWithDefaultConfig() (*ClientWithResponses, error) {
return NewClientWithConfig("", "")
}
func NewClientWithConfig(endpoint string, token string) (*ClientWithResponses, error) {
if endpoint == "" {
endpoint = os.Getenv("BINARYLANE_API_ENDPOINT")
if endpoint == "" {
endpoint = "https://api.binarylane.com.au/v2"
}
}
if token == "" {
token = os.Getenv("BINARYLANE_API_TOKEN")
if token == "" {
return nil, errors.New("missing or empty value for the Binary Lane API " +
"token. Set the `api_token` value in the configuration or use the " +
"BINARYLANE_API_TOKEN environment variable. If either is already set, " +
"ensure the value is not empty")
}
}
auth, err := securityprovider.NewSecurityProviderBearerToken(token)
if err != nil {
return nil, fmt.Errorf("failed to create API client with supplied API token: %w", err)
}
if endpoint == "" {
endpoint = "https://api.binarylane.com.au/v2"
}
client, err := NewClientWithResponses(
endpoint,
WithRequestEditorFn(func(ctx context.Context, req *http.Request) error {
dump, err := httputil.DumpRequestOut(req, true)
if err != nil {
return err
}
tflog.Debug(ctx, fmt.Sprintf("%q\n", dump))
return nil
}),
WithRequestEditorFn(auth.Intercept), // include auth AFTER the request logger
)
if err != nil {
return nil, fmt.Errorf("failed to create Binary Lane API client: %w", err)
}
return client, nil
}
+9 -473
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.3.0 DO NOT EDIT.
// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.4.1 DO NOT EDIT.
package binarylane
import (
@@ -197,17 +197,6 @@ type ClientInterface interface {
union json.RawMessage
}, recordId int64, body PutDomainsDomainNameRecordsRecordIdJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error)
// GetFailoverIpsServerId request
GetFailoverIpsServerId(ctx context.Context, serverId int64, params *GetFailoverIpsServerIdParams, reqEditors ...RequestEditorFn) (*http.Response, error)
// PostFailoverIpsServerIdWithBody request with any body
PostFailoverIpsServerIdWithBody(ctx context.Context, serverId int64, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error)
PostFailoverIpsServerId(ctx context.Context, serverId int64, body PostFailoverIpsServerIdJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error)
// GetFailoverIpsServerIdAvailable request
GetFailoverIpsServerIdAvailable(ctx context.Context, serverId int64, params *GetFailoverIpsServerIdAvailableParams, reqEditors ...RequestEditorFn) (*http.Response, error)
// GetImages request
GetImages(ctx context.Context, params *GetImagesParams, reqEditors ...RequestEditorFn) (*http.Response, error)
@@ -987,54 +976,6 @@ func (c *Client) PutDomainsDomainNameRecordsRecordId(ctx context.Context, domain
return c.Client.Do(req)
}
func (c *Client) GetFailoverIpsServerId(ctx context.Context, serverId int64, params *GetFailoverIpsServerIdParams, reqEditors ...RequestEditorFn) (*http.Response, error) {
req, err := NewGetFailoverIpsServerIdRequest(c.Server, serverId, params)
if err != nil {
return nil, err
}
req = req.WithContext(ctx)
if err := c.applyEditors(ctx, req, reqEditors); err != nil {
return nil, err
}
return c.Client.Do(req)
}
func (c *Client) PostFailoverIpsServerIdWithBody(ctx context.Context, serverId int64, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) {
req, err := NewPostFailoverIpsServerIdRequestWithBody(c.Server, serverId, contentType, body)
if err != nil {
return nil, err
}
req = req.WithContext(ctx)
if err := c.applyEditors(ctx, req, reqEditors); err != nil {
return nil, err
}
return c.Client.Do(req)
}
func (c *Client) PostFailoverIpsServerId(ctx context.Context, serverId int64, body PostFailoverIpsServerIdJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) {
req, err := NewPostFailoverIpsServerIdRequest(c.Server, serverId, body)
if err != nil {
return nil, err
}
req = req.WithContext(ctx)
if err := c.applyEditors(ctx, req, reqEditors); err != nil {
return nil, err
}
return c.Client.Do(req)
}
func (c *Client) GetFailoverIpsServerIdAvailable(ctx context.Context, serverId int64, params *GetFailoverIpsServerIdAvailableParams, reqEditors ...RequestEditorFn) (*http.Response, error) {
req, err := NewGetFailoverIpsServerIdAvailableRequest(c.Server, serverId, params)
if err != nil {
return nil, err
}
req = req.WithContext(ctx)
if err := c.applyEditors(ctx, req, reqEditors); err != nil {
return nil, err
}
return c.Client.Do(req)
}
func (c *Client) GetImages(ctx context.Context, params *GetImagesParams, reqEditors ...RequestEditorFn) (*http.Response, error) {
req, err := NewGetImagesRequest(c.Server, params)
if err != nil {
@@ -3920,197 +3861,6 @@ func NewPutDomainsDomainNameRecordsRecordIdRequestWithBody(server string, domain
return req, nil
}
// NewGetFailoverIpsServerIdRequest generates requests for GetFailoverIpsServerId
func NewGetFailoverIpsServerIdRequest(server string, serverId int64, params *GetFailoverIpsServerIdParams) (*http.Request, error) {
var err error
var pathParam0 string
pathParam0, err = runtime.StyleParamWithLocation("simple", false, "server_id", runtime.ParamLocationPath, serverId)
if err != nil {
return nil, err
}
serverURL, err := url.Parse(server)
if err != nil {
return nil, err
}
operationPath := fmt.Sprintf("/failover_ips/%s", pathParam0)
if operationPath[0] == '/' {
operationPath = "." + operationPath
}
queryURL, err := serverURL.Parse(operationPath)
if err != nil {
return nil, err
}
if params != nil {
queryValues := queryURL.Query()
if params.Page != nil {
if queryFrag, err := runtime.StyleParamWithLocation("form", true, "page", runtime.ParamLocationQuery, *params.Page); err != nil {
return nil, err
} else if parsed, err := url.ParseQuery(queryFrag); err != nil {
return nil, err
} else {
for k, v := range parsed {
for _, v2 := range v {
queryValues.Add(k, v2)
}
}
}
}
if params.PerPage != nil {
if queryFrag, err := runtime.StyleParamWithLocation("form", true, "per_page", runtime.ParamLocationQuery, *params.PerPage); err != nil {
return nil, err
} else if parsed, err := url.ParseQuery(queryFrag); err != nil {
return nil, err
} else {
for k, v := range parsed {
for _, v2 := range v {
queryValues.Add(k, v2)
}
}
}
}
queryURL.RawQuery = queryValues.Encode()
}
req, err := http.NewRequest("GET", queryURL.String(), nil)
if err != nil {
return nil, err
}
return req, nil
}
// NewPostFailoverIpsServerIdRequest calls the generic PostFailoverIpsServerId builder with application/json body
func NewPostFailoverIpsServerIdRequest(server string, serverId int64, body PostFailoverIpsServerIdJSONRequestBody) (*http.Request, error) {
var bodyReader io.Reader
buf, err := json.Marshal(body)
if err != nil {
return nil, err
}
bodyReader = bytes.NewReader(buf)
return NewPostFailoverIpsServerIdRequestWithBody(server, serverId, "application/json", bodyReader)
}
// NewPostFailoverIpsServerIdRequestWithBody generates requests for PostFailoverIpsServerId with any type of body
func NewPostFailoverIpsServerIdRequestWithBody(server string, serverId int64, contentType string, body io.Reader) (*http.Request, error) {
var err error
var pathParam0 string
pathParam0, err = runtime.StyleParamWithLocation("simple", false, "server_id", runtime.ParamLocationPath, serverId)
if err != nil {
return nil, err
}
serverURL, err := url.Parse(server)
if err != nil {
return nil, err
}
operationPath := fmt.Sprintf("/failover_ips/%s", pathParam0)
if operationPath[0] == '/' {
operationPath = "." + operationPath
}
queryURL, err := serverURL.Parse(operationPath)
if err != nil {
return nil, err
}
req, err := http.NewRequest("POST", queryURL.String(), body)
if err != nil {
return nil, err
}
req.Header.Add("Content-Type", contentType)
return req, nil
}
// NewGetFailoverIpsServerIdAvailableRequest generates requests for GetFailoverIpsServerIdAvailable
func NewGetFailoverIpsServerIdAvailableRequest(server string, serverId int64, params *GetFailoverIpsServerIdAvailableParams) (*http.Request, error) {
var err error
var pathParam0 string
pathParam0, err = runtime.StyleParamWithLocation("simple", false, "server_id", runtime.ParamLocationPath, serverId)
if err != nil {
return nil, err
}
serverURL, err := url.Parse(server)
if err != nil {
return nil, err
}
operationPath := fmt.Sprintf("/failover_ips/%s/available", pathParam0)
if operationPath[0] == '/' {
operationPath = "." + operationPath
}
queryURL, err := serverURL.Parse(operationPath)
if err != nil {
return nil, err
}
if params != nil {
queryValues := queryURL.Query()
if params.Page != nil {
if queryFrag, err := runtime.StyleParamWithLocation("form", true, "page", runtime.ParamLocationQuery, *params.Page); err != nil {
return nil, err
} else if parsed, err := url.ParseQuery(queryFrag); err != nil {
return nil, err
} else {
for k, v := range parsed {
for _, v2 := range v {
queryValues.Add(k, v2)
}
}
}
}
if params.PerPage != nil {
if queryFrag, err := runtime.StyleParamWithLocation("form", true, "per_page", runtime.ParamLocationQuery, *params.PerPage); err != nil {
return nil, err
} else if parsed, err := url.ParseQuery(queryFrag); err != nil {
return nil, err
} else {
for k, v := range parsed {
for _, v2 := range v {
queryValues.Add(k, v2)
}
}
}
}
queryURL.RawQuery = queryValues.Encode()
}
req, err := http.NewRequest("GET", queryURL.String(), nil)
if err != nil {
return nil, err
}
return req, nil
}
// NewGetImagesRequest generates requests for GetImages
func NewGetImagesRequest(server string, params *GetImagesParams) (*http.Request, error) {
var err error
@@ -8665,17 +8415,6 @@ type ClientWithResponsesInterface interface {
union json.RawMessage
}, recordId int64, body PutDomainsDomainNameRecordsRecordIdJSONRequestBody, reqEditors ...RequestEditorFn) (*PutDomainsDomainNameRecordsRecordIdResponse, error)
// GetFailoverIpsServerIdWithResponse request
GetFailoverIpsServerIdWithResponse(ctx context.Context, serverId int64, params *GetFailoverIpsServerIdParams, reqEditors ...RequestEditorFn) (*GetFailoverIpsServerIdResponse, error)
// PostFailoverIpsServerIdWithBodyWithResponse request with any body
PostFailoverIpsServerIdWithBodyWithResponse(ctx context.Context, serverId int64, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostFailoverIpsServerIdResponse, error)
PostFailoverIpsServerIdWithResponse(ctx context.Context, serverId int64, body PostFailoverIpsServerIdJSONRequestBody, reqEditors ...RequestEditorFn) (*PostFailoverIpsServerIdResponse, error)
// GetFailoverIpsServerIdAvailableWithResponse request
GetFailoverIpsServerIdAvailableWithResponse(ctx context.Context, serverId int64, params *GetFailoverIpsServerIdAvailableParams, reqEditors ...RequestEditorFn) (*GetFailoverIpsServerIdAvailableResponse, error)
// GetImagesWithResponse request
GetImagesWithResponse(ctx context.Context, params *GetImagesParams, reqEditors ...RequestEditorFn) (*GetImagesResponse, error)
@@ -9641,76 +9380,6 @@ func (r PutDomainsDomainNameRecordsRecordIdResponse) StatusCode() int {
return 0
}
type GetFailoverIpsServerIdResponse struct {
Body []byte
HTTPResponse *http.Response
JSON200 *FailoverIpsResponse
JSON404 *ProblemDetails
}
// Status returns HTTPResponse.Status
func (r GetFailoverIpsServerIdResponse) Status() string {
if r.HTTPResponse != nil {
return r.HTTPResponse.Status
}
return http.StatusText(0)
}
// StatusCode returns HTTPResponse.StatusCode
func (r GetFailoverIpsServerIdResponse) StatusCode() int {
if r.HTTPResponse != nil {
return r.HTTPResponse.StatusCode
}
return 0
}
type PostFailoverIpsServerIdResponse struct {
Body []byte
HTTPResponse *http.Response
JSON200 *ActionResponse
JSON400 *ValidationProblemDetails
JSON404 *ProblemDetails
}
// Status returns HTTPResponse.Status
func (r PostFailoverIpsServerIdResponse) Status() string {
if r.HTTPResponse != nil {
return r.HTTPResponse.Status
}
return http.StatusText(0)
}
// StatusCode returns HTTPResponse.StatusCode
func (r PostFailoverIpsServerIdResponse) StatusCode() int {
if r.HTTPResponse != nil {
return r.HTTPResponse.StatusCode
}
return 0
}
type GetFailoverIpsServerIdAvailableResponse struct {
Body []byte
HTTPResponse *http.Response
JSON200 *FailoverIpsResponse
JSON404 *ProblemDetails
}
// Status returns HTTPResponse.Status
func (r GetFailoverIpsServerIdAvailableResponse) Status() string {
if r.HTTPResponse != nil {
return r.HTTPResponse.Status
}
return http.StatusText(0)
}
// StatusCode returns HTTPResponse.StatusCode
func (r GetFailoverIpsServerIdAvailableResponse) StatusCode() int {
if r.HTTPResponse != nil {
return r.HTTPResponse.StatusCode
}
return 0
}
type GetImagesResponse struct {
Body []byte
HTTPResponse *http.Response
@@ -9761,6 +9430,7 @@ type GetImagesImageIdDownloadResponse struct {
Body []byte
HTTPResponse *http.Response
JSON200 *ImageDownloadResponse
JSON400 *ValidationProblemDetails
JSON404 *ProblemDetails
}
@@ -12123,41 +11793,6 @@ func (c *ClientWithResponses) PutDomainsDomainNameRecordsRecordIdWithResponse(ct
return ParsePutDomainsDomainNameRecordsRecordIdResponse(rsp)
}
// GetFailoverIpsServerIdWithResponse request returning *GetFailoverIpsServerIdResponse
func (c *ClientWithResponses) GetFailoverIpsServerIdWithResponse(ctx context.Context, serverId int64, params *GetFailoverIpsServerIdParams, reqEditors ...RequestEditorFn) (*GetFailoverIpsServerIdResponse, error) {
rsp, err := c.GetFailoverIpsServerId(ctx, serverId, params, reqEditors...)
if err != nil {
return nil, err
}
return ParseGetFailoverIpsServerIdResponse(rsp)
}
// PostFailoverIpsServerIdWithBodyWithResponse request with arbitrary body returning *PostFailoverIpsServerIdResponse
func (c *ClientWithResponses) PostFailoverIpsServerIdWithBodyWithResponse(ctx context.Context, serverId int64, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostFailoverIpsServerIdResponse, error) {
rsp, err := c.PostFailoverIpsServerIdWithBody(ctx, serverId, contentType, body, reqEditors...)
if err != nil {
return nil, err
}
return ParsePostFailoverIpsServerIdResponse(rsp)
}
func (c *ClientWithResponses) PostFailoverIpsServerIdWithResponse(ctx context.Context, serverId int64, body PostFailoverIpsServerIdJSONRequestBody, reqEditors ...RequestEditorFn) (*PostFailoverIpsServerIdResponse, error) {
rsp, err := c.PostFailoverIpsServerId(ctx, serverId, body, reqEditors...)
if err != nil {
return nil, err
}
return ParsePostFailoverIpsServerIdResponse(rsp)
}
// GetFailoverIpsServerIdAvailableWithResponse request returning *GetFailoverIpsServerIdAvailableResponse
func (c *ClientWithResponses) GetFailoverIpsServerIdAvailableWithResponse(ctx context.Context, serverId int64, params *GetFailoverIpsServerIdAvailableParams, reqEditors ...RequestEditorFn) (*GetFailoverIpsServerIdAvailableResponse, error) {
rsp, err := c.GetFailoverIpsServerIdAvailable(ctx, serverId, params, reqEditors...)
if err != nil {
return nil, err
}
return ParseGetFailoverIpsServerIdAvailableResponse(rsp)
}
// GetImagesWithResponse request returning *GetImagesResponse
func (c *ClientWithResponses) GetImagesWithResponse(ctx context.Context, params *GetImagesParams, reqEditors ...RequestEditorFn) (*GetImagesResponse, error) {
rsp, err := c.GetImages(ctx, params, reqEditors...)
@@ -14171,112 +13806,6 @@ func ParsePutDomainsDomainNameRecordsRecordIdResponse(rsp *http.Response) (*PutD
return response, nil
}
// ParseGetFailoverIpsServerIdResponse parses an HTTP response from a GetFailoverIpsServerIdWithResponse call
func ParseGetFailoverIpsServerIdResponse(rsp *http.Response) (*GetFailoverIpsServerIdResponse, error) {
bodyBytes, err := io.ReadAll(rsp.Body)
defer func() { _ = rsp.Body.Close() }()
if err != nil {
return nil, err
}
response := &GetFailoverIpsServerIdResponse{
Body: bodyBytes,
HTTPResponse: rsp,
}
switch {
case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200:
var dest FailoverIpsResponse
if err := json.Unmarshal(bodyBytes, &dest); err != nil {
return nil, err
}
response.JSON200 = &dest
case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 404:
var dest ProblemDetails
if err := json.Unmarshal(bodyBytes, &dest); err != nil {
return nil, err
}
response.JSON404 = &dest
}
return response, nil
}
// ParsePostFailoverIpsServerIdResponse parses an HTTP response from a PostFailoverIpsServerIdWithResponse call
func ParsePostFailoverIpsServerIdResponse(rsp *http.Response) (*PostFailoverIpsServerIdResponse, error) {
bodyBytes, err := io.ReadAll(rsp.Body)
defer func() { _ = rsp.Body.Close() }()
if err != nil {
return nil, err
}
response := &PostFailoverIpsServerIdResponse{
Body: bodyBytes,
HTTPResponse: rsp,
}
switch {
case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200:
var dest ActionResponse
if err := json.Unmarshal(bodyBytes, &dest); err != nil {
return nil, err
}
response.JSON200 = &dest
case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400:
var dest ValidationProblemDetails
if err := json.Unmarshal(bodyBytes, &dest); err != nil {
return nil, err
}
response.JSON400 = &dest
case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 404:
var dest ProblemDetails
if err := json.Unmarshal(bodyBytes, &dest); err != nil {
return nil, err
}
response.JSON404 = &dest
}
return response, nil
}
// ParseGetFailoverIpsServerIdAvailableResponse parses an HTTP response from a GetFailoverIpsServerIdAvailableWithResponse call
func ParseGetFailoverIpsServerIdAvailableResponse(rsp *http.Response) (*GetFailoverIpsServerIdAvailableResponse, error) {
bodyBytes, err := io.ReadAll(rsp.Body)
defer func() { _ = rsp.Body.Close() }()
if err != nil {
return nil, err
}
response := &GetFailoverIpsServerIdAvailableResponse{
Body: bodyBytes,
HTTPResponse: rsp,
}
switch {
case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200:
var dest FailoverIpsResponse
if err := json.Unmarshal(bodyBytes, &dest); err != nil {
return nil, err
}
response.JSON200 = &dest
case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 404:
var dest ProblemDetails
if err := json.Unmarshal(bodyBytes, &dest); err != nil {
return nil, err
}
response.JSON404 = &dest
}
return response, nil
}
// ParseGetImagesResponse parses an HTTP response from a GetImagesWithResponse call
func ParseGetImagesResponse(rsp *http.Response) (*GetImagesResponse, error) {
bodyBytes, err := io.ReadAll(rsp.Body)
@@ -14364,6 +13893,13 @@ func ParseGetImagesImageIdDownloadResponse(rsp *http.Response) (*GetImagesImageI
}
response.JSON200 = &dest
case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400:
var dest ValidationProblemDetails
if err := json.Unmarshal(bodyBytes, &dest); err != nil {
return nil, err
}
response.JSON400 = &dest
case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 404:
var dest ProblemDetails
if err := json.Unmarshal(bodyBytes, &dest); err != nil {
+4
View File
@@ -12,6 +12,9 @@ cat <<<$(jq '.paths |= with_entries(.key |= sub("/v2/"; "/"))' $OPENAPI_FILE) >$
# Terraform can't handle oneOf types, so we need to replace them with basic types
cat <<<$(jq '.components.schemas.CreateServerRequest.properties.image |= del(.oneOf) + {type:"string"}' $OPENAPI_FILE) >$OPENAPI_FILE
cat <<<$(jq '.components.schemas.CreateServerRequest.properties.ssh_keys.items |= del(.oneOf) + {type:"integer"}' $OPENAPI_FILE) >$OPENAPI_FILE
cat <<<$(jq '.components.schemas.Rebuild.properties.image |= del(.oneOf) + {type:"string"}' $OPENAPI_FILE) >$OPENAPI_FILE
cat <<<$(jq '.components.schemas.ImageOptions.properties.ssh_keys.items |= del(.oneOf) + {type:"integer"}' $OPENAPI_FILE) >$OPENAPI_FILE
cat <<<$(jq '.components.schemas.ChangeImage.properties.image |= del(.oneOf) + {type:"string"}' $OPENAPI_FILE) >$OPENAPI_FILE
cat <<<$(jq '.paths["/account/keys/{key_id}"].delete.parameters[0].schema |= del(.oneOf) + {type:"integer"}' $OPENAPI_FILE) >$OPENAPI_FILE
cat <<<$(jq '.paths["/account/keys/{key_id}"].put.parameters[0].schema |= del(.oneOf) + {type:"integer"}' $OPENAPI_FILE) >$OPENAPI_FILE
cat <<<$(jq '.paths["/account/keys/{key_id}"].get.parameters[0].schema |= del(.oneOf) + {type:"integer"}' $OPENAPI_FILE) >$OPENAPI_FILE
@@ -39,4 +42,5 @@ cat <<<$(jq '.components.schemas.AdvancedFirewallRule.properties.source_addresse
## 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.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
+22 -314
View File
@@ -8,7 +8,7 @@
"url": "https://support.binarylane.com.au",
"email": "support@binarylane.com.au"
},
"version": "0.25.0",
"version": "0.26.0",
"x-logo": {
"url": "https://www.binarylane.com.au/res/images/binarylane/logo.png",
"backgroundColor": "#000000",
@@ -1200,242 +1200,6 @@
"x-cli-command": "domain record delete"
}
},
"/failover_ips/{server_id}": {
"get": {
"tags": [
"FailoverIps"
],
"summary": "Fetch the Failover IPs for a Server",
"parameters": [
{
"name": "server_id",
"in": "path",
"description": "The target server id.",
"required": true,
"schema": {
"type": "integer",
"description": "The target server id.",
"format": "int64"
}
},
{
"name": "page",
"in": "query",
"description": "The selected page. Page numbering starts at 1",
"schema": {
"maximum": 2147483647,
"minimum": 1,
"type": "integer",
"description": "The selected page. Page numbering starts at 1",
"format": "int32",
"default": 1
}
},
{
"name": "per_page",
"in": "query",
"description": "The number of results to show per page.",
"schema": {
"maximum": 200,
"minimum": 1,
"type": "integer",
"description": "The number of results to show per page.",
"format": "int32",
"default": 20
}
}
],
"responses": {
"200": {
"description": "Success",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/FailoverIpsResponse"
}
}
}
},
"404": {
"description": "Not Found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
}
}
},
"401": {
"description": "Unauthorized"
}
},
"x-codeSamples": [
{
"lang": "Curl",
"source": "curl -X GET \"https://api.binarylane.com.au/v2/failover_ips/${server_id}?page=${page}&per_page=${per_page}\" \\\n-H \"Authorization: Bearer ${APITOKEN}\""
}
],
"x-cli-command": "server failover-ip get"
},
"post": {
"tags": [
"FailoverIps"
],
"summary": "Sets the List of Failover IPs that are Assigned to a Server",
"description": "This overwrites the current list, i.e. submit the entire list, not just updates.\nIf NoContent is returned no changes were made.\nIf an action is returned the changes have been saved but the effect may not be complete until the action is complete. If the action does not complete the network changes can be forced by rebooting the server.",
"parameters": [
{
"name": "server_id",
"in": "path",
"description": "The target server id.",
"required": true,
"schema": {
"type": "integer",
"description": "The target server id.",
"format": "int64"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"allOf": [
{
"$ref": "#/components/schemas/FailoverIpsRequest"
}
]
}
}
}
},
"responses": {
"200": {
"description": "Success",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ActionResponse"
}
}
}
},
"204": {
"description": "No Content"
},
"400": {
"description": "Bad Request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ValidationProblemDetails"
}
}
}
},
"404": {
"description": "Not Found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
}
}
},
"401": {
"description": "Unauthorized"
}
},
"x-codeSamples": [
{
"lang": "Curl",
"source": "curl -X POST \"https://api.binarylane.com.au/v2/failover_ips/${server_id}\" \\\n-H \"Authorization: Bearer ${APITOKEN}\" \\\n-H \"Content-Type: application/json\" -d \"${PAYLOAD}\""
}
],
"x-cli-command": "server failover-ip update"
}
},
"/failover_ips/{server_id}/available": {
"get": {
"tags": [
"FailoverIps"
],
"summary": "Fetch a List of all Failover IPs that are Available to be Assigned to a Server",
"parameters": [
{
"name": "server_id",
"in": "path",
"description": "The target server id.",
"required": true,
"schema": {
"type": "integer",
"description": "The target server id.",
"format": "int64"
}
},
{
"name": "page",
"in": "query",
"description": "The selected page. Page numbering starts at 1",
"schema": {
"maximum": 2147483647,
"minimum": 1,
"type": "integer",
"description": "The selected page. Page numbering starts at 1",
"format": "int32",
"default": 1
}
},
{
"name": "per_page",
"in": "query",
"description": "The number of results to show per page.",
"schema": {
"maximum": 200,
"minimum": 1,
"type": "integer",
"description": "The number of results to show per page.",
"format": "int32",
"default": 20
}
}
],
"responses": {
"200": {
"description": "Success",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/FailoverIpsResponse"
}
}
}
},
"404": {
"description": "Not Found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
}
}
},
"401": {
"description": "Unauthorized"
}
},
"x-codeSamples": [
{
"lang": "Curl",
"source": "curl -X GET \"https://api.binarylane.com.au/v2/failover_ips/${server_id}/available?page=${page}&per_page=${per_page}\" \\\n-H \"Authorization: Bearer ${APITOKEN}\""
}
],
"x-cli-command": "server failover-ip available"
}
},
"/images": {
"get": {
"tags": [
@@ -1613,6 +1377,16 @@
}
}
},
"400": {
"description": "Bad Request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ValidationProblemDetails"
}
}
}
},
"404": {
"description": "Not Found",
"content": {
@@ -9199,7 +8973,7 @@
},
"iso": {
"type": "boolean",
"description": "If this is true the backup is an ISO image and cannot be restored. ISO images may only be attached for use as a boot disk or an additional disk.",
"description": "If this is true the backup is an ISO image and cannot be restored or downloaded. ISO images may only be attached for use as a boot disk or an additional disk.",
"readOnly": true
},
"backup_disks": {
@@ -9514,17 +9288,10 @@
"type": "object",
"properties": {
"image": {
"oneOf": [
{
"type": "integer"
},
{
"type": "string"
}
],
"description": "The slug or ID of the selected image. What type of image is permitted here varies based on the server action.",
"nullable": true,
"example": 5
"example": 5,
"type": "string"
},
"options": {
"allOf": [
@@ -10942,53 +10709,6 @@
},
"description": "Enable IPv6 for a Server"
},
"FailoverIpsRequest": {
"required": [
"failover_ips"
],
"type": "object",
"properties": {
"failover_ips": {
"type": "array",
"items": {
"type": "string"
},
"description": "The list of IP Failover addresses to assign to this server. This overwrites the current list, so any current IP Failover addresses that are omitted will be removed from the server."
}
}
},
"FailoverIpsResponse": {
"required": [
"failover_ips",
"meta"
],
"type": "object",
"properties": {
"meta": {
"allOf": [
{
"$ref": "#/components/schemas/Meta"
}
],
"description": "Contains metadata about the response, currently this includes the total number of items."
},
"links": {
"allOf": [
{
"$ref": "#/components/schemas/Links"
}
],
"nullable": true
},
"failover_ips": {
"type": "array",
"items": {
"type": "string"
},
"readOnly": true
}
}
},
"ForwardingRule": {
"required": [
"entry_protocol"
@@ -11306,15 +11026,8 @@
"ssh_keys": {
"type": "array",
"items": {
"oneOf": [
{
"type": "integer"
},
{
"type": "string"
}
],
"example": 5
"example": 5,
"type": "integer"
},
"description": "This may be either the existing SSH Keys IDs or fingerprints.\nIf this is null or not provided any SSH keys that have been marked as default will be deployed (if the operating system supports SSH Keys).\nSubmit an empty array to disable deployment of default keys.",
"nullable": true
@@ -11845,7 +11558,10 @@
}
],
"description": "The rules that determine which servers are considered 'healthy' and in the server pool for the load balancer.",
"readOnly": true
"readOnly": true,
"x-oapi-codegen-extra-tags": {
"tfsdk": "health_check"
}
},
"region": {
"allOf": [
@@ -12488,17 +12204,10 @@
"type": "string"
},
"image": {
"oneOf": [
{
"type": "integer"
},
{
"type": "string"
}
],
"description": "The Operating System ID or slug or Backup image ID to use as a base for the rebuild.",
"nullable": true,
"example": 5
"example": 5,
"type": "string"
},
"options": {
"allOf": [
@@ -15026,7 +14735,6 @@
"ServerActions",
"Actions",
"DataUsages",
"FailoverIps",
"Images",
"Keys",
"ReverseNames",
+6 -264
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.3.0 DO NOT EDIT.
// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.4.1 DO NOT EDIT.
package binarylane
import (
@@ -714,7 +714,7 @@ type BackupInfo struct {
// BackupDisks A list of the individual disks that make up this backup.
BackupDisks *[]BackupDisk `json:"backup_disks,omitempty"`
// Iso If this is true the backup is an ISO image and cannot be restored. ISO images may only be attached for use as a boot disk or an additional disk.
// Iso If this is true the backup is an ISO image and cannot be restored or downloaded. ISO images may only be attached for use as a boot disk or an additional disk.
Iso *bool `json:"iso,omitempty"`
// Locked If this is true the backup is locked and cannot be replaced.
@@ -854,23 +854,12 @@ type ChangeBackupScheduleType string
// ChangeImage defines model for ChangeImage.
type ChangeImage struct {
// Image The slug or ID of the selected image. What type of image is permitted here varies based on the server action.
Image *ChangeImage_Image `json:"image"`
Image *string `json:"image"`
// Options Additional options for the server configuration after the image has been changed.
Options *ImageOptions `json:"options"`
}
// ChangeImageImage0 defines model for .
type ChangeImageImage0 = int
// ChangeImageImage1 defines model for .
type ChangeImageImage1 = string
// ChangeImage_Image The slug or ID of the selected image. What type of image is permitted here varies based on the server action.
type ChangeImage_Image struct {
union json.RawMessage
}
// ChangeIpv6 Enable or Disable IPv6 for a Server
type ChangeIpv6 struct {
// Enabled The desired enabled status of IPv6.
@@ -1513,21 +1502,6 @@ type EnableIpv6 struct {
// EnableIpv6Type defines model for EnableIpv6.Type.
type EnableIpv6Type string
// FailoverIpsRequest defines model for FailoverIpsRequest.
type FailoverIpsRequest struct {
// FailoverIps The list of IP Failover addresses to assign to this server. This overwrites the current list, so any current IP Failover addresses that are omitted will be removed from the server.
FailoverIps []string `json:"failover_ips"`
}
// FailoverIpsResponse defines model for FailoverIpsResponse.
type FailoverIpsResponse struct {
FailoverIps *[]string `json:"failover_ips,omitempty"`
Links *Links `json:"links"`
// Meta Contains metadata about the response, currently this includes the total number of items.
Meta Meta `json:"meta"`
}
// ForwardingRule defines model for ForwardingRule.
type ForwardingRule struct {
// EntryProtocol The protocol that traffic must match for this load balancer to forward traffic according to this rule.
@@ -1662,23 +1636,12 @@ type ImageOptions struct {
// SshKeys This may be either the existing SSH Keys IDs or fingerprints.
// If this is null or not provided any SSH keys that have been marked as default will be deployed (if the operating system supports SSH Keys).
// Submit an empty array to disable deployment of default keys.
SshKeys *[]ImageOptions_SshKeys_Item `json:"ssh_keys"`
SshKeys *[]int `json:"ssh_keys"`
// UserData If provided this will be used to initialise the new server. This must be left null if the Image does not support UserData, see DistributionInfo.Features for more information.
UserData *string `json:"user_data"`
}
// ImageOptionsSshKeys0 defines model for .
type ImageOptionsSshKeys0 = int
// ImageOptionsSshKeys1 defines model for .
type ImageOptionsSshKeys1 = string
// ImageOptions_SshKeys_Item defines model for ImageOptions.ssh_keys.Item.
type ImageOptions_SshKeys_Item struct {
union json.RawMessage
}
// ImageQueryType
// | Value | Description |
// | ----- | ----------- |
@@ -1860,7 +1823,7 @@ type LoadBalancer struct {
ForwardingRules *[]ForwardingRule `json:"forwarding_rules,omitempty"`
// 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"`
HealthCheck *HealthCheck `json:"health_check,omitempty" tfsdk:"health_check"`
// Id The ID of the load balancer.
Id *int64 `json:"id,omitempty"`
@@ -2176,24 +2139,13 @@ type RebootType string
// Rebuild Rebuild an Existing Server
type Rebuild struct {
// Image The Operating System ID or slug or Backup image ID to use as a base for the rebuild.
Image *Rebuild_Image `json:"image"`
Image *string `json:"image"`
// Options Additional options. Leaving this entirely null or any of the properties included null will use the defaults from the existing server.
Options *ImageOptions `json:"options"`
Type RebuildType `json:"type"`
}
// RebuildImage0 defines model for .
type RebuildImage0 = int
// RebuildImage1 defines model for .
type RebuildImage1 = string
// Rebuild_Image The Operating System ID or slug or Backup image ID to use as a base for the rebuild.
type Rebuild_Image struct {
union json.RawMessage
}
// RebuildType defines model for Rebuild.Type.
type RebuildType string
@@ -3247,27 +3199,6 @@ type PutDomainsDomainNameRecordsRecordIdParamsDomainName0 = int
// PutDomainsDomainNameRecordsRecordIdParamsDomainName1 defines parameters for PutDomainsDomainNameRecordsRecordId.
type PutDomainsDomainNameRecordsRecordIdParamsDomainName1 = string
// GetFailoverIpsServerIdParams defines parameters for GetFailoverIpsServerId.
type GetFailoverIpsServerIdParams struct {
// Page The selected page. Page numbering starts at 1
Page *int32 `form:"page,omitempty" json:"page,omitempty"`
// PerPage The number of results to show per page.
PerPage *int32 `form:"per_page,omitempty" json:"per_page,omitempty"`
}
// PostFailoverIpsServerIdJSONBody defines parameters for PostFailoverIpsServerId.
type PostFailoverIpsServerIdJSONBody = FailoverIpsRequest
// GetFailoverIpsServerIdAvailableParams defines parameters for GetFailoverIpsServerIdAvailable.
type GetFailoverIpsServerIdAvailableParams struct {
// Page The selected page. Page numbering starts at 1
Page *int32 `form:"page,omitempty" json:"page,omitempty"`
// PerPage The number of results to show per page.
PerPage *int32 `form:"per_page,omitempty" json:"per_page,omitempty"`
}
// GetImagesParams defines parameters for GetImages.
type GetImagesParams struct {
// Type Queries for distribution will include images that have pre-installed applications.
@@ -3555,9 +3486,6 @@ type PostDomainsDomainNameRecordsJSONRequestBody = PostDomainsDomainNameRecordsJ
// PutDomainsDomainNameRecordsRecordIdJSONRequestBody defines body for PutDomainsDomainNameRecordsRecordId for application/json ContentType.
type PutDomainsDomainNameRecordsRecordIdJSONRequestBody = PutDomainsDomainNameRecordsRecordIdJSONBody
// PostFailoverIpsServerIdJSONRequestBody defines body for PostFailoverIpsServerId for application/json ContentType.
type PostFailoverIpsServerIdJSONRequestBody = PostFailoverIpsServerIdJSONBody
// PostLoadBalancersJSONRequestBody defines body for PostLoadBalancers for application/json ContentType.
type PostLoadBalancersJSONRequestBody = PostLoadBalancersJSONBody
@@ -3985,130 +3913,6 @@ func (a ValidationProblemDetails) MarshalJSON() ([]byte, error) {
return json.Marshal(object)
}
// AsChangeImageImage0 returns the union data inside the ChangeImage_Image as a ChangeImageImage0
func (t ChangeImage_Image) AsChangeImageImage0() (ChangeImageImage0, error) {
var body ChangeImageImage0
err := json.Unmarshal(t.union, &body)
return body, err
}
// FromChangeImageImage0 overwrites any union data inside the ChangeImage_Image as the provided ChangeImageImage0
func (t *ChangeImage_Image) FromChangeImageImage0(v ChangeImageImage0) error {
b, err := json.Marshal(v)
t.union = b
return err
}
// MergeChangeImageImage0 performs a merge with any union data inside the ChangeImage_Image, using the provided ChangeImageImage0
func (t *ChangeImage_Image) MergeChangeImageImage0(v ChangeImageImage0) error {
b, err := json.Marshal(v)
if err != nil {
return err
}
merged, err := runtime.JSONMerge(t.union, b)
t.union = merged
return err
}
// AsChangeImageImage1 returns the union data inside the ChangeImage_Image as a ChangeImageImage1
func (t ChangeImage_Image) AsChangeImageImage1() (ChangeImageImage1, error) {
var body ChangeImageImage1
err := json.Unmarshal(t.union, &body)
return body, err
}
// FromChangeImageImage1 overwrites any union data inside the ChangeImage_Image as the provided ChangeImageImage1
func (t *ChangeImage_Image) FromChangeImageImage1(v ChangeImageImage1) error {
b, err := json.Marshal(v)
t.union = b
return err
}
// MergeChangeImageImage1 performs a merge with any union data inside the ChangeImage_Image, using the provided ChangeImageImage1
func (t *ChangeImage_Image) MergeChangeImageImage1(v ChangeImageImage1) error {
b, err := json.Marshal(v)
if err != nil {
return err
}
merged, err := runtime.JSONMerge(t.union, b)
t.union = merged
return err
}
func (t ChangeImage_Image) MarshalJSON() ([]byte, error) {
b, err := t.union.MarshalJSON()
return b, err
}
func (t *ChangeImage_Image) UnmarshalJSON(b []byte) error {
err := t.union.UnmarshalJSON(b)
return err
}
// AsImageOptionsSshKeys0 returns the union data inside the ImageOptions_SshKeys_Item as a ImageOptionsSshKeys0
func (t ImageOptions_SshKeys_Item) AsImageOptionsSshKeys0() (ImageOptionsSshKeys0, error) {
var body ImageOptionsSshKeys0
err := json.Unmarshal(t.union, &body)
return body, err
}
// FromImageOptionsSshKeys0 overwrites any union data inside the ImageOptions_SshKeys_Item as the provided ImageOptionsSshKeys0
func (t *ImageOptions_SshKeys_Item) FromImageOptionsSshKeys0(v ImageOptionsSshKeys0) error {
b, err := json.Marshal(v)
t.union = b
return err
}
// MergeImageOptionsSshKeys0 performs a merge with any union data inside the ImageOptions_SshKeys_Item, using the provided ImageOptionsSshKeys0
func (t *ImageOptions_SshKeys_Item) MergeImageOptionsSshKeys0(v ImageOptionsSshKeys0) error {
b, err := json.Marshal(v)
if err != nil {
return err
}
merged, err := runtime.JSONMerge(t.union, b)
t.union = merged
return err
}
// AsImageOptionsSshKeys1 returns the union data inside the ImageOptions_SshKeys_Item as a ImageOptionsSshKeys1
func (t ImageOptions_SshKeys_Item) AsImageOptionsSshKeys1() (ImageOptionsSshKeys1, error) {
var body ImageOptionsSshKeys1
err := json.Unmarshal(t.union, &body)
return body, err
}
// FromImageOptionsSshKeys1 overwrites any union data inside the ImageOptions_SshKeys_Item as the provided ImageOptionsSshKeys1
func (t *ImageOptions_SshKeys_Item) FromImageOptionsSshKeys1(v ImageOptionsSshKeys1) error {
b, err := json.Marshal(v)
t.union = b
return err
}
// MergeImageOptionsSshKeys1 performs a merge with any union data inside the ImageOptions_SshKeys_Item, using the provided ImageOptionsSshKeys1
func (t *ImageOptions_SshKeys_Item) MergeImageOptionsSshKeys1(v ImageOptionsSshKeys1) error {
b, err := json.Marshal(v)
if err != nil {
return err
}
merged, err := runtime.JSONMerge(t.union, b)
t.union = merged
return err
}
func (t ImageOptions_SshKeys_Item) MarshalJSON() ([]byte, error) {
b, err := t.union.MarshalJSON()
return b, err
}
func (t *ImageOptions_SshKeys_Item) UnmarshalJSON(b []byte) error {
err := t.union.UnmarshalJSON(b)
return err
}
// AsNetworkNetmask0 returns the union data inside the Network_Netmask as a NetworkNetmask0
func (t Network_Netmask) AsNetworkNetmask0() (NetworkNetmask0, error) {
var body NetworkNetmask0
@@ -4171,68 +3975,6 @@ func (t *Network_Netmask) UnmarshalJSON(b []byte) error {
return err
}
// AsRebuildImage0 returns the union data inside the Rebuild_Image as a RebuildImage0
func (t Rebuild_Image) AsRebuildImage0() (RebuildImage0, error) {
var body RebuildImage0
err := json.Unmarshal(t.union, &body)
return body, err
}
// FromRebuildImage0 overwrites any union data inside the Rebuild_Image as the provided RebuildImage0
func (t *Rebuild_Image) FromRebuildImage0(v RebuildImage0) error {
b, err := json.Marshal(v)
t.union = b
return err
}
// MergeRebuildImage0 performs a merge with any union data inside the Rebuild_Image, using the provided RebuildImage0
func (t *Rebuild_Image) MergeRebuildImage0(v RebuildImage0) error {
b, err := json.Marshal(v)
if err != nil {
return err
}
merged, err := runtime.JSONMerge(t.union, b)
t.union = merged
return err
}
// AsRebuildImage1 returns the union data inside the Rebuild_Image as a RebuildImage1
func (t Rebuild_Image) AsRebuildImage1() (RebuildImage1, error) {
var body RebuildImage1
err := json.Unmarshal(t.union, &body)
return body, err
}
// FromRebuildImage1 overwrites any union data inside the Rebuild_Image as the provided RebuildImage1
func (t *Rebuild_Image) FromRebuildImage1(v RebuildImage1) error {
b, err := json.Marshal(v)
t.union = b
return err
}
// MergeRebuildImage1 performs a merge with any union data inside the Rebuild_Image, using the provided RebuildImage1
func (t *Rebuild_Image) MergeRebuildImage1(v RebuildImage1) error {
b, err := json.Marshal(v)
if err != nil {
return err
}
merged, err := runtime.JSONMerge(t.union, b)
t.union = merged
return err
}
func (t Rebuild_Image) MarshalJSON() ([]byte, error) {
b, err := t.union.MarshalJSON()
return b, err
}
func (t *Rebuild_Image) UnmarshalJSON(b []byte) error {
err := t.union.UnmarshalJSON(b)
return err
}
// AsRestoreImage0 returns the union data inside the Restore_Image as a RestoreImage0
func (t Restore_Image) AsRestoreImage0() (RestoreImage0, error) {
var body RestoreImage0
@@ -93,9 +93,9 @@ func (d *loadBalancerDataSource) Read(ctx context.Context, req datasource.ReadRe
return
}
diags := SetLoadBalancerModelState(ctx, &data.LoadBalancerModel, lbResp.JSON200.LoadBalancer)
diags := setLoadBalancerModelState(ctx, &data.LoadBalancerModel, lbResp.JSON200.LoadBalancer)
resp.Diagnostics.Append(diags...)
if diags.HasError() {
if resp.Diagnostics.HasError() {
return
}
+47 -29
View File
@@ -9,6 +9,7 @@ import (
"terraform-provider-binarylane/internal/resources"
"time"
"github.com/hashicorp/terraform-plugin-framework-timeouts/resource/timeouts"
"github.com/hashicorp/terraform-plugin-framework/attr"
"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-framework/path"
@@ -37,6 +38,7 @@ type loadBalancerResource struct {
type loadBalancerResourceModel struct {
resources.LoadBalancerModel
Timeouts timeouts.Value `tfsdk:"timeouts"`
}
func (r *loadBalancerResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
@@ -86,6 +88,11 @@ func (r *loadBalancerResource) Schema(ctx context.Context, req resource.SchemaRe
stringplanmodifier.RequiresReplace(),
},
}
resp.Schema.Attributes["timeouts"] =
timeouts.Attributes(ctx, timeouts.Opts{
Create: true,
})
}
func (r *loadBalancerResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
@@ -137,18 +144,17 @@ func (r *loadBalancerResource) Create(ctx context.Context, req resource.CreateRe
)
return
}
if lbResp.StatusCode() != http.StatusOK {
tflog.Info(ctx, fmt.Sprintf("Attempted to create new load balancer: request=%+v", body))
resp.Diagnostics.AddError(
"Unexpected HTTP status code creating load balancer",
fmt.Sprintf("Received %s creating new load balancer: name=%s. Details: %s", lbResp.Status(), data.Name.ValueString(), lbResp.Body))
"Unexpected status code creating load balancer",
fmt.Sprintf("Received %s creating new load balancer: name=%s. Details: %s", lbResp.Status(), data.Name.ValueString(), lbResp.Body),
)
return
}
diags = SetLoadBalancerModelState(ctx, &data.LoadBalancerModel, lbResp.JSON200.LoadBalancer)
diags = setLoadBalancerModelState(ctx, &data.LoadBalancerModel, lbResp.JSON200.LoadBalancer)
resp.Diagnostics.Append(diags...)
if diags.HasError() {
if resp.Diagnostics.HasError() {
return
}
@@ -170,31 +176,43 @@ func (r *loadBalancerResource) Create(ctx context.Context, req resource.CreateRe
return
}
timeLimit := time.Now().Add(time.Duration(60 * time.Second))
for {
tflog.Info(ctx, "Waiting for load balancer to be ready...")
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
readyResp, err := r.bc.client.GetActionsActionIdWithResponse(ctx, createActionId)
if err != nil {
resp.Diagnostics.AddError("Error waiting for load balancer to be ready", err.Error())
return
}
if readyResp.StatusCode() == http.StatusOK && readyResp.JSON200.Action.CompletedAt != nil {
tflog.Info(ctx, "Load balancer is ready")
break
}
if time.Now().After(timeLimit) {
retryLoop:
for {
select {
case <-ctx.Done():
if lastReadyResp == nil {
return
}
resp.Diagnostics.AddError(
"Timed out waiting for load balancer to be ready",
"Timed out waiting for load balancer to be created",
fmt.Sprintf(
"Timed out waiting for load balancer to be created, as `wait_for_create` was surpassed without "+
"recieving a `completed_at` in response: name=%s, status=%s, details: %s",
data.Name.ValueString(), readyResp.Status(), readyResp.Body,
"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))
}
tflog.Debug(ctx, fmt.Sprintf("Waiting for load balancer to be ready: name=%s, status=%s, details: %s", data.Name.ValueString(), readyResp.Status(), readyResp.Body))
time.Sleep(time.Second * 5)
}
}
@@ -227,9 +245,9 @@ func (r *loadBalancerResource) Read(ctx context.Context, req resource.ReadReques
return
}
diags := SetLoadBalancerModelState(ctx, &data.LoadBalancerModel, lbResp.JSON200.LoadBalancer)
diags := setLoadBalancerModelState(ctx, &data.LoadBalancerModel, lbResp.JSON200.LoadBalancer)
resp.Diagnostics.Append(diags...)
if diags.HasError() {
if resp.Diagnostics.HasError() {
return
}
@@ -291,9 +309,9 @@ func (r *loadBalancerResource) Update(ctx context.Context, req resource.UpdateRe
return
}
diags = SetLoadBalancerModelState(ctx, &data.LoadBalancerModel, lbResp.JSON200.LoadBalancer)
diags = setLoadBalancerModelState(ctx, &data.LoadBalancerModel, lbResp.JSON200.LoadBalancer)
resp.Diagnostics.Append(diags...)
if diags.HasError() {
if resp.Diagnostics.HasError() {
return
}
@@ -396,7 +414,7 @@ func (r *loadBalancerResource) ImportState(
resp.Diagnostics.Append(diags...)
}
func SetLoadBalancerModelState(ctx context.Context, data *resources.LoadBalancerModel, lb *binarylane.LoadBalancer) diag.Diagnostics {
func setLoadBalancerModelState(ctx context.Context, data *resources.LoadBalancerModel, lb *binarylane.LoadBalancer) diag.Diagnostics {
var diags, diag diag.Diagnostics
data.Id = types.Int64Value(*lb.Id)
@@ -1,8 +1,14 @@
package provider
import (
"context"
"crypto/rand"
"encoding/base64"
"fmt"
"log"
"net/http"
"strings"
"terraform-provider-binarylane/internal/binarylane"
"testing"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
@@ -25,25 +31,25 @@ func TestLoadBalancerResource(t *testing.T) {
{
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 + `"
wait_for_create = 60
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]
forwarding_rules = [{ entry_protocol = "http" }]
name = "tf-test-lb"
server_ids = [binarylane_server.test.0.id, binarylane_server.test.1.id]
forwarding_rules = [{ entry_protocol = "http" }]
}
data "binarylane_load_balancer" "test" {
depends_on = [binarylane_load_balancer.test]
id = binarylane_load_balancer.test.id
id = binarylane_load_balancer.test.id
}
`,
Check: resource.ComposeAggregateTestCheckFunc(
@@ -84,3 +90,60 @@ data "binarylane_load_balancer" "test" {
},
})
}
func init() {
resource.AddTestSweepers("load_balancer", &resource.Sweeper{
Name: "load_balancer",
Dependencies: []string{"server"},
F: func(_ string) error {
client, err := binarylane.NewClientWithDefaultConfig()
if err != nil {
return fmt.Errorf("Error creating Binary Lane API client: %w", err)
}
ctx := context.Background()
var page int32 = 1
perPage := int32(200)
var nextPage bool = true
for nextPage {
params := binarylane.GetLoadBalancersParams{
Page: &page,
PerPage: &perPage,
}
listResp, err := client.GetLoadBalancersWithResponse(ctx, &params)
if err != nil {
return fmt.Errorf("Error getting load balancers for test sweep: %w", err)
}
if listResp.StatusCode() != http.StatusOK {
return fmt.Errorf("Unexpected status code getting load balancers for test sweep: %s", listResp.Body)
}
loadBalancers := *listResp.JSON200.LoadBalancers
for _, lb := range loadBalancers {
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)
}
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)
}
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 {
nextPage = false
break
}
page++
}
return nil
},
})
}
+6 -61
View File
@@ -2,12 +2,9 @@ package provider
import (
"context"
"os"
"terraform-provider-binarylane/internal/binarylane"
"github.com/deepmap/oapi-codegen/pkg/securityprovider"
"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/provider"
"github.com/hashicorp/terraform-plugin-framework/provider/schema"
"github.com/hashicorp/terraform-plugin-framework/resource"
@@ -25,8 +22,7 @@ func New(version string) func() provider.Provider {
}
type BinarylaneClient struct {
endpoint string
client *binarylane.ClientWithResponses
client *binarylane.ClientWithResponses
}
type binarylaneProvider struct {
@@ -67,68 +63,17 @@ func (p *binarylaneProvider) Configure(ctx context.Context, req provider.Configu
return
}
if config.Endpoint.IsUnknown() {
resp.Diagnostics.AddAttributeError(
path.Root("api_endpoint"),
"Unknown Binary Lane API endpoint",
"The provider cannot create the Binary Lane API client as there is an unknown configuration value for the "+
"Binary Lane API endpoint. Either target apply the source of the value first, set the value statically in "+
"the configuration, or use the BINARYLANE_API_ENDPOINT environment variable.",
)
}
if config.Token.IsUnknown() {
resp.Diagnostics.AddAttributeError(
path.Root("api_token"),
"Unknown Binary Lane token",
"The provider cannot create the Binary Lane API client as there is an unknown configuration value for the "+
"Binary Lane API token. Either target apply the source of the value first, set the value statically in the "+
"configuration, or use the BINARYLANE_API_TOKEN environment variable.",
)
}
if resp.Diagnostics.HasError() {
return
}
// Default values to environment variables, but override
// with Terraform configuration value if set.
endpoint := os.Getenv("BINARYLANE_API_ENDPOINT")
token := os.Getenv("BINARYLANE_API_TOKEN")
if !config.Endpoint.IsNull() {
endpoint = config.Endpoint.ValueString()
}
if !config.Token.IsNull() {
token = config.Token.ValueString()
}
if endpoint == "" {
endpoint = "https://api.binarylane.com.au/v2"
}
if token == "" {
resp.Diagnostics.AddAttributeError(
path.Root("api_token"),
"Missing Binary Lane API token",
"The provider cannot create the Binary Lane API client as there is a missing or empty value for the Binary "+
"Lane API token. Set the token value in the configuration or use the BINARYLANE_API_TOKEN environment "+
"variable. If either is already set, ensure the value is not empty.",
)
}
if resp.Diagnostics.HasError() {
return
}
auth, err := securityprovider.NewSecurityProviderBearerToken(token)
if err != nil {
resp.Diagnostics.AddError("Failed to create security provider with supplied token", err.Error())
return
}
client, err := binarylane.NewClientWithResponses(endpoint, binarylane.WithRequestEditorFn(auth.Intercept))
client, err := binarylane.NewClientWithConfig(
config.Endpoint.ValueString(),
config.Token.ValueString(),
)
if err != nil {
resp.Diagnostics.AddError("Failed to create Binary Lane API client", err.Error())
return
}
binarylaneClient := BinarylaneClient{
endpoint: endpoint,
client: client,
client: client,
}
resp.DataSourceData = binarylaneClient
+3
View File
@@ -11,6 +11,9 @@ provider "binarylane" {
# api_token = "test123"
# api_endpoint = "https://test.binarylane.internal.au/v2"
}
# End of provider config
`
)
+56 -10
View File
@@ -30,6 +30,8 @@ type serverDataModel struct {
PublicIpv4Addresses types.List `tfsdk:"public_ipv4_addresses"`
PrivateIPv4Addresses types.List `tfsdk:"private_ipv4_addresses"`
Permalink types.String `tfsdk:"permalink"`
Memory types.Int32 `tfsdk:"memory"`
Disk types.Int32 `tfsdk:"disk"`
}
func (d *serverDataSource) Configure(_ context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
@@ -98,6 +100,20 @@ func (d *serverDataSource) Schema(ctx context.Context, req datasource.SchemaRequ
ElementType: types.StringType,
Computed: true,
}
memoryDescription := "The amount of memory in MB assigned to the server."
resp.Schema.Attributes["memory"] = &schema.Int32Attribute{
Description: memoryDescription,
MarkdownDescription: memoryDescription,
Computed: true,
}
diskDescription := "The amount of storage in GB assigned to the server."
resp.Schema.Attributes["disk"] = &schema.Int32Attribute{
Description: diskDescription,
MarkdownDescription: diskDescription,
Computed: true,
}
}
func (d *serverDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
@@ -128,16 +144,19 @@ func (d *serverDataSource) Read(ctx context.Context, req datasource.ReadRequest,
return
}
// Set data values
data.Id = types.Int64Value(*serverResp.JSON200.Server.Id)
data.Name = types.StringValue(*serverResp.JSON200.Server.Name)
data.Image = types.StringValue(*serverResp.JSON200.Server.Image.Slug)
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.PortBlocking = types.BoolValue(serverResp.JSON200.Server.Networks.PortBlocking)
data.VpcId = types.Int64PointerValue(serverResp.JSON200.Server.VpcId)
data.Permalink = types.StringValue(*serverResp.JSON200.Server.Permalink)
var publicIpv4Addresses []string
var privateIpv4Addresses []string
data.Memory = types.Int32Value(*serverResp.JSON200.Server.Memory)
data.Disk = types.Int32Value(*serverResp.JSON200.Server.Disk)
publicIpv4Addresses := []string{}
privateIpv4Addresses := []string{}
for _, v4address := range serverResp.JSON200.Server.Networks.V4 {
if v4address.Type == "public" {
@@ -146,13 +165,40 @@ func (d *serverDataSource) Read(ctx context.Context, req datasource.ReadRequest,
privateIpv4Addresses = append(privateIpv4Addresses, v4address.IpAddress)
}
}
data.PublicIpv4Addresses, diags = types.ListValueFrom(ctx, types.StringType, publicIpv4Addresses)
resp.Diagnostics.Append(diags...)
data.PrivateIPv4Addresses, diags = types.ListValueFrom(ctx, types.StringType, privateIpv4Addresses)
resp.Diagnostics.Append(diags...)
// Save data into Terraform state
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
tfPublicIpv4Addresses, diag := types.ListValueFrom(ctx, types.StringType, publicIpv4Addresses)
diags.Append(diag...)
if diag.HasError() {
data.PublicIpv4Addresses = types.ListUnknown(data.PublicIpv4Addresses.ElementType(ctx))
} else {
data.PublicIpv4Addresses = tfPublicIpv4Addresses
}
tfPrivateIpv4Addresses, diag := types.ListValueFrom(ctx, types.StringType, privateIpv4Addresses)
diags.Append(diag...)
if diag.HasError() {
data.PrivateIPv4Addresses = types.ListUnknown(data.PrivateIPv4Addresses.ElementType(ctx))
} else {
data.PrivateIPv4Addresses = tfPrivateIpv4Addresses
}
// Get user data script
userDataResp, err := d.bc.client.GetServersServerIdUserDataWithResponse(ctx, data.Id.ValueInt64())
if err != nil {
resp.Diagnostics.AddError(
fmt.Sprintf("Error reading server user data: id=%s, name=%s", data.Id.String(), data.Name.ValueString()),
err.Error(),
)
return
}
if userDataResp.StatusCode() != http.StatusOK {
resp.Diagnostics.AddError(
fmt.Sprintf("Unexpected HTTP status %d reading server user data: name=%s, id=%s", userDataResp.StatusCode(), data.Name.ValueString(), data.Id.String()),
string(userDataResp.Body),
)
return
}
data.UserData = types.StringPointerValue(userDataResp.JSON200.UserData)
// Save data into Terraform state
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
@@ -21,27 +21,28 @@ func TestServerFirewallRulesResource(t *testing.T) {
// Create and Read testing
{
Config: providerConfig + `
resource "binarylane_server" "test" {
name = "tf-test-server-fw-rules"
region = "per"
image = "debian-12"
size = "std-min"
password = "` + password + `"
wait_for_create = 60 # Must wait for the server to be ready before creating firewall rules
name = "tf-test-server-fw-rules"
region = "per"
image = "debian-12"
size = "std-min"
password = "` + password + `"
public_ipv4_count = 0
}
resource "binarylane_server_firewall_rules" "test" {
server_id = binarylane_server.test.id
firewall_rules = [
{
description = "Allow SSH"
protocol = "tcp"
source_addresses = ["0.0.0.0/0"]
destination_addresses = [binarylane_server.test.private_ipv4_addresses.0]
destination_ports = ["22"]
action = "accept"
}
]
firewall_rules = [
{
description = "Allow SSH"
protocol = "tcp"
source_addresses = ["0.0.0.0/0"]
destination_addresses = [binarylane_server.test.private_ipv4_addresses.0]
destination_ports = ["22"]
action = "accept"
}
]
}
data "binarylane_server_firewall_rules" "test" {
@@ -95,27 +96,28 @@ data "binarylane_server_firewall_rules" "test" {
// Update and Read testing
{
Config: providerConfig + `
resource "binarylane_server" "test" {
name = "tf-test-server-fw-rules"
region = "per"
image = "debian-12"
size = "std-min"
password = "` + password + `"
wait_for_create = 60 # Must wait for the server to be ready before creating firewall rules
name = "tf-test-server-fw-rules"
region = "per"
image = "debian-12"
size = "std-min"
password = "` + password + `"
public_ipv4_count = 0
}
resource "binarylane_server_firewall_rules" "test" {
server_id = binarylane_server.test.id
firewall_rules = [
{
description = "Allow HTTP" # Updated description
protocol = "tcp"
source_addresses = ["0.0.0.0/0"]
destination_addresses = [binarylane_server.test.private_ipv4_addresses.0]
destination_ports = ["80"] # Updated port
action = "accept"
},
]
firewall_rules = [
{
description = "Allow HTTP" # Updated description
protocol = "tcp"
source_addresses = ["0.0.0.0/0"]
destination_addresses = [binarylane_server.test.private_ipv4_addresses.0]
destination_ports = ["80"] # Updated port
action = "accept"
},
]
}
`,
Check: resource.ComposeAggregateTestCheckFunc(
File diff suppressed because it is too large Load Diff
+168 -26
View File
@@ -1,8 +1,14 @@
package provider
import (
"context"
"crypto/rand"
"encoding/base64"
"fmt"
"log"
"net/http"
"strings"
"terraform-provider-binarylane/internal/binarylane"
"testing"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
@@ -18,48 +24,54 @@ func TestServerResource(t *testing.T) {
}
password := base64.URLEncoding.EncodeToString(pw_bytes)
sshPublicKeyInitial := GeneratePublicKey(t)
sshPublicKeyUpdated := GeneratePublicKey(t)
resource.ParallelTest(t, resource.TestCase{
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
Steps: []resource.TestStep{
// Create and Read testing
{
Config: providerConfig + `
resource "binarylane_vpc" "test" {
name = "tf-test-server-resource"
ip_range = "10.240.0.0/16"
name = "tf-test-server-resource"
ip_range = "10.240.0.0/16"
}
resource "binarylane_ssh_key" "test" {
name = "tf-test-server-resource"
public_key = "` + GeneratePublicKey(t) + `"
resource "binarylane_ssh_key" "initial" {
name = "tf-test-server-resource-initial"
public_key = "` + sshPublicKeyInitial + `"
default = true
}
resource "binarylane_ssh_key" "unused" {
name = "tf-test-server-resource-unused"
public_key = "` + GeneratePublicKey(t) + `"
resource "binarylane_ssh_key" "updated" {
name = "tf-test-server-resource-updated"
public_key = "` + sshPublicKeyUpdated + `"
default = true
}
resource "binarylane_server" "test" {
name = "tf-test-server-resource"
region = "per"
image = "debian-12"
size = "std-min"
password = "` + password + `"
vpc_id = binarylane_vpc.test.id
public_ipv4_count = 0
user_data = <<EOT
name = "tf-test-server-resource"
region = "per"
image = "debian-11"
size = "std-min"
memory = 1152
password = "` + password + `"
vpc_id = binarylane_vpc.test.id
public_ipv4_count = 1
ssh_keys = [binarylane_ssh_key.initial.id]
source_and_destination_check = false
user_data = <<EOT
#cloud-config
echo "Hello World" > /var/tmp/output.txt
EOT
ssh_keys = [binarylane_ssh_key.test.id]
}
data "binarylane_server" "test" {
depends_on = [binarylane_server.test]
id = binarylane_server.test.id
id = binarylane_server.test.id
}
`,
Check: resource.ComposeAggregateTestCheckFunc(
@@ -67,28 +79,37 @@ data "binarylane_server" "test" {
resource.TestCheckResourceAttrSet("binarylane_server.test", "id"),
resource.TestCheckResourceAttr("binarylane_server.test", "name", "tf-test-server-resource"),
resource.TestCheckResourceAttr("binarylane_server.test", "region", "per"),
resource.TestCheckResourceAttr("binarylane_server.test", "image", "debian-12"),
resource.TestCheckResourceAttr("binarylane_server.test", "image", "debian-11"),
resource.TestCheckResourceAttr("binarylane_server.test", "size", "std-min"),
resource.TestCheckResourceAttr("binarylane_server.test", "memory", "1152"),
resource.TestCheckResourceAttr("binarylane_server.test", "disk", "20"),
resource.TestCheckResourceAttrSet("binarylane_server.test", "vpc_id"),
resource.TestCheckResourceAttr("binarylane_server.test", "public_ipv4_count", "0"),
resource.TestCheckResourceAttr("binarylane_server.test", "public_ipv4_count", "1"),
resource.TestCheckResourceAttr("binarylane_server.test", "password", password),
resource.TestCheckResourceAttr("binarylane_server.test", "user_data", `#cloud-config
echo "Hello World" > /var/tmp/output.txt
`),
resource.TestCheckResourceAttr("binarylane_server.test", "public_ipv4_addresses.#", "0"),
resource.TestCheckResourceAttr("binarylane_server.test", "public_ipv4_addresses.#", "1"),
resource.TestCheckResourceAttrSet("binarylane_server.test", "private_ipv4_addresses.0"),
resource.TestCheckResourceAttr("binarylane_server.test", "port_blocking", "true"),
resource.TestCheckResourceAttr("binarylane_server.test", "ssh_keys.#", "1"), // Only the test SSH key should be registered
resource.TestCheckResourceAttrPair("binarylane_server.test", "ssh_keys.0", "binarylane_ssh_key.test", "id"),
resource.TestCheckResourceAttr("binarylane_server.test", "ssh_keys.#", "1"),
resource.TestCheckResourceAttrPair("binarylane_server.test", "ssh_keys.0", "binarylane_ssh_key.initial", "id"),
resource.TestCheckResourceAttrSet("binarylane_server.test", "permalink"),
resource.TestCheckResourceAttr("binarylane_server.test", "source_and_destination_check", "false"),
// Verify data source values
resource.TestCheckResourceAttrPair("data.binarylane_server.test", "id", "binarylane_server.test", "id"),
resource.TestCheckResourceAttr("data.binarylane_server.test", "name", "tf-test-server-resource"),
resource.TestCheckResourceAttr("data.binarylane_server.test", "region", "per"),
resource.TestCheckResourceAttr("data.binarylane_server.test", "image", "debian-12"),
resource.TestCheckResourceAttr("data.binarylane_server.test", "image", "debian-11"),
resource.TestCheckResourceAttr("data.binarylane_server.test", "size", "std-min"),
resource.TestCheckResourceAttrSet("data.binarylane_server.test", "vpc_id"),
resource.TestCheckResourceAttrPair("data.binarylane_server.test", "permalink", "binarylane_server.test", "permalink"),
resource.TestCheckResourceAttr("data.binarylane_server.test", "user_data", `#cloud-config
echo "Hello World" > /var/tmp/output.txt
`),
resource.TestCheckResourceAttr("data.binarylane_server.test", "memory", "1152"),
resource.TestCheckResourceAttr("data.binarylane_server.test", "disk", "20"),
),
},
// Test import by ID
@@ -96,7 +117,7 @@ echo "Hello World" > /var/tmp/output.txt
ResourceName: "binarylane_server.test",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"password", "ssh_keys", "user_data", "wait_for_create", "public_ipv4_count"},
ImportStateVerifyIgnore: []string{"password", "ssh_keys", "timeouts"},
},
// Test import by name
{
@@ -104,8 +125,129 @@ echo "Hello World" > /var/tmp/output.txt
ImportState: true,
ImportStateId: "tf-test-server-resource",
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"password", "ssh_keys", "user_data", "wait_for_create", "public_ipv4_count"},
ImportStateVerifyIgnore: []string{"password", "ssh_keys", "timeouts"},
},
// Update and Read testing
{
Config: providerConfig + `
resource "binarylane_vpc" "test" {
name = "tf-test-server-resource"
ip_range = "10.240.0.0/16"
}
resource "binarylane_ssh_key" "initial" {
name = "tf-test-server-resource-initial"
public_key = "` + sshPublicKeyInitial + `"
default = true
}
resource "binarylane_ssh_key" "updated" {
name = "tf-test-server-resource-updated"
public_key = "` + sshPublicKeyUpdated + `"
default = true
}
resource "binarylane_server" "test" {
name = "tf-test-server-resource-2"
region = "per"
image = "debian-12"
size = "std-1vcpu"
disk = "45"
password = "` + password + `"
vpc_id = null
public_ipv4_count = 0
ssh_keys = [binarylane_ssh_key.updated.id]
# source_and_destination_check = null # defaults to null when vpc_id is null
user_data = <<EOT
#cloud-config
echo "Hello Whitespace" > /var/tmp/output.txt
EOT
}
`,
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr("binarylane_server.test", "name", "tf-test-server-resource-2"),
resource.TestCheckResourceAttr("binarylane_server.test", "size", "std-1vcpu"),
resource.TestCheckResourceAttr("binarylane_server.test", "memory", "2048"),
resource.TestCheckResourceAttr("binarylane_server.test", "disk", "45"),
resource.TestCheckResourceAttr("binarylane_server.test", "public_ipv4_count", "0"),
resource.TestCheckResourceAttr("binarylane_server.test", "public_ipv4_addresses.#", "0"),
resource.TestCheckResourceAttr("binarylane_server.test", "image", "debian-12"),
resource.TestCheckNoResourceAttr("binarylane_server.test", "vpc_id"),
resource.TestCheckResourceAttr("binarylane_server.test", "ssh_keys.#", "1"),
resource.TestCheckResourceAttrPair("binarylane_server.test", "ssh_keys.0", "binarylane_ssh_key.updated", "id"),
resource.TestCheckNoResourceAttr("binarylane_server.test", "source_and_destination_check"),
resource.TestCheckResourceAttr("binarylane_server.test", "user_data", // test extra whitespace
`#cloud-config
echo "Hello Whitespace" > /var/tmp/output.txt
`),
),
},
},
})
}
func init() {
resource.AddTestSweepers("server", &resource.Sweeper{
Name: "server",
F: func(_ string) error {
client, err := binarylane.NewClientWithDefaultConfig()
if err != nil {
return fmt.Errorf("Error creating Binary Lane API client: %w", err)
}
ctx := context.Background()
var page int32 = 1
perPage := int32(200)
nextPage := true
for nextPage {
params := binarylane.GetServersParams{
Page: &page,
PerPage: &perPage,
}
listResp, err := client.GetServersWithResponse(ctx, &params)
if err != nil {
return fmt.Errorf("Error getting servers for test sweep: %w", err)
}
if listResp.StatusCode() != http.StatusOK {
return fmt.Errorf("Unexpected status code getting servers in test sweep: %s", listResp.Body)
}
servers := *listResp.JSON200.Servers
for _, s := range servers {
if strings.HasPrefix(*s.Name, "tf-test-") {
reason := "Terraform deletion"
params := binarylane.DeleteServersServerIdParams{
Reason: &reason,
}
deleteResp, err := client.DeleteServersServerIdWithResponse(ctx, *s.Id, &params)
if err != nil {
return fmt.Errorf("Error deleting server %d during test sweep: %w", *s.Id, err)
}
if deleteResp.StatusCode() != http.StatusNoContent {
return fmt.Errorf("Unexpected status %d deleting server %d in test sweep: %s", deleteResp.StatusCode(), *s.Id, deleteResp.Body)
}
log.Println("Deleted server during test sweep:", *s.Id)
}
}
if listResp.JSON200.Links == nil || listResp.JSON200.Links.Pages == nil || listResp.JSON200.Links.Pages.Next == nil {
nextPage = false
break
}
page++
}
return nil
},
})
}
+26 -22
View File
@@ -21,7 +21,7 @@ import (
var (
_ resource.Resource = &sshKeyResource{}
_ resource.ResourceWithConfigure = &sshKeyResource{}
_ resource.ResourceWithImportState = &serverResource{}
_ resource.ResourceWithImportState = &sshKeyResource{}
)
func NewSshKeyResource() resource.Resource {
@@ -102,7 +102,6 @@ func (r *sshKeyResource) Create(ctx context.Context, req resource.CreateRequest,
return
}
// Create API call logic
sshResp, err := r.bc.client.PostAccountKeysWithResponse(ctx, binarylane.SshKeyRequest{
Name: data.Name.ValueString(),
Default: data.Default.ValueBoolPointer(),
@@ -117,8 +116,8 @@ func (r *sshKeyResource) Create(ctx context.Context, req resource.CreateRequest,
}
if sshResp.StatusCode() != http.StatusOK {
resp.Diagnostics.AddError(
"Unexpected HTTP status code creating server",
fmt.Sprintf("Received %s creating new server: name=%s. Details: %s", sshResp.Status(), data.Name.ValueString(), sshResp.Body),
"Unexpected HTTP status code creating SSH key",
fmt.Sprintf("Received %s creating SSH key: name=%s. Details: %s", sshResp.Status(), data.Name.ValueString(), sshResp.Body),
)
return
}
@@ -158,8 +157,8 @@ func (r *sshKeyResource) Read(ctx context.Context, req resource.ReadRequest, res
}
if sshResp.StatusCode() != http.StatusOK {
resp.Diagnostics.AddError(
"Unexpected HTTP status code creating server",
fmt.Sprintf("Received %s creating new server: name=%s. Details: %s", sshResp.Status(), data.Name.ValueString(), sshResp.Body),
"Unexpected HTTP status code getting SSH key",
fmt.Sprintf("Received %s getting SSH key: name=%s. Details: %s", sshResp.Status(), data.Name.ValueString(), sshResp.Body),
)
return
}
@@ -176,22 +175,28 @@ func (r *sshKeyResource) Read(ctx context.Context, req resource.ReadRequest, res
}
func (r *sshKeyResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
var data sshKeyModel
var plan, state sshKeyModel
// Read Terraform prior state data into the model
resp.Diagnostics.Append(req.State.Get(ctx, &state)...)
if resp.Diagnostics.HasError() {
return
}
// Read Terraform plan data into the model
resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...)
resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...)
if resp.Diagnostics.HasError() {
return
}
// Update API call logic
sshResp, err := r.bc.client.PutAccountKeysKeyIdWithResponse(ctx, int(data.Id.ValueInt64()), binarylane.UpdateSshKeyRequest{
Name: data.Name.ValueString(),
Default: data.Default.ValueBoolPointer(),
sshResp, err := r.bc.client.PutAccountKeysKeyIdWithResponse(ctx, int(state.Id.ValueInt64()), binarylane.UpdateSshKeyRequest{
Name: plan.Name.ValueString(),
Default: plan.Default.ValueBoolPointer(),
})
if err != nil {
resp.Diagnostics.AddError(
fmt.Sprintf("Error updating SSH Key: name=%s", data.Name.ValueString()),
fmt.Sprintf("Error updating SSH Key: name=%s", plan.Name.ValueString()),
err.Error(),
)
return
@@ -199,30 +204,29 @@ func (r *sshKeyResource) Update(ctx context.Context, req resource.UpdateRequest,
if sshResp.StatusCode() != http.StatusOK {
resp.Diagnostics.AddError(
"Unexpected HTTP status code updating SSH Key",
fmt.Sprintf("Received %s updating new SSH Key: name=%s. Details: %s", sshResp.Status(), data.Name.ValueString(), sshResp.Body),
fmt.Sprintf("Received %s updating new SSH Key: name=%s. Details: %s", sshResp.Status(), plan.Name.ValueString(), sshResp.Body),
)
return
}
// Save updated data into Terraform state
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...)
}
func (r *sshKeyResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
var data sshKeyModel
// Read Terraform prior state data into the model
resp.Diagnostics.Append(req.State.Get(ctx, &data)...)
var state sshKeyModel
// Read Terraform prior state into the model
resp.Diagnostics.Append(req.State.Get(ctx, &state)...)
if resp.Diagnostics.HasError() {
return
}
// Delete API call logic
sshResp, err := r.bc.client.DeleteAccountKeysKeyIdWithResponse(ctx, int(data.Id.ValueInt64()))
sshResp, err := r.bc.client.DeleteAccountKeysKeyIdWithResponse(ctx, int(state.Id.ValueInt64()))
if err != nil {
resp.Diagnostics.AddError(
fmt.Sprintf("Error deleting SSH Key: name=%s", data.Name.ValueString()),
fmt.Sprintf("Error deleting SSH Key: name=%s", state.Name.ValueString()),
err.Error(),
)
return
@@ -230,7 +234,7 @@ func (r *sshKeyResource) Delete(ctx context.Context, req resource.DeleteRequest,
if sshResp.StatusCode() != http.StatusNoContent {
resp.Diagnostics.AddError(
"Unexpected HTTP status code deleting SSH Key",
fmt.Sprintf("Received %s deleting SSH Key: name=%s. Details: %s", sshResp.Status(), data.Name.ValueString(), sshResp.Body),
fmt.Sprintf("Received %s deleting SSH Key: name=%s. Details: %s", sshResp.Status(), state.Name.ValueString(), sshResp.Body),
)
return
}
@@ -268,7 +272,7 @@ func (r *sshKeyResource) ImportState(
if sshResp.StatusCode() != http.StatusOK {
resp.Diagnostics.AddError(
"Unexpected HTTP status code getting SSH key for import",
fmt.Sprintf("Received %s reading SSH key: fingerprint=%s. Details: %s", sshResp.Status(), req.ID,
fmt.Sprintf("Received %s getting SSH key for import: fingerprint=%s. Details: %s", sshResp.Status(), req.ID,
sshResp.Body))
return
}
+71 -7
View File
@@ -1,9 +1,14 @@
package provider
import (
"context"
"crypto/ed25519"
"encoding/base64"
"fmt"
"log"
"net/http"
"strings"
"terraform-provider-binarylane/internal/binarylane"
"testing"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
@@ -19,26 +24,27 @@ func TestSshKeyResource(t *testing.T) {
// Create and Read testing
{
Config: providerConfig + `
resource "binarylane_ssh_key" "test" {
name = "tf_ssh_key_resource_test"
public_key = "` + publicKey + `"
name = "tf-test-key-resource-test"
public_key = "` + publicKey + `"
}
data "binarylane_ssh_key" "test" {
depends_on = [binarylane_ssh_key.test]
id = binarylane_ssh_key.test.id
id = binarylane_ssh_key.test.id
}
`,
Check: resource.ComposeAggregateTestCheckFunc(
// Verify resource values
resource.TestCheckResourceAttr("binarylane_ssh_key.test", "name", "tf_ssh_key_resource_test"),
resource.TestCheckResourceAttr("binarylane_ssh_key.test", "name", "tf-test-key-resource-test"),
resource.TestCheckResourceAttr("binarylane_ssh_key.test", "public_key", publicKey),
resource.TestCheckResourceAttr("binarylane_ssh_key.test", "default", "false"),
resource.TestCheckResourceAttrSet("binarylane_ssh_key.test", "id"),
// Verify data source values
resource.TestCheckResourceAttr("data.binarylane_ssh_key.test", "name", "tf_ssh_key_resource_test"),
resource.TestCheckResourceAttr("data.binarylane_ssh_key.test", "name", "tf-test-key-resource-test"),
resource.TestCheckResourceAttrSet("data.binarylane_ssh_key.test", "public_key"), // Ideally would check this is identical, but whitespace is not preserved
resource.TestCheckResourceAttr("data.binarylane_ssh_key.test", "default", "false"),
resource.TestCheckResourceAttrSet("data.binarylane_ssh_key.test", "id"),
@@ -62,14 +68,14 @@ data "binarylane_ssh_key" "test" {
// {
// Config: providerConfig + `
// resource "binarylane_ssh_key" "test" {
// name = "tf_ssh_key_resource_test"
// name = "tf-test-key-resource-test"
// public_key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJCsuosklP0T4fJcQDgkeVh7dQu+eV+vev1CfwdUkj7h test@company.internal"
// default = true
// }
// `,
// Check: resource.ComposeAggregateTestCheckFunc(
// // Verify resource values
// resource.TestCheckResourceAttr("binarylane_ssh_key.test", "name", "tf_ssh_key_resource_test"),
// resource.TestCheckResourceAttr("binarylane_ssh_key.test", "name", "tf-test-key-resource-test"),
// resource.TestCheckResourceAttr("data.binarylane_ssh_key.test", "default", "true"),
// ),
// },
@@ -106,3 +112,61 @@ func ImportByFingerprint(state *terraform.State) (fingerprint string, err error)
return rawState["fingerprint"], nil
}
func init() {
resource.AddTestSweepers("ssh_key", &resource.Sweeper{
Name: "ssh_key",
F: func(_ string) error {
client, err := binarylane.NewClientWithDefaultConfig()
if err != nil {
return fmt.Errorf("Error creating Binary Lane API client: %w", err)
}
ctx := context.Background()
var page int32 = 1
perPage := int32(200)
nextPage := true
for nextPage {
params := binarylane.GetAccountKeysParams{
Page: &page,
PerPage: &perPage,
}
listResp, err := client.GetAccountKeysWithResponse(ctx, &params)
if err != nil {
return fmt.Errorf("Error getting SSH keys for test sweep: %w", err)
}
if listResp.StatusCode() != http.StatusOK {
return fmt.Errorf("Unexpected status code getting SSH keys for test sweep: %s", listResp.Body)
}
keys := listResp.JSON200.SshKeys
for _, k := range keys {
if strings.HasPrefix(*k.Name, "tf-test-") {
deleteResp, err := client.DeleteAccountKeysKeyIdWithResponse(ctx, int(*k.Id))
if err != nil {
return fmt.Errorf("Error deleting SSH key %d for test sweep: %w", *k.Id, err)
}
if deleteResp.StatusCode() != http.StatusNoContent {
return fmt.Errorf("Unexpected status %d deleting SSH key %d for test sweep: %s", deleteResp.StatusCode(), *k.Id, deleteResp.Body)
}
log.Println("Deleted SSH key for test sweep:", *k.Id)
}
}
if listResp.JSON200.Links == nil || listResp.JSON200.Links.Pages == nil || listResp.JSON200.Links.Pages.Next == nil {
nextPage = false
break
}
page++
}
return nil
},
})
}
+11
View File
@@ -0,0 +1,11 @@
package provider
import (
"testing"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
)
func TestMain(m *testing.M) {
resource.TestMain(m)
}
+28
View File
@@ -1,6 +1,7 @@
package provider
import (
"context"
"fmt"
"slices"
@@ -153,3 +154,30 @@ func convertResourceSchemaToDataSourceSchema(rs r_schema.Schema, cfg AttributeCo
return &ds, nil
}
func listContainsUnknown(ctx context.Context, list types.List) bool {
// If the whole list is unknown, return true
if list.IsUnknown() {
return true
}
// Get elements as generic attr.Value to check individual unknown status
var elements []attr.Value
diags := list.ElementsAs(ctx, &elements, false)
if diags.HasError() {
return true // Assume unknown in case of errors
}
// Check if any element is unknown
for _, elem := range elements {
if elem.IsUnknown() {
return true
}
}
return false
}
func Pointer[T any](d T) *T {
return &d
}
+55
View File
@@ -0,0 +1,55 @@
package provider
import (
"context"
"fmt"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
)
var (
_ validator.Int32 = &MultipleOfValidator{}
)
type MultipleOfValidator struct {
Multiple, RangeFrom, RangeTo int32
}
func (v MultipleOfValidator) Description(ctx context.Context) string {
if v.RangeFrom == 0 {
return fmt.Sprintf(`must be a multiple of %d`, v.Multiple)
}
return fmt.Sprintf("when greater than %d, must be a multiple of %d", v.RangeFrom, v.Multiple)
}
func (v MultipleOfValidator) MarkdownDescription(ctx context.Context) string {
if v.RangeFrom == 0 {
return fmt.Sprintf(`must be a multiple of %d`, v.Multiple)
}
return fmt.Sprintf("when greater than %d, must be a multiple of %d", v.RangeFrom, v.Multiple)
}
func (v MultipleOfValidator) ValidateInt32(ctx context.Context, req validator.Int32Request, resp *validator.Int32Response) {
if req.ConfigValue.IsUnknown() || req.ConfigValue.IsNull() {
return
}
memory := req.ConfigValue.ValueInt32()
if memory%v.Multiple == 0 || v.RangeFrom != 0 && memory < v.RangeFrom || v.RangeTo != 0 && memory >= v.RangeTo {
return
}
if v.RangeFrom != 0 {
resp.Diagnostics.AddAttributeError(
req.Path,
"Not a Multiple",
fmt.Sprintf("if greater than %d, value must be a multiple of %d", v.RangeFrom, v.Multiple),
)
} else {
resp.Diagnostics.AddAttributeError(
req.Path,
"Not a Multiple",
fmt.Sprintf("value must be a multiple of %d", v.Multiple),
)
}
}
+90 -23
View File
@@ -1,6 +1,12 @@
package provider
import (
"context"
"fmt"
"log"
"net/http"
"strings"
"terraform-provider-binarylane/internal/binarylane"
"testing"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
@@ -14,30 +20,31 @@ func TestVpcResource(t *testing.T) {
// Create and Read testing
{
Config: providerConfig + `
resource "binarylane_vpc" "test" {
name = "tf-test-vpc"
ip_range = "10.240.0.0/16"
name = "tf-test-vpc"
ip_range = "10.240.0.0/16"
}
data "binarylane_vpc" "test" {
depends_on = [binarylane_vpc.test]
id = binarylane_vpc.test.id
id = binarylane_vpc.test.id
}
resource "binarylane_vpc_route_entries" "test" {
vpc_id = binarylane_vpc.test.id
route_entries = [
{
description = "test"
destination = "0.0.0.0/0"
router = "10.240.0.1"
}
]
vpc_id = binarylane_vpc.test.id
route_entries = [
{
description = "test"
destination = "0.0.0.0/0"
router = "10.240.0.1"
}
]
}
data "binarylane_vpc_route_entries" "test" {
vpc_id = binarylane_vpc_route_entries.test.vpc_id
vpc_id = binarylane_vpc_route_entries.test.vpc_id
}
`,
Check: resource.ComposeAggregateTestCheckFunc(
@@ -82,21 +89,23 @@ data "binarylane_vpc_route_entries" "test" {
// Update and Read testing
{
Config: providerConfig + `
resource "binarylane_vpc" "test" {
name = "tf-test-vpc-renamed"
ip_range = "10.240.0.0/16"
name = "tf-test-vpc-renamed"
ip_range = "10.240.0.0/16"
}
resource "binarylane_vpc_route_entries" "test" {
vpc_id = binarylane_vpc.test.id
route_entries = [
{
description = "test-renamed"
destination = "0.0.0.0/0"
router = "10.240.0.2"
}
]
}`,
vpc_id = binarylane_vpc.test.id
route_entries = [
{
description = "test-renamed"
destination = "0.0.0.0/0"
router = "10.240.0.2"
}
]
}
`,
Check: resource.ComposeAggregateTestCheckFunc(
// Verify binarylane_vpc resource values updated
resource.TestCheckResourceAttr("binarylane_vpc.test", "name", "tf-test-vpc-renamed"), // Updated name
@@ -114,3 +123,61 @@ resource "binarylane_vpc_route_entries" "test" {
},
})
}
func init() {
resource.AddTestSweepers("vpc", &resource.Sweeper{
Name: "vpc",
F: func(_ string) error {
client, err := binarylane.NewClientWithDefaultConfig()
if err != nil {
return fmt.Errorf("Error creating Binary Lane API client: %w", err)
}
ctx := context.Background()
var page int32 = 1
perPage := int32(200)
nextPage := true
for nextPage {
params := binarylane.GetVpcsParams{
Page: &page,
PerPage: &perPage,
}
listResp, err := client.GetVpcsWithResponse(ctx, &params)
if err != nil {
return fmt.Errorf("Error getting VPCs for test sweep: %w", err)
}
if listResp.StatusCode() != http.StatusOK {
return fmt.Errorf("Unexpected status code getting VPCs for test sweep: %s", listResp.Body)
}
vpcs := listResp.JSON200.Vpcs
for _, vpc := range *vpcs {
if strings.HasPrefix(*vpc.Name, "tf-test-") {
deleteResp, err := client.DeleteVpcsVpcIdWithResponse(ctx, *vpc.Id)
if err != nil {
return fmt.Errorf("Error deleting VPC %d in test sweep: %w", *vpc.Id, err)
}
if deleteResp.StatusCode() != http.StatusNoContent {
return fmt.Errorf("Unexpected status %d deleting VPC %d for test sweep: %s", deleteResp.StatusCode(), *vpc.Id, deleteResp.Body)
}
log.Println("Deleted VPC for test sweep:", *vpc.Id)
}
}
if listResp.JSON200.Links == nil || listResp.JSON200.Links.Pages == nil || listResp.JSON200.Links.Pages.Next == nil {
nextPage = false
break
}
page++
}
return nil
},
})
}