forked from mirrors/terraform-provider-binarylane
Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a0a227c88c | |||
| f8edcd0e06 | |||
| 04552e0fcf | |||
| 66fcb6f85e | |||
| 806bdebaf8 | |||
| dd06380c63 | |||
| 322a8fda80 | |||
| a50daac8e9 | |||
| 424828123d | |||
| 4c50298eca | |||
| cbef2be0fe | |||
| 5767bb6739 | |||
| 74eac97fe8 | |||
| a30b6b14a7 | |||
| 0a4156269f | |||
| 0adff101c6 | |||
| 5e3b30a49b | |||
| 45d7ab450c | |||
| c5b250becf | |||
| 10070095e1 | |||
| 24f05a6266 | |||
| 86b980c91b | |||
| 21b43d92b9 | |||
| e70e10c4c9 |
@@ -23,7 +23,7 @@ jobs:
|
||||
needs: test
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
# Allow goreleaser to access older tag information.
|
||||
fetch-depth: 0
|
||||
@@ -32,16 +32,21 @@ jobs:
|
||||
go-version-file: 'go.mod'
|
||||
cache: true
|
||||
- name: Import GPG key
|
||||
uses: crazy-max/ghaction-import-gpg@cb9bde2e2525e640591a934b1fd28eef1dcaf5e5 # v6.2.0
|
||||
uses: crazy-max/ghaction-import-gpg@e89d40939c28e39f97cf32126055eeae86ba74ec # v6.3.0
|
||||
id: import_gpg
|
||||
with:
|
||||
gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }}
|
||||
passphrase: ${{ secrets.PASSPHRASE }}
|
||||
- name: Run GoReleaser
|
||||
uses: goreleaser/goreleaser-action@9ed2f89a662bf1735a48bc8557fd212fa902bebf # v6.1.0
|
||||
uses: goreleaser/goreleaser-action@e435ccd777264be153ace6237001ef4d979d3a7a # v6.4.0
|
||||
with:
|
||||
args: release --clean
|
||||
env:
|
||||
# GitHub sets the GITHUB_TOKEN secret automatically.
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
GPG_FINGERPRINT: ${{ steps.import_gpg.outputs.fingerprint }}
|
||||
- name: Publish Release
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
run: gh release edit "${{ github.ref }}" --draft false
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
@@ -23,7 +23,7 @@ jobs:
|
||||
group: test
|
||||
cancel-in-progress: true # would be nice if GH offered cancel-pending instead, https://github.com/orgs/community/discussions/63136
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version-file: 'go.mod'
|
||||
@@ -54,7 +54,7 @@ jobs:
|
||||
# name: Unit Tests
|
||||
# runs-on: ubuntu-latest
|
||||
# steps:
|
||||
# - uses: actions/checkout@v4
|
||||
# - uses: actions/checkout@v5
|
||||
# - uses: actions/setup-go@v5
|
||||
# with:
|
||||
# go-version-file: 'go.mod'
|
||||
|
||||
Vendored
+3
@@ -1,3 +1,6 @@
|
||||
{
|
||||
"go.testEnvFile": "${workspaceFolder}/.env",
|
||||
"go.testEnvVars": {
|
||||
"TF_LOG": "TRACE"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,9 +19,10 @@ Planned features:
|
||||
- [x] Firewall Rules
|
||||
- [x] Cloud Init
|
||||
- [x] Updating server properties
|
||||
- [x] "Advanced Features"
|
||||
- [x] IPV6
|
||||
- [ ] Customised Backups
|
||||
- [ ] Software
|
||||
- [ ] IPV6
|
||||
- [ ] Alerts
|
||||
- [x] SSH Keys
|
||||
- [x] Virtual Private Cloud
|
||||
@@ -35,9 +36,9 @@ Planned features:
|
||||
- [x] Examples
|
||||
- [x] Basic
|
||||
- [x] Cloud Init
|
||||
- [x] K3s
|
||||
- [ ] NixOS
|
||||
- [ ] Virtual Private Cloud
|
||||
- [ ] Kubernetes
|
||||
|
||||
## Server parameters
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ data "binarylane_load_balancer" "example" {
|
||||
|
||||
- `forwarding_rules` (Attributes List) The rules that control which traffic the load balancer will forward to servers in the pool. Leave null to accept a default "HTTP" only forwarding rule. (see [below for nested schema](#nestedatt--forwarding_rules))
|
||||
- `health_check` (Object) The rules that determine which servers are considered 'healthy' and in the server pool for the load balancer. Leave this null to accept appropriate defaults based on the forwarding_rules. (see [below for nested schema](#nestedatt--health_check))
|
||||
- `ip` (String) The IPv4 address of the load balancer.
|
||||
- `name` (String) The hostname of the load balancer.
|
||||
- `region` (String) Leave null to create an anycast load balancer.
|
||||
- `server_ids` (List of Number) A list of server IDs to assign to this load balancer.
|
||||
@@ -38,7 +39,12 @@ data "binarylane_load_balancer" "example" {
|
||||
|
||||
Read-Only:
|
||||
|
||||
- `entry_protocol` (String) The protocol that traffic must match for the load balancer to forward it. Valid values are "http" and "https".
|
||||
- `entry_protocol` (String) The protocol that traffic must match for this load balancer to forward traffic according to this rule.
|
||||
|
||||
| Value | Description |
|
||||
| ----- | ----------- |
|
||||
| http | The load balancer will forward HTTP traffic that matches this rule. |
|
||||
| https | The load balancer will forward HTTPS traffic that matches this rule. |
|
||||
|
||||
|
||||
<a id="nestedatt--health_check"></a>
|
||||
|
||||
@@ -27,17 +27,45 @@ data "binarylane_server" "example" {
|
||||
|
||||
### Read-Only
|
||||
|
||||
- `backups` (Boolean) If `true`, the server will be backed up twice per day. By default, backups are disabled.
|
||||
- `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.
|
||||
- `advanced_features` (Object) (see [below for nested schema](#nestedatt--advanced_features))
|
||||
- `backups` (Boolean) If `true` this will enable two daily backups for the server. By default, backups are disabled.
|
||||
- `disk` (Number) The total storage in GB for this server. Leave null to accept the default for the size Valid values:
|
||||
- must be a multiple of 5
|
||||
- \> 60 GB must be a multiple of 10
|
||||
- \> 200 GB must be a multiple of 100
|
||||
- `image` (String) The slug of the selected operating system, such as `debian-12`. You can fetch a full list of images from the BinaryLane API.
|
||||
- `ipv6` (Boolean) If `true` this will add a public and private IPv6 address to the server. By default, IPv6 is disabled.
|
||||
- `memory` (Number) The total memory in MB for this server. Leave null to accept the default size. Valid values:
|
||||
- must be a multiple of 128
|
||||
- \> 2048 MB must be a multiple of 1024
|
||||
- \> 16384 MB must be a multiple of 2048
|
||||
- \> 24576 MB 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.
|
||||
- `permalink` (String) A randomly generated two-word identifier assigned to servers in regions that support this feature
|
||||
- `port_blocking` (Boolean) Port blocking of outgoing connections for email, SSH and Remote Desktop (TCP ports 22, 25, and 3389) is enabled by default for all new servers. If this is false port blocking will be disabled. Disabling port blocking is only available to reviewed accounts.
|
||||
- `private_ipv4_addresses` (List of String) The private IPv4 addresses assigned to the server.
|
||||
- `private_ipv6_addresses` (List of String) The private IPv6 addresses assigned to the server.
|
||||
- `public_ipv4_addresses` (List of String) The public IPv4 addresses assigned to the server.
|
||||
- `public_ipv6_addresses` (List of String) The public IPv6 addresses assigned to the server.
|
||||
- `region` (String) The slug of the selected region.
|
||||
- `size` (String) The slug of the selected size.
|
||||
- `ssh_keys` (List of Number) This is a list of SSH key ids that were added to the server during creation.
|
||||
- `user_data` (String) A script or cloud-config YAML file to configure the server.
|
||||
- `vpc_id` (Number) ID of the Virtual Private Cloud (VPC) the server is connected to.
|
||||
- `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.
|
||||
- `user_data` (String) A script or cloud-config YAML file to configure the server. Can only be specified if the OS image supports UserData (i.e. not Windows). See more: https://cloudinit.readthedocs.io/en/latest/explanation/format.html#user-data-script
|
||||
- `vpc_id` (Number) Leave null to use default (public) network for the selected region.
|
||||
|
||||
<a id="nestedatt--advanced_features"></a>
|
||||
### Nested Schema for `advanced_features`
|
||||
|
||||
Read-Only:
|
||||
|
||||
- `cloud_init` (Boolean)
|
||||
- `driver_disk` (Boolean)
|
||||
- `emulated_devices` (Boolean)
|
||||
- `emulated_hyperv` (Boolean)
|
||||
- `emulated_tpm` (Boolean)
|
||||
- `local_rtc` (Boolean)
|
||||
- `nested_virt` (Boolean)
|
||||
- `qemu_guest_agent` (Boolean)
|
||||
- `uefi_boot` (Boolean)
|
||||
- `unset_uuid` (Boolean)
|
||||
|
||||
@@ -35,8 +35,20 @@ data "binarylane_server_firewall_rules" "example" {
|
||||
Read-Only:
|
||||
|
||||
- `action` (String) The action to take when there is a match on this rule.
|
||||
|
||||
| Value | Description |
|
||||
| ----- | ----------- |
|
||||
| drop | Traffic matching this rule will be dropped. |
|
||||
| accept | Traffic matching this rule will be accepted. |
|
||||
- `description` (String) A description to assist in identifying this rule. Commonly used to record the reason for the rule or the intent behind it, e.g. "Block access to RDP" or "Allow access from HQ".
|
||||
- `destination_addresses` (List of String) The destination addresses to match for this rule. Each address may be an individual IPv4 address or a range in IPv4 CIDR notation.
|
||||
- `destination_ports` (List of String) The destination ports to match for this rule. Leave null or empty to match on all ports.
|
||||
- `protocol` (String) The protocol to match for this rule.
|
||||
|
||||
| Value | Description |
|
||||
| ----- | ----------- |
|
||||
| all | This rule will match any protocol. |
|
||||
| icmp | This rule will match ICMP traffic only. |
|
||||
| tcp | This rule will match TCP traffic only. |
|
||||
| udp | This rule will match UDP traffic only. |
|
||||
- `source_addresses` (List of String) The source addresses to match for this rule. Each address may be an individual IPv4 address or a range in IPv4 CIDR notation.
|
||||
|
||||
@@ -30,4 +30,4 @@ data "binarylane_ssh_key" "example" {
|
||||
- `default` (Boolean) If `true`, this SSH key will be included on all new server installations (if the operating system supports SSH key injection).
|
||||
- `fingerprint` (String) The fingerprint of the SSH key.
|
||||
- `name` (String) A name to help you identify the key.
|
||||
- `public_key` (String) The public key in OpenSSH "authorized_keys" format.
|
||||
- `public_key` (String) The public key in OpenSSH "authorized_keys" format. This should be a valid public key, such as one generated by `ssh-keygen`.
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
---
|
||||
# generated by https://github.com/hashicorp/terraform-plugin-docs
|
||||
page_title: "binarylane Provider"
|
||||
subcategory: ""
|
||||
description: |-
|
||||
|
||||
---
|
||||
|
||||
@@ -46,13 +46,19 @@ resource "binarylane_load_balancer" "example" {
|
||||
### Read-Only
|
||||
|
||||
- `id` (Number) The ID of the load balancer to fetch.
|
||||
- `ip` (String) The IPv4 address of the load balancer.
|
||||
|
||||
<a id="nestedatt--forwarding_rules"></a>
|
||||
### Nested Schema for `forwarding_rules`
|
||||
|
||||
Required:
|
||||
|
||||
- `entry_protocol` (String) The protocol that traffic must match for the load balancer to forward it. Valid values are "http" and "https".
|
||||
- `entry_protocol` (String) The protocol that traffic must match for this load balancer to forward traffic according to this rule.
|
||||
|
||||
| Value | Description |
|
||||
| ----- | ----------- |
|
||||
| http | The load balancer will forward HTTP traffic that matches this rule. |
|
||||
| https | The load balancer will forward HTTPS traffic that matches this rule. |
|
||||
|
||||
|
||||
<a id="nestedatt--health_check"></a>
|
||||
@@ -63,6 +69,12 @@ Optional:
|
||||
- `path` (String) Leave null to accept the default '/' path.
|
||||
- `protocol` (String) Leave null to accept the default HTTP protocol.
|
||||
|
||||
| Value | Description |
|
||||
| ----- | ----------- |
|
||||
| http | The health check will be performed via HTTP. |
|
||||
| https | The health check will be performed via HTTPS. |
|
||||
| both | The health check will be performed via both HTTP and HTTPS. Failing a health check on one protocol will remove the server from the pool of servers only for that protocol. |
|
||||
|
||||
|
||||
<a id="nestedatt--timeouts"></a>
|
||||
### Nested Schema for `timeouts`
|
||||
@@ -75,6 +87,8 @@ Optional:
|
||||
|
||||
Import is supported using the following syntax:
|
||||
|
||||
The [`terraform import` command](https://developer.hashicorp.com/terraform/cli/commands/import) can be used, for example:
|
||||
|
||||
```shell
|
||||
terraform import binarylane_load_balancer.example "<name or id>"
|
||||
```
|
||||
|
||||
@@ -38,11 +38,13 @@ resource "binarylane_server" "example" {
|
||||
|
||||
### Optional
|
||||
|
||||
- `advanced_features` (Attributes) (see [below for nested schema](#nestedatt--advanced_features))
|
||||
- `backups` (Boolean) If `true` this will enable two daily backups for the server. By default, backups are disabled.
|
||||
- `disk` (Number) The total storage in GB for this server. Leave null to accept the default for the size Valid values:
|
||||
- must be a multiple of 5
|
||||
- \> 60 GB must be a multiple of 10
|
||||
- \> 200 GB must be a multiple of 100
|
||||
- `ipv6` (Boolean) If `true` this will add a public and private IPv6 address to the server. By default, IPv6 is disabled.
|
||||
- `memory` (Number) The total memory in MB for this server. Leave null to accept the default size. Valid values:
|
||||
- must be a multiple of 128
|
||||
- \> 2048 MB must be a multiple of 1024
|
||||
@@ -63,7 +65,29 @@ resource "binarylane_server" "example" {
|
||||
- `password_change_supported` (Boolean) If this is true then the `password` attribute can be changed with Terraform. If this is false then the `password` attribute can only be replaced with a null/empty value, which will clear the root/administrator password allowing the password to be changed via the web console.
|
||||
- `permalink` (String) A randomly generated two-word identifier assigned to servers in regions that support this feature
|
||||
- `private_ipv4_addresses` (List of String) The private IPv4 addresses assigned to the server.
|
||||
- `private_ipv6_addresses` (List of String) The private IPv6 addresses assigned to the server.
|
||||
- `public_ipv4_addresses` (List of String) The public IPv4 addresses assigned to the server.
|
||||
- `public_ipv6_addresses` (List of String) The public IPv6 addresses assigned to the server.
|
||||
|
||||
<a id="nestedatt--advanced_features"></a>
|
||||
### Nested Schema for `advanced_features`
|
||||
|
||||
Optional:
|
||||
|
||||
- `driver_disk` (Boolean) When this option is enabled a copy of the KVM driver disc for Windows ("virtio-win.iso") will be attached to your server as a virtual CD. This option can also be used in combination with your own attached backup when installing Windows.
|
||||
- `emulated_devices` (Boolean) When emulated devices is enabled, the KVM specific "VirtIO" disk drive and network devices are removed, and replaced with emulated versions of physical hardware: an old IDE HDD and an Intel E1000 network card. Emulated devices are much slower than the VirtIO devices, and so this option should not be enabled unless absolutely necessary.
|
||||
- `emulated_hyperv` (Boolean) Enable HyperV (a hypervisor produced by Microsoft) support. Enabled by default on Windows servers, generally of no value for non-Windows servers.
|
||||
- `emulated_tpm` (Boolean) When enabled this provides an emulated TPM v1.2 device to your Cloud Server. Warning: the TPM state is not backed up.
|
||||
- `local_rtc` (Boolean) When a server is booted the virtual BIOS receives the current date and time from the host node. The BIOS does not have an explicit timezone, so the timezone used is implicit and must be understood by the operating system. Most operating systems other than Windows expect the time to be UTC since it allows the operating system to control the timezone used when displaying the time. Our Windows installations have also been customized to use UTC, but when using your own installation of Windows this should be set to the host node's local timezone.
|
||||
- `nested_virt` (Boolean) When this option is enabled the functionality necessary to run your own KVM servers within your server is enabled. Note that all the networking limits - one MAC address per VPS, restricted to specific IPs - still apply to public cloud so this feature is generally only useful in combination with Virtual Private Cloud.
|
||||
- `unset_uuid` (Boolean) When this option is NOT enabled a 128-bit unique identifier is exposed to your server through the virtual BIOS. Each server receives a different UUID. Some proprietary licensed software utilize this identifier to "tie" the license to a specific server.
|
||||
|
||||
Read-Only:
|
||||
|
||||
- `cloud_init` (Boolean) When this option is enabled the Cloud Server will be provided a datasource for the cloud-init service.
|
||||
- `qemu_guest_agent` (Boolean) When this option is enabled the server will allow QEMU Guest Agent to perform password reset without rebooting.
|
||||
- `uefi_boot` (Boolean) When this option is enabled the Cloud Server will use UEFI instead of legacy PC BIOS.
|
||||
|
||||
|
||||
<a id="nestedatt--timeouts"></a>
|
||||
### Nested Schema for `timeouts`
|
||||
@@ -77,6 +101,8 @@ Optional:
|
||||
|
||||
Import is supported using the following syntax:
|
||||
|
||||
The [`terraform import` command](https://developer.hashicorp.com/terraform/cli/commands/import) can be used, for example:
|
||||
|
||||
```shell
|
||||
terraform import binarylane_server.example "<server name or id>"
|
||||
```
|
||||
|
||||
@@ -46,8 +46,20 @@ resource "binarylane_server_firewall_rules" "example" {
|
||||
Required:
|
||||
|
||||
- `action` (String) The action to take when there is a match on this rule.
|
||||
|
||||
| Value | Description |
|
||||
| ----- | ----------- |
|
||||
| drop | Traffic matching this rule will be dropped. |
|
||||
| accept | Traffic matching this rule will be accepted. |
|
||||
- `destination_addresses` (List of String) The destination addresses to match for this rule. Each address may be an individual IPv4 address or a range in IPv4 CIDR notation.
|
||||
- `protocol` (String) The protocol to match for this rule.
|
||||
|
||||
| Value | Description |
|
||||
| ----- | ----------- |
|
||||
| all | This rule will match any protocol. |
|
||||
| icmp | This rule will match ICMP traffic only. |
|
||||
| tcp | This rule will match TCP traffic only. |
|
||||
| udp | This rule will match UDP traffic only. |
|
||||
- `source_addresses` (List of String) The source addresses to match for this rule. Each address may be an individual IPv4 address or a range in IPv4 CIDR notation.
|
||||
|
||||
Optional:
|
||||
@@ -59,6 +71,8 @@ Optional:
|
||||
|
||||
Import is supported using the following syntax:
|
||||
|
||||
The [`terraform import` command](https://developer.hashicorp.com/terraform/cli/commands/import) can be used, for example:
|
||||
|
||||
```shell
|
||||
terraform import binarylane_server_firewall_rules.example "<server name or id>"
|
||||
```
|
||||
|
||||
@@ -32,7 +32,7 @@ resource "binarylane_server" "example" {
|
||||
### Required
|
||||
|
||||
- `name` (String) A name to help you identify the key.
|
||||
- `public_key` (String) The public key in OpenSSH "authorized_keys" format.
|
||||
- `public_key` (String) The public key in OpenSSH "authorized_keys" format. This should be a valid public key, such as one generated by `ssh-keygen`.
|
||||
|
||||
### Optional
|
||||
|
||||
@@ -47,6 +47,8 @@ resource "binarylane_server" "example" {
|
||||
|
||||
Import is supported using the following syntax:
|
||||
|
||||
The [`terraform import` command](https://developer.hashicorp.com/terraform/cli/commands/import) can be used, for example:
|
||||
|
||||
```shell
|
||||
terraform import binarylane_ssh_key.example "<SSH Key ID or fingerprint>"
|
||||
```
|
||||
|
||||
@@ -43,6 +43,8 @@ resource "binarylane_server" "example" {
|
||||
|
||||
Import is supported using the following syntax:
|
||||
|
||||
The [`terraform import` command](https://developer.hashicorp.com/terraform/cli/commands/import) can be used, for example:
|
||||
|
||||
```shell
|
||||
terraform import binarylane_vpc.example "<vpc_id>"
|
||||
```
|
||||
|
||||
@@ -67,6 +67,8 @@ Optional:
|
||||
|
||||
Import is supported using the following syntax:
|
||||
|
||||
The [`terraform import` command](https://developer.hashicorp.com/terraform/cli/commands/import) can be used, for example:
|
||||
|
||||
```shell
|
||||
terraform import binarylane_vpc_route_entries.example "<vpc_id>"
|
||||
```
|
||||
|
||||
+1
-1
@@ -6,6 +6,6 @@ In order of increasing complexity, these examples show how to use the provider.
|
||||
- [./offerings](./offerings/main.tf) - Use data sources to list available images, regions, and sizes.
|
||||
- [./ssh](./ssh/main.tf) - Create a server and registers an SSH key as a global default.
|
||||
- [./cloud-init](./cloud-init/main.tf) - Create a server with a cloud-init configuration.
|
||||
- [./k3s](./k3s/main.tf) - Create Kubernetes cluster using k3s.
|
||||
- [./nix](./nix/main.tf) - WIP - Create a server with a NixOS configuration.
|
||||
- [./vpc](./vpc/main.tf) - WIP - Create a server with a Virtual Private Cloud.
|
||||
- [./k3s](./k3s/main.tf) - WIP - Create Kubernetes cluster using k3s.
|
||||
|
||||
@@ -3,10 +3,10 @@ bootcmd:
|
||||
# If you have additional installation steps that need to be awaited, define
|
||||
# these in the `bootcmd` section and they will also be awaited.
|
||||
#
|
||||
- [cloud-init-per, once, 'example-installing', sh, -c, 'sleep 60'] # pretend this is a slow installation step
|
||||
- [cloud-init-per, instance, 'example-installing', sh, -c, 'sleep 60'] # pretend this is a slow installation step
|
||||
- [
|
||||
cloud-init-per,
|
||||
once,
|
||||
instance,
|
||||
'example-done',
|
||||
sh,
|
||||
-c,
|
||||
|
||||
@@ -38,3 +38,4 @@ terraform.rc
|
||||
|
||||
# .kube/config contains credentials
|
||||
.kube
|
||||
.id_ed25519*
|
||||
|
||||
+11
-8
@@ -1,15 +1,18 @@
|
||||
# WIP - examples/k8s
|
||||
# examples/k3s
|
||||
|
||||
This WIP example shows how to create a Kubernetes cluster on Binary Lane.
|
||||
This example shows how to create a K3s cluster on Binary Lane.
|
||||
|
||||
After setting up the cluster by running `terraform apply`, the kubeconfig file will be downloaded to the `.kube/config` file in the current directory. You can then use `kubectl` to interact with the cluster, for example:
|
||||
|
||||
The SSH key used to access the servers is stored in the `.id_ed25519` file. You can use it to SSH into the servers:
|
||||
|
||||
```sh
|
||||
ssh -o "IdentitiesOnly=yes" -i ./.id_ed25519 root@neptune-stand.bnr.la
|
||||
```
|
||||
|
||||
## Prior art
|
||||
|
||||
- [MartinHodges/create_k8s](https://github.com/MartinHodges/create_k8s) repo and the [medium article](https://medium.com/@martin.hodges/creating-a-kubernetes-cluster-from-scratch-in-1-hour-using-automation-a25e387be547) that goes with it.
|
||||
- https://github.com/inscapist/terraform-k3s-private-cloud
|
||||
- https://github.com/schnerring/schnerring.github.io/blob/07d06fb40e3d01f2483a739f516ac4d711a5742c/content/blog/use-terraform-to-deploy-an-azure-kubernetes-service-aks-cluster-traefik-2-cert-manager-and-lets-encrypt-certificates/index.md
|
||||
|
||||
## Remaining TODOs
|
||||
|
||||
- [ ] Consider rewriting module to use `microk8s` instead of `k3s`
|
||||
- [ ] Use `kustomize` instead of `helm`
|
||||
- [ ] Use the `binarylane_load_balancer` resource instead of `kubectl port-forward` (or use the load balancer in another example)
|
||||
- https://github.com/xunleii/terraform-module-k3s
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
#!/bin/bash -x
|
||||
exec >/tmp/k3s-agent-join-debug.log 2>&1
|
||||
|
||||
export K3S_TOKEN="${cluster_token}"
|
||||
export K3S_URL="https://${cluster_server}:6443"
|
||||
|
||||
curl -sfL https://get.k3s.io | sh -s - agent \
|
||||
--node-name="$(hostname -f)"
|
||||
|
||||
unset K3S_TOKEN
|
||||
unset K3S_URL
|
||||
|
||||
# Disable firewall recommended
|
||||
ufw disable
|
||||
|
||||
echo "K3s Node Join Completed"
|
||||
@@ -1,25 +0,0 @@
|
||||
#!/bin/bash -x
|
||||
exec >/tmp/k3s-server-install-debug.log 2>&1
|
||||
|
||||
export INSTALL_K3S_NAME="${cluster_id}"
|
||||
export K3S_TOKEN="${cluster_token}"
|
||||
export K3S_KUBECONFIG_MODE="644"
|
||||
|
||||
curl -sfL https://get.k3s.io | sh -s - server \
|
||||
--node-name="$(hostname -f)"
|
||||
# --disable-cloud-controller \
|
||||
# --disable servicelb \
|
||||
# --disable local-storage \
|
||||
# --disable traefik
|
||||
|
||||
unset INSTALL_K3S_NAME
|
||||
unset K3S_TOKEN
|
||||
unset K3S_KUBECONFIG_MODE
|
||||
|
||||
echo "Installing Helm"
|
||||
curl -sfL https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 | bash
|
||||
|
||||
# Disable firewall recommended
|
||||
ufw disable
|
||||
|
||||
echo "K3s Setup Completed"
|
||||
@@ -0,0 +1,50 @@
|
||||
module "k3s" {
|
||||
# source = "xunleii/k3s/module" # Uncomment after https://github.com/xunleii/terraform-module-k3s/pull/207 is merged
|
||||
source = "github.com/dvdmuckle/terraform-module-k3s?ref=62dca7731b78f1120a141a2703e3ed14470276c0"
|
||||
|
||||
depends_on_ = binarylane_server.agents
|
||||
k3s_version = "latest"
|
||||
cluster_domain = "cluster.local"
|
||||
managed_fields = ["label"]
|
||||
|
||||
// These subnets are used by the Flannel network interface in K3s, and are NOT the same as the VPC address space
|
||||
cidr = {
|
||||
pods = "10.42.0.0/16",
|
||||
services = "10.43.0.0/16",
|
||||
}
|
||||
|
||||
servers = {
|
||||
for i in range(length(binarylane_server.servers)) :
|
||||
binarylane_server.servers[i].name => {
|
||||
ip = binarylane_server.servers[i].private_ipv4_addresses[0]
|
||||
name = binarylane_server.servers[i].name
|
||||
connection = {
|
||||
host = binarylane_server.servers[i].permalink
|
||||
private_key = trimspace(tls_private_key.ed25519_provisioning.private_key_pem)
|
||||
}
|
||||
labels = { "node.kubernetes.io/type" = "master" }
|
||||
flags = [
|
||||
"--tls-san ${binarylane_server.servers[0].private_ipv4_addresses[0]}",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
agents = {
|
||||
for i in range(length(binarylane_server.agents)) :
|
||||
binarylane_server.agents[i].name => {
|
||||
ip = binarylane_server.agents[i].private_ipv4_addresses[0]
|
||||
name = binarylane_server.agents[i].name
|
||||
connection = {
|
||||
host = binarylane_server.agents[i].permalink
|
||||
private_key = trimspace(tls_private_key.ed25519_provisioning.private_key_pem)
|
||||
}
|
||||
labels = { "node.kubernetes.io/pool" = "general" }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource "local_sensitive_file" "kube_config" {
|
||||
content = module.k3s.kube_config
|
||||
filename = ".kube/config"
|
||||
file_permission = "0644"
|
||||
}
|
||||
+28
-69
@@ -1,100 +1,60 @@
|
||||
locals {
|
||||
cluster_id = "tf-example-k8s"
|
||||
custom_domain = "tf-example-k8s.internal"
|
||||
cluster_id = "tf-example-k3s"
|
||||
custom_domain = "tf-example-k3s.internal"
|
||||
}
|
||||
|
||||
resource "random_password" "binarylane" {
|
||||
length = 18
|
||||
}
|
||||
|
||||
resource "random_password" "cluster_token" {
|
||||
length = 64
|
||||
special = false
|
||||
}
|
||||
|
||||
# SSH Key
|
||||
# -------
|
||||
resource "tls_private_key" "ed25519_provisioning" {
|
||||
algorithm = "ED25519"
|
||||
}
|
||||
|
||||
resource "local_sensitive_file" "ssh_private_key" {
|
||||
content = tls_private_key.ed25519_provisioning.private_key_openssh
|
||||
filename = ".id_ed25519"
|
||||
file_permission = "0600"
|
||||
}
|
||||
|
||||
resource "local_file" "ssh_public_key" {
|
||||
content = tls_private_key.ed25519_provisioning.public_key_openssh
|
||||
filename = ".id_ed25519.pub"
|
||||
file_permission = "0644"
|
||||
}
|
||||
|
||||
resource "binarylane_ssh_key" "example" {
|
||||
name = "tf-example-k8s"
|
||||
public_key = file("~/.ssh/id_ed25519.pub")
|
||||
name = "tf-example-k3s"
|
||||
public_key = tls_private_key.ed25519_provisioning.public_key_openssh
|
||||
}
|
||||
|
||||
# Virtual Private Cloud
|
||||
# ---------------------
|
||||
resource "binarylane_vpc" "example" {
|
||||
name = local.cluster_id
|
||||
ip_range = "10.240.0.0/16"
|
||||
ip_range = "10.0.0.0/8"
|
||||
}
|
||||
|
||||
# k3s Servers
|
||||
# -----------
|
||||
data "cloudinit_config" "server" {
|
||||
gzip = false
|
||||
base64_encode = false
|
||||
|
||||
part {
|
||||
content_type = "text/x-shellscript"
|
||||
content = templatefile("${path.module}/k3s-server-install.sh", {
|
||||
cluster_id = local.cluster_id,
|
||||
cluster_token = random_password.cluster_token.result,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
resource "binarylane_server" "server" {
|
||||
resource "binarylane_server" "servers" {
|
||||
count = 1
|
||||
|
||||
name = "${local.cluster_id}-server-${count.index + 1}"
|
||||
region = "per"
|
||||
image = "ubuntu-24.04"
|
||||
size = "std-min"
|
||||
size = "std-1vcpu" # 2GB memory, 1 vCPU
|
||||
password = random_password.binarylane.result
|
||||
ssh_keys = [binarylane_ssh_key.example.id]
|
||||
vpc_id = binarylane_vpc.example.id
|
||||
public_ipv4_count = 1
|
||||
user_data = sensitive(data.cloudinit_config.server.rendered)
|
||||
}
|
||||
|
||||
data "external" "kubeconfig" {
|
||||
program = [
|
||||
"/usr/bin/ssh",
|
||||
"-o UserKnownHostsFile=/dev/null",
|
||||
"-o StrictHostKeyChecking=no",
|
||||
"root@${binarylane_server.server.0.permalink}",
|
||||
"echo '{\"kubeconfig\":\"'$(cat /etc/rancher/k3s/k3s.yaml | base64)'\"}'",
|
||||
]
|
||||
}
|
||||
|
||||
resource "local_sensitive_file" "kubeconfig" {
|
||||
depends_on = [binarylane_server.server]
|
||||
|
||||
content = replace(
|
||||
base64decode(
|
||||
replace(data.external.kubeconfig.result.kubeconfig, " ", "")
|
||||
),
|
||||
"server: https://127.0.0.1:6443",
|
||||
"server: https://${binarylane_server.server.0.permalink}:6443",
|
||||
)
|
||||
filename = "${path.module}/.kube/config"
|
||||
file_permission = "0600"
|
||||
}
|
||||
|
||||
# k3s Agents
|
||||
# ----------
|
||||
data "cloudinit_config" "agent" {
|
||||
gzip = false
|
||||
base64_encode = false
|
||||
|
||||
part {
|
||||
content_type = "text/x-shellscript"
|
||||
content = templatefile("${path.module}/k3s-agent-join.sh", {
|
||||
cluster_token = random_password.cluster_token.result,
|
||||
cluster_server = binarylane_server.server.0.private_ipv4_addresses.0
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
resource "binarylane_server" "agent" {
|
||||
resource "binarylane_server" "agents" {
|
||||
count = 2
|
||||
|
||||
name = "${local.cluster_id}-agent-${count.index + 1}"
|
||||
@@ -105,12 +65,11 @@ resource "binarylane_server" "agent" {
|
||||
ssh_keys = [binarylane_ssh_key.example.id]
|
||||
vpc_id = binarylane_vpc.example.id
|
||||
public_ipv4_count = 1
|
||||
user_data = sensitive(data.cloudinit_config.agent.rendered)
|
||||
}
|
||||
|
||||
# Virtual Private Cloud Routing
|
||||
# -----------------------------
|
||||
resource "binarylane_vpc_route_entries" "example" {
|
||||
resource "binarylane_vpc_route_entries" "example" { # TODO
|
||||
vpc_id = binarylane_vpc.example.id
|
||||
route_entries = [
|
||||
# {
|
||||
@@ -122,12 +81,12 @@ resource "binarylane_vpc_route_entries" "example" {
|
||||
}
|
||||
|
||||
locals {
|
||||
agent_ips = flatten([for _, a in binarylane_server.agent : a.private_ipv4_addresses])
|
||||
server_ips = flatten([for _, s in binarylane_server.server : s.private_ipv4_addresses])
|
||||
agent_ips = flatten([for _, a in binarylane_server.agents : a.private_ipv4_addresses])
|
||||
server_ips = flatten([for _, s in binarylane_server.servers : s.private_ipv4_addresses])
|
||||
}
|
||||
|
||||
resource "binarylane_server_firewall_rules" "example" {
|
||||
for_each = { for server in concat(binarylane_server.server, binarylane_server.agent) : server.name => server }
|
||||
for_each = { for server in concat(binarylane_server.servers, binarylane_server.agents) : server.name => server }
|
||||
|
||||
server_id = each.value.id
|
||||
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
resource "kubectl_manifest" "hello" {
|
||||
yaml_body = <<YAML
|
||||
apiVersion: apps/v1
|
||||
kind: DaemonSet
|
||||
metadata:
|
||||
name: nginx-hello
|
||||
labels:
|
||||
app: nginx-hello
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app: nginx-hello
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: nginx-hello
|
||||
spec:
|
||||
containers:
|
||||
- image: nginxdemos/hello
|
||||
name: nginx-hello
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 8080
|
||||
protocol: TCP
|
||||
YAML
|
||||
}
|
||||
|
||||
resource "kubectl_manifest" "hello_service" {
|
||||
yaml_body = <<YAML
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: nginx-hello
|
||||
labels:
|
||||
app: nginx-hello
|
||||
spec:
|
||||
type: ClusterIP
|
||||
selector:
|
||||
app: nginx-hello
|
||||
ports:
|
||||
- port: 80
|
||||
YAML
|
||||
}
|
||||
|
||||
resource "kubectl_manifest" "hello_ingress" {
|
||||
yaml_body = <<YAML
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: nginx-hello
|
||||
spec:
|
||||
rules:
|
||||
- host: "*.bnr.la"
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: nginx-hello
|
||||
port:
|
||||
number: 80
|
||||
YAML
|
||||
}
|
||||
@@ -3,25 +3,7 @@ terraform {
|
||||
binarylane = {
|
||||
source = "oscarhermoso/binarylane"
|
||||
}
|
||||
kubectl = {
|
||||
source = "alekc/kubectl"
|
||||
version = ">= 2.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "binarylane" {}
|
||||
|
||||
provider "helm" {
|
||||
kubernetes {
|
||||
host = "${binarylane_server.server.0.permalink}:6443"
|
||||
config_path = local_sensitive_file.kubeconfig.filename
|
||||
insecure = true # TODO
|
||||
}
|
||||
}
|
||||
|
||||
provider "kubectl" {
|
||||
host = "${binarylane_server.server.0.permalink}:6443"
|
||||
config_path = local_sensitive_file.kubeconfig.filename
|
||||
insecure = true # TODO
|
||||
}
|
||||
|
||||
+5
-4
@@ -1,9 +1,10 @@
|
||||
package main
|
||||
|
||||
//go:generate ./internal/binarylane/fetch-openapi.sh
|
||||
//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=internal/binarylane/client.cfg.yml internal/binarylane/openapi.json
|
||||
//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=internal/binarylane/types.cfg.yml internal/binarylane/openapi.json
|
||||
//go:generate go run github.com/hashicorp/terraform-plugin-codegen-openapi/cmd/tfplugingen-openapi generate --config=./provider_gen_config.yml internal/binarylane/openapi.json --output=./provider_code_spec.json
|
||||
//go:generate ./scripts/fetch-openapi.sh
|
||||
//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=internal/binarylane/client.cfg.yml ./openapi.json
|
||||
//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=internal/binarylane/types.cfg.yml ./openapi.json
|
||||
//go:generate go run github.com/hashicorp/terraform-plugin-codegen-openapi/cmd/tfplugingen-openapi generate --config=./provider_gen_config.yml ./openapi.json --output=./provider_code_spec.json
|
||||
//go:generate ./scripts/extend-provider.sh
|
||||
//go:generate mkdir -p internal/resources internal/data_sources
|
||||
//go:generate go run github.com/hashicorp/terraform-plugin-codegen-framework/cmd/tfplugingen-framework generate resources --input=./provider_code_spec.json --output=./internal/resources --package=resources
|
||||
//go:generate go run github.com/hashicorp/terraform-plugin-codegen-framework/cmd/tfplugingen-framework generate data-sources --input=./provider_code_spec.json --output=./internal/data_sources --package=data_sources
|
||||
|
||||
@@ -1,20 +1,22 @@
|
||||
module terraform-provider-binarylane
|
||||
|
||||
go 1.22.7
|
||||
go 1.23.7
|
||||
|
||||
toolchain go1.24.1
|
||||
|
||||
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.20.1
|
||||
github.com/hashicorp/terraform-plugin-framework v1.13.0
|
||||
github.com/hashicorp/terraform-plugin-docs v0.22.0
|
||||
github.com/hashicorp/terraform-plugin-framework v1.15.1
|
||||
github.com/hashicorp/terraform-plugin-framework-timeouts v0.5.0
|
||||
github.com/hashicorp/terraform-plugin-framework-validators v0.16.0
|
||||
github.com/hashicorp/terraform-plugin-go v0.26.0
|
||||
github.com/hashicorp/terraform-plugin-framework-validators v0.18.0
|
||||
github.com/hashicorp/terraform-plugin-go v0.28.0
|
||||
github.com/hashicorp/terraform-plugin-log v0.9.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
|
||||
github.com/hashicorp/terraform-plugin-testing v1.13.3
|
||||
github.com/oapi-codegen/oapi-codegen/v2 v2.5.0
|
||||
github.com/oapi-codegen/runtime v1.1.2
|
||||
)
|
||||
|
||||
require (
|
||||
@@ -23,53 +25,52 @@ require (
|
||||
github.com/Masterminds/goutils v1.1.1 // indirect
|
||||
github.com/Masterminds/semver/v3 v3.2.1 // indirect
|
||||
github.com/Masterminds/sprig/v3 v3.2.3 // indirect
|
||||
github.com/ProtonMail/go-crypto v1.1.0-alpha.2 // indirect
|
||||
github.com/ProtonMail/go-crypto v1.1.6 // indirect
|
||||
github.com/agext/levenshtein v1.2.2 // indirect
|
||||
github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect
|
||||
github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect
|
||||
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.7.1 // indirect
|
||||
github.com/bmatcuk/doublestar/v4 v4.8.1 // indirect
|
||||
github.com/buger/jsonparser v1.1.1 // indirect
|
||||
github.com/cloudflare/circl v1.3.7 // indirect
|
||||
github.com/cloudflare/circl v1.6.1 // indirect
|
||||
github.com/dprotaso/go-yit v0.0.0-20220510233725-9ba8df137936 // indirect
|
||||
github.com/fatih/color v1.18.0 // indirect
|
||||
github.com/frankban/quicktest v1.14.6 // indirect
|
||||
github.com/fsnotify/fsnotify v1.5.4 // indirect
|
||||
github.com/getkin/kin-openapi v0.127.0 // indirect
|
||||
github.com/getkin/kin-openapi v0.132.0 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.21.0 // indirect
|
||||
github.com/go-openapi/swag v0.23.0 // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/google/go-cmp v0.6.0 // indirect
|
||||
github.com/google/go-cmp v0.7.0 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/hashicorp/cli v1.1.6 // indirect
|
||||
github.com/hashicorp/cli v1.1.7 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-checkpoint v0.5.0 // indirect
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||
github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 // indirect
|
||||
github.com/hashicorp/go-cty v1.5.0 // indirect
|
||||
github.com/hashicorp/go-hclog v1.6.3 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/hashicorp/go-plugin v1.6.2 // indirect
|
||||
github.com/hashicorp/go-plugin v1.6.3 // indirect
|
||||
github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
|
||||
github.com/hashicorp/go-uuid v1.0.3 // indirect
|
||||
github.com/hashicorp/go-version v1.7.0 // indirect
|
||||
github.com/hashicorp/hc-install v0.9.0 // indirect
|
||||
github.com/hashicorp/hc-install v0.9.2 // indirect
|
||||
github.com/hashicorp/hcl/v2 v2.23.0 // indirect
|
||||
github.com/hashicorp/logutils v1.0.0 // indirect
|
||||
github.com/hashicorp/terraform-exec v0.21.0 // indirect
|
||||
github.com/hashicorp/terraform-json v0.23.0 // indirect
|
||||
github.com/hashicorp/terraform-exec v0.23.0 // indirect
|
||||
github.com/hashicorp/terraform-json v0.25.0 // indirect
|
||||
github.com/hashicorp/terraform-plugin-codegen-spec v0.2.0 // indirect
|
||||
github.com/hashicorp/terraform-plugin-sdk/v2 v2.35.0 // indirect
|
||||
github.com/hashicorp/terraform-registry-address v0.2.4 // indirect
|
||||
github.com/hashicorp/terraform-plugin-sdk/v2 v2.37.0 // indirect
|
||||
github.com/hashicorp/terraform-registry-address v0.3.0 // indirect
|
||||
github.com/hashicorp/terraform-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.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
|
||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.15 // indirect
|
||||
github.com/mitchellh/copystructure v1.2.0 // indirect
|
||||
@@ -78,14 +79,17 @@ require (
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
|
||||
github.com/oklog/run v1.1.0 // indirect
|
||||
github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 // indirect
|
||||
github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 // indirect
|
||||
github.com/oklog/run v1.2.0 // indirect
|
||||
github.com/onsi/gomega v1.33.1 // indirect
|
||||
github.com/pb33f/libopenapi v0.15.0 // indirect
|
||||
github.com/perimeterx/marshmallow v1.1.5 // indirect
|
||||
github.com/posener/complete v1.2.3 // indirect
|
||||
github.com/rivo/uniseg v0.2.0 // indirect
|
||||
github.com/shopspring/decimal v1.3.1 // indirect
|
||||
github.com/speakeasy-api/openapi-overlay v0.9.0 // indirect
|
||||
github.com/speakeasy-api/jsonpath v0.6.0 // indirect
|
||||
github.com/speakeasy-api/openapi-overlay v0.10.2 // indirect
|
||||
github.com/spf13/cast v1.5.1 // indirect
|
||||
github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect
|
||||
github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect
|
||||
@@ -97,20 +101,20 @@ require (
|
||||
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
|
||||
github.com/yuin/goldmark v1.7.7 // indirect
|
||||
github.com/yuin/goldmark-meta v1.1.0 // indirect
|
||||
github.com/zclconf/go-cty v1.15.0 // indirect
|
||||
github.com/zclconf/go-cty v1.16.3 // indirect
|
||||
go.abhg.dev/goldmark/frontmatter v0.2.0 // indirect
|
||||
golang.org/x/crypto v0.32.0 // indirect
|
||||
golang.org/x/crypto v0.40.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20240409090435-93d18d7e34b8 // indirect
|
||||
golang.org/x/mod v0.21.0 // indirect
|
||||
golang.org/x/net v0.34.0 // indirect
|
||||
golang.org/x/sync v0.10.0 // indirect
|
||||
golang.org/x/sys v0.29.0 // indirect
|
||||
golang.org/x/text v0.21.0 // indirect
|
||||
golang.org/x/tools v0.22.0 // indirect
|
||||
golang.org/x/mod v0.25.0 // indirect
|
||||
golang.org/x/net v0.42.0 // indirect
|
||||
golang.org/x/sync v0.16.0 // indirect
|
||||
golang.org/x/sys v0.34.0 // indirect
|
||||
golang.org/x/text v0.27.0 // indirect
|
||||
golang.org/x/tools v0.34.0 // indirect
|
||||
google.golang.org/appengine v1.6.8 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 // indirect
|
||||
google.golang.org/grpc v1.69.4 // indirect
|
||||
google.golang.org/protobuf v1.36.3 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250728155136-f173205681a0 // indirect
|
||||
google.golang.org/grpc v1.74.2 // indirect
|
||||
google.golang.org/protobuf v1.36.6 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
@@ -11,10 +11,10 @@ github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0
|
||||
github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=
|
||||
github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA=
|
||||
github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM=
|
||||
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
|
||||
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
|
||||
github.com/ProtonMail/go-crypto v1.1.0-alpha.2 h1:bkyFVUP+ROOARdgCiJzNQo2V2kiB97LyUpzH9P6Hrlg=
|
||||
github.com/ProtonMail/go-crypto v1.1.0-alpha.2/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE=
|
||||
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
|
||||
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
||||
github.com/ProtonMail/go-crypto v1.1.6 h1:ZcV+Ropw6Qn0AX9brlQLAUXfqLBc7Bl+f/DmNxpLfdw=
|
||||
github.com/ProtonMail/go-crypto v1.1.6/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE=
|
||||
github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk=
|
||||
github.com/agext/levenshtein v1.2.2 h1:0S/Yg6LYmFJ5stwQeRp6EeOcCbj7xiqQSdNelsXvaqE=
|
||||
github.com/agext/levenshtein v1.2.2/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558=
|
||||
@@ -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.7.1 h1:fdDeAqgT47acgwd9bd9HxJRDmc9UAmPpc+2m0CXv75Q=
|
||||
github.com/bmatcuk/doublestar/v4 v4.7.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
|
||||
github.com/bmatcuk/doublestar/v4 v4.8.1 h1:54Bopc5c2cAvhLRAzqOGCYHYyhcDHsFF4wWIR5wKP38=
|
||||
github.com/bmatcuk/doublestar/v4 v4.8.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
|
||||
github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA=
|
||||
github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8=
|
||||
github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs=
|
||||
@@ -39,11 +39,11 @@ github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx2
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU=
|
||||
github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA=
|
||||
github.com/cloudflare/circl v1.6.1 h1:zqIqSPIndyBh1bjLVVDHMPpVKqp8Su/V+6MeDzzQBQ0=
|
||||
github.com/cloudflare/circl v1.6.1/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg=
|
||||
github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
|
||||
github.com/cyphar/filepath-securejoin v0.4.1 h1:JyxxyPEaktOD+GAnqIqTf9A8tHyAG22rowi7HkoSU1s=
|
||||
github.com/cyphar/filepath-securejoin v0.4.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
@@ -63,16 +63,16 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI=
|
||||
github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
|
||||
github.com/getkin/kin-openapi v0.127.0 h1:Mghqi3Dhryf3F8vR370nN67pAERW+3a95vomb3MAREY=
|
||||
github.com/getkin/kin-openapi v0.127.0/go.mod h1:OZrfXzUfGrNbsKj+xmFBx6E5c6yH3At/tAKSc2UszXM=
|
||||
github.com/getkin/kin-openapi v0.132.0 h1:3ISeLMsQzcb5v26yeJrBcdTCEQTag36ZjaGk7MIRUwk=
|
||||
github.com/getkin/kin-openapi v0.132.0/go.mod h1:3OlG51PCYNsPByuiMB0t4fjnNlIDnaEDsjiKUV8nL58=
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
|
||||
github.com/go-git/go-billy/v5 v5.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-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
||||
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-git/go-billy/v5 v5.6.2 h1:6Q86EsPXMa7c3YZ3aLAQsMA0VlWmy43r6FHqa/UNbRM=
|
||||
github.com/go-git/go-billy/v5 v5.6.2/go.mod h1:rcFC2rAsp/erv7CMz9GczHcuD0D32fWzH+MJAU+jaUU=
|
||||
github.com/go-git/go-git/v5 v5.14.0 h1:/MD3lCrGjCen5WfEAzKg00MJJffKhC8gzS80ycmCi60=
|
||||
github.com/go-git/go-git/v5 v5.14.0/go.mod h1:Z5Xhoia5PcWA3NF8vRLURn9E5FRhSl7dGj9ItW3Wk5k=
|
||||
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
|
||||
@@ -82,8 +82,8 @@ github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ
|
||||
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=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ=
|
||||
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw=
|
||||
github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
@@ -101,14 +101,14 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/hashicorp/cli v1.1.6 h1:CMOV+/LJfL1tXCOKrgAX0uRKnzjj/mpmqNXloRSy2K8=
|
||||
github.com/hashicorp/cli v1.1.6/go.mod h1:MPon5QYlgjjo0BSoAiN0ESeT5fRzDjVRp+uioJ0piz4=
|
||||
github.com/hashicorp/cli v1.1.7 h1:/fZJ+hNdwfTSfsxMBa9WWMlfjUZbX8/LnUxgAd7lCVU=
|
||||
github.com/hashicorp/cli v1.1.7/go.mod h1:e6Mfpga9OCT1vqzFuoGZiiF/KaG9CbUfO5s3ghU3YgU=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
|
||||
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
@@ -117,15 +117,15 @@ github.com/hashicorp/go-checkpoint v0.5.0/go.mod h1:7nfLNL10NsxqO4iWuW6tWW0HjZuD
|
||||
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
|
||||
github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 h1:1/D3zfFHttUKaCaGKZ/dR2roBXv0vKbSCnssIldfQdI=
|
||||
github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320/go.mod h1:EiZBMaudVLy8fmjf9Npq1dq9RalhveqZG5w/yz3mHWs=
|
||||
github.com/hashicorp/go-cty v1.5.0 h1:EkQ/v+dDNUqnuVpmS5fPqyY71NXVgT5gf32+57xY8g0=
|
||||
github.com/hashicorp/go-cty v1.5.0/go.mod h1:lFUCG5kd8exDobgSfyj4ONE/dc822kiYMguVKdHGMLM=
|
||||
github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k=
|
||||
github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
|
||||
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
|
||||
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
|
||||
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
||||
github.com/hashicorp/go-plugin v1.6.2 h1:zdGAEd0V1lCaU0u+MxWQhtSDQmahpkwOun8U8EiRVog=
|
||||
github.com/hashicorp/go-plugin v1.6.2/go.mod h1:CkgLQ5CZqNmdL9U9JzM532t8ZiYQ35+pj3b1FD37R0Q=
|
||||
github.com/hashicorp/go-plugin v1.6.3 h1:xgHB+ZUSYeuJi96WtxEjzi23uh7YQpznjGh0U0UUrwg=
|
||||
github.com/hashicorp/go-plugin v1.6.3/go.mod h1:MRobyh+Wc/nYy1V4KAXUiYfzxoYhs7V1mlH1Z7iY2h0=
|
||||
github.com/hashicorp/go-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=
|
||||
@@ -133,40 +133,40 @@ 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.9.0 h1:2dIk8LcvANwtv3QZLckxcjyF5w8KVtiMxu6G6eLhghE=
|
||||
github.com/hashicorp/hc-install v0.9.0/go.mod h1:+6vOP+mf3tuGgMApVYtmsnDoKWMDcFXeTxCACYZ8SFg=
|
||||
github.com/hashicorp/hc-install v0.9.2 h1:v80EtNX4fCVHqzL9Lg/2xkp62bbvQMnvPQ0G+OmtO24=
|
||||
github.com/hashicorp/hc-install v0.9.2/go.mod h1:XUqBQNnuT4RsxoxiM9ZaUk0NX8hi2h+Lb6/c0OZnC/I=
|
||||
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.23.0 h1:sniCkExU4iKtTADReHzACkk8fnpQXrdD2xoR+lppBkI=
|
||||
github.com/hashicorp/terraform-json v0.23.0/go.mod h1:MHdXbBAbSg0GvzuWazEGKAn/cyNfIB7mN6y7KJN6y2c=
|
||||
github.com/hashicorp/terraform-exec v0.23.0 h1:MUiBM1s0CNlRFsCLJuM5wXZrzA3MnPYEsiXmzATMW/I=
|
||||
github.com/hashicorp/terraform-exec v0.23.0/go.mod h1:mA+qnx1R8eePycfwKkCRk3Wy65mwInvlpAeOwmA7vlY=
|
||||
github.com/hashicorp/terraform-json v0.25.0 h1:rmNqc/CIfcWawGiwXmRuiXJKEiJu1ntGoxseG1hLhoQ=
|
||||
github.com/hashicorp/terraform-json v0.25.0/go.mod h1:sMKS8fiRDX4rVlR6EJUMudg1WcanxCMoWwTLkgZP/vc=
|
||||
github.com/hashicorp/terraform-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.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-docs v0.22.0 h1:fwIDStbFel1PPNkM+mDPnpB4efHZBdGoMz/zt5FbTDw=
|
||||
github.com/hashicorp/terraform-plugin-docs v0.22.0/go.mod h1:55DJVyZ7BNK4t/lANcQ1YpemRuS6KsvIO1BbGA+xzGE=
|
||||
github.com/hashicorp/terraform-plugin-framework v1.15.1 h1:2mKDkwb8rlx/tvJTlIcpw0ykcmvdWv+4gY3SIgk8Pq8=
|
||||
github.com/hashicorp/terraform-plugin-framework v1.15.1/go.mod h1:hxrNI/GY32KPISpWqlCoTLM9JZsGH3CyYlir09bD/fI=
|
||||
github.com/hashicorp/terraform-plugin-framework-timeouts v0.5.0 h1:I/N0g/eLZ1ZkLZXUQ0oRSXa8YG/EF0CEuQP1wXdrzKw=
|
||||
github.com/hashicorp/terraform-plugin-framework-timeouts v0.5.0/go.mod h1:t339KhmxnaF4SzdpxmqW8HnQBHVGYazwtfxU0qCs4eE=
|
||||
github.com/hashicorp/terraform-plugin-framework-validators v0.16.0 h1:O9QqGoYDzQT7lwTXUsZEtgabeWW96zUBh47Smn2lkFA=
|
||||
github.com/hashicorp/terraform-plugin-framework-validators v0.16.0/go.mod h1:Bh89/hNmqsEWug4/XWKYBwtnw3tbz5BAy1L1OgvbIaY=
|
||||
github.com/hashicorp/terraform-plugin-go v0.26.0 h1:cuIzCv4qwigug3OS7iKhpGAbZTiypAfFQmw8aE65O2M=
|
||||
github.com/hashicorp/terraform-plugin-go v0.26.0/go.mod h1:+CXjuLDiFgqR+GcrM5a2E2Kal5t5q2jb0E3D57tTdNY=
|
||||
github.com/hashicorp/terraform-plugin-framework-validators v0.18.0 h1:OQnlOt98ua//rCw+QhBbSqfW3QbwtVrcdWeQN5gI3Hw=
|
||||
github.com/hashicorp/terraform-plugin-framework-validators v0.18.0/go.mod h1:lZvZvagw5hsJwuY7mAY6KUz45/U6fiDR0CzQAwWD0CA=
|
||||
github.com/hashicorp/terraform-plugin-go v0.28.0 h1:zJmu2UDwhVN0J+J20RE5huiF3XXlTYVIleaevHZgKPA=
|
||||
github.com/hashicorp/terraform-plugin-go v0.28.0/go.mod h1:FDa2Bb3uumkTGSkTFpWSOwWJDwA7bf3vdP3ltLDTH6o=
|
||||
github.com/hashicorp/terraform-plugin-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.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.4 h1:JXu/zHB2Ymg/TGVCRu10XqNa4Sh2bWcqCNyKWjnCPJA=
|
||||
github.com/hashicorp/terraform-registry-address v0.2.4/go.mod h1:tUNYTVyCtU4OIGXXMDp7WNcJ+0W1B4nmstVDgHMjfAU=
|
||||
github.com/hashicorp/terraform-plugin-sdk/v2 v2.37.0 h1:NFPMacTrY/IdcIcnUB+7hsore1ZaRWU9cnB6jFoBnIM=
|
||||
github.com/hashicorp/terraform-plugin-sdk/v2 v2.37.0/go.mod h1:QYmYnLfsosrxjCnGY1p9c7Zj6n9thnEE+7RObeYs3fA=
|
||||
github.com/hashicorp/terraform-plugin-testing v1.13.3 h1:QLi/khB8Z0a5L54AfPrHukFpnwsGL8cwwswj4RZduCo=
|
||||
github.com/hashicorp/terraform-plugin-testing v1.13.3/go.mod h1:WHQ9FDdiLoneey2/QHpGM/6SAYf4A7AZazVg7230pLE=
|
||||
github.com/hashicorp/terraform-registry-address v0.3.0 h1:HMpK3nqaGFPS9VmgRXrJL/dzHNdheGVKk5k7VlFxzCo=
|
||||
github.com/hashicorp/terraform-registry-address v0.3.0/go.mod h1:jRGCMiLaY9zii3GLC7hqpSnwhfnCN5yzvY0hh4iCGbM=
|
||||
github.com/hashicorp/terraform-svchost v0.1.1 h1:EZZimZ1GxdqFRinZ1tpJwVxxt49xc/S52uzrw4x0jKQ=
|
||||
github.com/hashicorp/terraform-svchost v0.1.1/go.mod h1:mNsjQfZyf/Jhz35v6/0LWcv26+X7JPS+buii2c9/ctc=
|
||||
github.com/hashicorp/yamux v0.1.2 h1:XtB8kyFOyHXYVFnwT5C3+Bdo8gArse7j2AQ0DA0Uey8=
|
||||
@@ -179,8 +179,6 @@ 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.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=
|
||||
@@ -201,11 +199,10 @@ github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0
|
||||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
|
||||
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
|
||||
@@ -227,12 +224,16 @@ github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwd
|
||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
||||
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
||||
github.com/oapi-codegen/oapi-codegen/v2 v2.4.1 h1:ykgG34472DWey7TSjd8vIfNykXgjOgYJZoQbKfEeY/Q=
|
||||
github.com/oapi-codegen/oapi-codegen/v2 v2.4.1/go.mod h1:N5+lY1tiTDV3V1BeHtOxeWXHoPVeApvsvjJqegfoaz8=
|
||||
github.com/oapi-codegen/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=
|
||||
github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU=
|
||||
github.com/oapi-codegen/oapi-codegen/v2 v2.5.0 h1:iJvF8SdB/3/+eGOXEpsWkD8FQAHj6mqkb6Fnsoc8MFU=
|
||||
github.com/oapi-codegen/oapi-codegen/v2 v2.5.0/go.mod h1:fwlMxUEMuQK5ih9aymrxKPQqNm2n8bdLk1ppjH+lr9w=
|
||||
github.com/oapi-codegen/runtime v1.1.2 h1:P2+CubHq8fO4Q6fV1tqDBZHCwpVpvPg7oKiYzQgXIyI=
|
||||
github.com/oapi-codegen/runtime v1.1.2/go.mod h1:SK9X900oXmPWilYR5/WKPzt3Kqxn/uS/+lbpREv+eCg=
|
||||
github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 h1:G7ERwszslrBzRxj//JalHPu/3yz+De2J+4aLtSRlHiY=
|
||||
github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037/go.mod h1:2bpvgLBZEtENV5scfDFEtB/5+1M4hkQhDQrccEJ/qGw=
|
||||
github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 h1:bQx3WeLcUWy+RletIKwUIt4x3t8n2SxavmoclizMb8c=
|
||||
github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90/go.mod h1:y5+oSEHCPT/DGrS++Wc/479ERge0zTFxaF8PbGKcg2o=
|
||||
github.com/oklog/run v1.2.0 h1:O8x3yXwah4A73hJdlrwo/2X6J62gE5qTMusH0dvz60E=
|
||||
github.com/oklog/run v1.2.0/go.mod h1:mgDbKRSwPhJfesJ4PntqFUbKQRZ50NgmZTSPlFA0YFk=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.10.2/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||
@@ -250,8 +251,8 @@ github.com/pb33f/libopenapi v0.15.0 h1:AoBYIY3HXqDDF8O9kcudlqWaRFZZJmgtueE649oHz
|
||||
github.com/pb33f/libopenapi v0.15.0/go.mod h1:m+4Pwri31UvcnZjuP8M7TlbR906DXJmMvYsbis234xg=
|
||||
github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s=
|
||||
github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw=
|
||||
github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4=
|
||||
github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI=
|
||||
github.com/pjbgf/sha1cd v0.3.2 h1:a9wb0bp1oC2TGwStyn0Umc/IGKQnEgF0vVaZ8QF8eo4=
|
||||
github.com/pjbgf/sha1cd v0.3.2/go.mod h1:zQWigSxVmsHEZow5qaLtPYxpcKMMQpa09ixqBxuCS6A=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
@@ -260,18 +261,20 @@ 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.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
|
||||
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
|
||||
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
|
||||
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
|
||||
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
|
||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
|
||||
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
||||
github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8=
|
||||
github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
||||
github.com/skeema/knownhosts v1.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/skeema/knownhosts v1.3.1 h1:X2osQ+RAjK76shCbvhHHHVl3ZlgDm8apHEHFqRjnBY8=
|
||||
github.com/skeema/knownhosts v1.3.1/go.mod h1:r7KTdC8l4uxWRyK2TpQZ/1o5HaSzh06ePQNxPwTcfiY=
|
||||
github.com/speakeasy-api/jsonpath v0.6.0 h1:IhtFOV9EbXplhyRqsVhHoBmmYjblIRh5D1/g8DHMXJ8=
|
||||
github.com/speakeasy-api/jsonpath v0.6.0/go.mod h1:ymb2iSkyOycmzKwbEAYPJV/yi2rSmvBCLZJcyD+VVWw=
|
||||
github.com/speakeasy-api/openapi-overlay v0.10.2 h1:VOdQ03eGKeiHnpb1boZCGm7x8Haj6gST0P3SGTX95GU=
|
||||
github.com/speakeasy-api/openapi-overlay v0.10.2/go.mod h1:n0iOU7AqKpNFfEt6tq7qYITC4f0yzVVdFw0S7hukemg=
|
||||
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA=
|
||||
github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48=
|
||||
@@ -282,8 +285,8 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
|
||||
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||
github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
|
||||
@@ -312,35 +315,37 @@ github.com/yuin/goldmark v1.7.7 h1:5m9rrB1sW3JUMToKFQfb+FGt1U7r57IHu5GrYrG2nqU=
|
||||
github.com/yuin/goldmark v1.7.7/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
|
||||
github.com/yuin/goldmark-meta v1.1.0 h1:pWw+JLHGZe8Rk0EGsMVssiNb/AaPMHfSRszZeUeiOUc=
|
||||
github.com/yuin/goldmark-meta v1.1.0/go.mod h1:U4spWENafuA7Zyg+Lj5RqK/MF+ovMYtBvXi1lBb2VP0=
|
||||
github.com/zclconf/go-cty v1.15.0 h1:tTCRWxsexYUmtt/wVxgDClUe+uQusuI443uL6e+5sXQ=
|
||||
github.com/zclconf/go-cty v1.15.0/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE=
|
||||
github.com/zclconf/go-cty v1.16.3 h1:osr++gw2T61A8KVYHoQiFbFd1Lh3JOCXc/jFLJXKTxk=
|
||||
github.com/zclconf/go-cty v1.16.3/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE=
|
||||
github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940 h1:4r45xpDWB6ZMSMNJFMOjqrGHynW3DIBuR2H9j0ug+Mo=
|
||||
github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940/go.mod h1:CmBdvvj3nqzfzJ6nTCIwDTPZ56aVGvDrmztiO5g3qrM=
|
||||
go.abhg.dev/goldmark/frontmatter v0.2.0 h1:P8kPG0YkL12+aYk2yU3xHv4tcXzeVnN+gU0tJ5JnxRw=
|
||||
go.abhg.dev/goldmark/frontmatter v0.2.0/go.mod h1:XqrEkZuM57djk7zrlRUB02x8I5J0px76YjkOzhB4YlU=
|
||||
go.opentelemetry.io/otel v1.31.0 h1:NsJcKPIW0D0H3NgzPDHmo0WW6SptzPdqg/L1zsIm2hY=
|
||||
go.opentelemetry.io/otel v1.31.0/go.mod h1:O0C14Yl9FgkjqcCZAsE053C13OaddMYr/hz6clDkEJE=
|
||||
go.opentelemetry.io/otel/metric v1.31.0 h1:FSErL0ATQAmYHUIzSezZibnyVlft1ybhy4ozRPcF2fE=
|
||||
go.opentelemetry.io/otel/metric v1.31.0/go.mod h1:C3dEloVbLuYoX41KpmAhOqNriGbA+qqH6PQ5E5mUfnY=
|
||||
go.opentelemetry.io/otel/sdk v1.31.0 h1:xLY3abVHYZ5HSfOg3l2E5LUj2Cwva5Y7yGxnSW9H5Gk=
|
||||
go.opentelemetry.io/otel/sdk v1.31.0/go.mod h1:TfRbMdhvxIIr/B2N2LQW2S5v9m3gOQ/08KsbbO5BPT0=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.31.0 h1:i9hxxLJF/9kkvfHppyLL55aW7iIJz4JjxTeYusH7zMc=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.31.0/go.mod h1:CRInTMVvNhUKgSAMbKyTMxqOBC0zgyxzW55lZzX43Y8=
|
||||
go.opentelemetry.io/otel/trace v1.31.0 h1:ffjsj1aRouKewfr85U2aGagJ46+MvodynlQ1HYdmJys=
|
||||
go.opentelemetry.io/otel/trace v1.31.0/go.mod h1:TXZkRk7SM2ZQLtR6eoAWQFIHPvzQ06FJAsO1tJg480A=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
||||
go.opentelemetry.io/otel v1.36.0 h1:UumtzIklRBY6cI/lllNZlALOF5nNIzJVb16APdvgTXg=
|
||||
go.opentelemetry.io/otel v1.36.0/go.mod h1:/TcFMXYjyRNh8khOAO9ybYkqaDBb/70aVwkNML4pP8E=
|
||||
go.opentelemetry.io/otel/metric v1.36.0 h1:MoWPKVhQvJ+eeXWHFBOPoBOi20jh6Iq2CcCREuTYufE=
|
||||
go.opentelemetry.io/otel/metric v1.36.0/go.mod h1:zC7Ks+yeyJt4xig9DEw9kuUFe5C3zLbVjV2PzT6qzbs=
|
||||
go.opentelemetry.io/otel/sdk v1.36.0 h1:b6SYIuLRs88ztox4EyrvRti80uXIFy+Sqzoh9kFULbs=
|
||||
go.opentelemetry.io/otel/sdk v1.36.0/go.mod h1:+lC+mTgD+MUWfjJubi2vvXWcVxyr9rmlshZni72pXeY=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.36.0 h1:r0ntwwGosWGaa0CrSt8cuNuTcccMXERFwHX4dThiPis=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.36.0/go.mod h1:qTNOhFDfKRwX0yXOqJYegL5WRaW376QbB7P4Pb0qva4=
|
||||
go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKrsNd4w=
|
||||
go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
||||
golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=
|
||||
golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
|
||||
golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM=
|
||||
golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY=
|
||||
golang.org/x/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.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0=
|
||||
golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
|
||||
golang.org/x/mod v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w=
|
||||
golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
|
||||
golang.org/x/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=
|
||||
@@ -351,14 +356,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.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
|
||||
golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
|
||||
golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs=
|
||||
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=
|
||||
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.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
|
||||
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
|
||||
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
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=
|
||||
@@ -381,29 +386,27 @@ golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
|
||||
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
|
||||
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.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.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
|
||||
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
|
||||
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA=
|
||||
golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c=
|
||||
golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo=
|
||||
golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
@@ -411,10 +414,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-20241021214115-324edc3d5d38 h1:zciRKQ4kBpFgpfC5QQCVtnnNAcLIqweL7plyZRQHVpI=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI=
|
||||
google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A=
|
||||
google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250728155136-f173205681a0 h1:MAKi5q709QWfnkkpNQ0M12hYJ1+e8qYVDyowc4U1XZM=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250728155136-f173205681a0/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
|
||||
google.golang.org/grpc v1.74.2 h1:WoosgB65DlWVC9FqI82dGsZhWFNBSLjQ84bjROOpMu4=
|
||||
google.golang.org/grpc v1.74.2/go.mod h1:CtQ+BGjaAIXHs/5YS3i473GqwBBa1zGQNevxdeBEXrM=
|
||||
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=
|
||||
@@ -423,8 +426,8 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU=
|
||||
google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
|
||||
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Package binarylane provides primitives to interact with the openapi HTTP API.
|
||||
//
|
||||
// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.4.1 DO NOT EDIT.
|
||||
// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.5.0 DO NOT EDIT.
|
||||
package binarylane
|
||||
|
||||
import (
|
||||
@@ -151,8 +151,10 @@ type ClientInterface interface {
|
||||
// GetDomainsNameservers request
|
||||
GetDomainsNameservers(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error)
|
||||
|
||||
// PostDomainsRefreshNameserverCache request
|
||||
PostDomainsRefreshNameserverCache(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error)
|
||||
// PostDomainsRefreshNameserverCacheWithBody request with any body
|
||||
PostDomainsRefreshNameserverCacheWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error)
|
||||
|
||||
PostDomainsRefreshNameserverCache(ctx context.Context, body PostDomainsRefreshNameserverCacheJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error)
|
||||
|
||||
// DeleteDomainsDomainName request
|
||||
DeleteDomainsDomainName(ctx context.Context, domainName struct {
|
||||
@@ -843,8 +845,20 @@ func (c *Client) GetDomainsNameservers(ctx context.Context, reqEditors ...Reques
|
||||
return c.Client.Do(req)
|
||||
}
|
||||
|
||||
func (c *Client) PostDomainsRefreshNameserverCache(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) {
|
||||
req, err := NewPostDomainsRefreshNameserverCacheRequest(c.Server)
|
||||
func (c *Client) PostDomainsRefreshNameserverCacheWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) {
|
||||
req, err := NewPostDomainsRefreshNameserverCacheRequestWithBody(c.Server, 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) PostDomainsRefreshNameserverCache(ctx context.Context, body PostDomainsRefreshNameserverCacheJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) {
|
||||
req, err := NewPostDomainsRefreshNameserverCacheRequest(c.Server, body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -3490,8 +3504,19 @@ func NewGetDomainsNameserversRequest(server string) (*http.Request, error) {
|
||||
return req, nil
|
||||
}
|
||||
|
||||
// NewPostDomainsRefreshNameserverCacheRequest generates requests for PostDomainsRefreshNameserverCache
|
||||
func NewPostDomainsRefreshNameserverCacheRequest(server string) (*http.Request, error) {
|
||||
// NewPostDomainsRefreshNameserverCacheRequest calls the generic PostDomainsRefreshNameserverCache builder with application/json body
|
||||
func NewPostDomainsRefreshNameserverCacheRequest(server string, body PostDomainsRefreshNameserverCacheJSONRequestBody) (*http.Request, error) {
|
||||
var bodyReader io.Reader
|
||||
buf, err := json.Marshal(body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bodyReader = bytes.NewReader(buf)
|
||||
return NewPostDomainsRefreshNameserverCacheRequestWithBody(server, "application/json", bodyReader)
|
||||
}
|
||||
|
||||
// NewPostDomainsRefreshNameserverCacheRequestWithBody generates requests for PostDomainsRefreshNameserverCache with any type of body
|
||||
func NewPostDomainsRefreshNameserverCacheRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) {
|
||||
var err error
|
||||
|
||||
serverURL, err := url.Parse(server)
|
||||
@@ -3509,11 +3534,13 @@ func NewPostDomainsRefreshNameserverCacheRequest(server string) (*http.Request,
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req, err := http.NewRequest("POST", queryURL.String(), nil)
|
||||
req, err := http.NewRequest("POST", queryURL.String(), body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req.Header.Add("Content-Type", contentType)
|
||||
|
||||
return req, nil
|
||||
}
|
||||
|
||||
@@ -8445,8 +8472,10 @@ type ClientWithResponsesInterface interface {
|
||||
// GetDomainsNameserversWithResponse request
|
||||
GetDomainsNameserversWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetDomainsNameserversResponse, error)
|
||||
|
||||
// PostDomainsRefreshNameserverCacheWithResponse request
|
||||
PostDomainsRefreshNameserverCacheWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*PostDomainsRefreshNameserverCacheResponse, error)
|
||||
// PostDomainsRefreshNameserverCacheWithBodyWithResponse request with any body
|
||||
PostDomainsRefreshNameserverCacheWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostDomainsRefreshNameserverCacheResponse, error)
|
||||
|
||||
PostDomainsRefreshNameserverCacheWithResponse(ctx context.Context, body PostDomainsRefreshNameserverCacheJSONRequestBody, reqEditors ...RequestEditorFn) (*PostDomainsRefreshNameserverCacheResponse, error)
|
||||
|
||||
// DeleteDomainsDomainNameWithResponse request
|
||||
DeleteDomainsDomainNameWithResponse(ctx context.Context, domainName struct {
|
||||
@@ -11585,9 +11614,17 @@ func (c *ClientWithResponses) GetDomainsNameserversWithResponse(ctx context.Cont
|
||||
return ParseGetDomainsNameserversResponse(rsp)
|
||||
}
|
||||
|
||||
// PostDomainsRefreshNameserverCacheWithResponse request returning *PostDomainsRefreshNameserverCacheResponse
|
||||
func (c *ClientWithResponses) PostDomainsRefreshNameserverCacheWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*PostDomainsRefreshNameserverCacheResponse, error) {
|
||||
rsp, err := c.PostDomainsRefreshNameserverCache(ctx, reqEditors...)
|
||||
// PostDomainsRefreshNameserverCacheWithBodyWithResponse request with arbitrary body returning *PostDomainsRefreshNameserverCacheResponse
|
||||
func (c *ClientWithResponses) PostDomainsRefreshNameserverCacheWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostDomainsRefreshNameserverCacheResponse, error) {
|
||||
rsp, err := c.PostDomainsRefreshNameserverCacheWithBody(ctx, contentType, body, reqEditors...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ParsePostDomainsRefreshNameserverCacheResponse(rsp)
|
||||
}
|
||||
|
||||
func (c *ClientWithResponses) PostDomainsRefreshNameserverCacheWithResponse(ctx context.Context, body PostDomainsRefreshNameserverCacheJSONRequestBody, reqEditors ...RequestEditorFn) (*PostDomainsRefreshNameserverCacheResponse, error) {
|
||||
rsp, err := c.PostDomainsRefreshNameserverCache(ctx, body, reqEditors...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Package binarylane provides primitives to interact with the openapi HTTP API.
|
||||
//
|
||||
// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.4.1 DO NOT EDIT.
|
||||
// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.5.0 DO NOT EDIT.
|
||||
package binarylane
|
||||
|
||||
import (
|
||||
@@ -36,20 +36,6 @@ const (
|
||||
AddDiskTypeAddDisk AddDiskType = "add_disk"
|
||||
)
|
||||
|
||||
// Defines values for AdvancedFeature.
|
||||
const (
|
||||
CloudInit AdvancedFeature = "cloud-init"
|
||||
DriverDisk AdvancedFeature = "driver-disk"
|
||||
EmulatedDevices AdvancedFeature = "emulated-devices"
|
||||
EmulatedHyperv AdvancedFeature = "emulated-hyperv"
|
||||
EmulatedTpm AdvancedFeature = "emulated-tpm"
|
||||
LocalRtc AdvancedFeature = "local-rtc"
|
||||
NestedVirt AdvancedFeature = "nested-virt"
|
||||
QemuGuestAgent AdvancedFeature = "qemu-guest-agent"
|
||||
UefiBoot AdvancedFeature = "uefi-boot"
|
||||
UnsetUuid AdvancedFeature = "unset-uuid"
|
||||
)
|
||||
|
||||
// Defines values for AdvancedFirewallRuleAction.
|
||||
const (
|
||||
Accept AdvancedFirewallRuleAction = "accept"
|
||||
@@ -421,10 +407,14 @@ const (
|
||||
PcI440fx5point0 VmMachineType = "pc_i440fx_5point0"
|
||||
PcI440fx5point1 VmMachineType = "pc_i440fx_5point1"
|
||||
PcI440fx7point2 VmMachineType = "pc_i440fx_7point2"
|
||||
PcI440fx8point2 VmMachineType = "pc_i440fx_8point2"
|
||||
)
|
||||
|
||||
// Account defines model for Account.
|
||||
type Account struct {
|
||||
// AdditionalIpv4Limit The maximum additional IPv4 addresses this account may assign across all servers. You may contact support to request this limit be increased.
|
||||
AdditionalIpv4Limit *int32 `json:"additional_ipv4_limit,omitempty"`
|
||||
|
||||
// ConfiguredPaymentMethods The payment methods that are configured (available) for this account.
|
||||
ConfiguredPaymentMethods *[]PaymentMethod `json:"configured_payment_methods,omitempty"`
|
||||
|
||||
@@ -490,6 +480,16 @@ type Action struct {
|
||||
ResourceId *int64 `json:"resource_id"`
|
||||
|
||||
// ResourceType The resource type (if any) associated with this action.
|
||||
//
|
||||
// | Value | Description |
|
||||
// | ----- | ----------- |
|
||||
// | server | Server |
|
||||
// | load-balancer | Load Balancer |
|
||||
// | ssh-key | SSH Key |
|
||||
// | vpc | Virtual Private Network |
|
||||
// | image | Backup or Operating System Image |
|
||||
// | registered-domain-name | Registered Domain Name |
|
||||
//
|
||||
ResourceType *ResourceType `json:"resource_type"`
|
||||
|
||||
// ResultData Returned information from a completed action. For example: a successful completed 'uptime' action will have the uptime value in this field.
|
||||
@@ -568,24 +568,15 @@ type AddDisk struct {
|
||||
// AddDiskType defines model for AddDisk.Type.
|
||||
type AddDiskType string
|
||||
|
||||
// AdvancedFeature
|
||||
// | Value | Description |
|
||||
// | ----- | ----------- |
|
||||
// | emulated-hyperv | Enable HyperV (a hypervisor produced by Microsoft) support. Enabled by default on Windows servers, generally of no value for non-Windows servers. |
|
||||
// | emulated-devices | When emulated devices is enabled, the KVM specific "VirtIO" disk drive and network devices are removed, and replaced with emulated versions of physical hardware: an old IDE HDD and an Intel E1000 network card. Emulated devices are much slower than the VirtIO devices, and so this option should not be enabled unless absolutely necessary. |
|
||||
// | nested-virt | When this option is enabled the functionality necessary to run your own KVM servers within your server is enabled. Note that all the networking limits - one MAC address per VPS, restricted to specific IPs - still apply to public cloud so this is feature is generally only useful in combination with Virtual Private Cloud. |
|
||||
// | driver-disk | When this option is enabled a copy of the KVM driver disc for Windows ("virtio-win.iso") will be attached to your server as a virtual CD. This option can also be used in combination with your own attached backup when installing Windows. |
|
||||
// | unset-uuid | When this option is NOT enabled a 128-bit unique identifier is exposed to your server through the virtual BIOS. Each server receives a different UUID. Some propriety licensed software utilise this identifier to "tie" the license to a specific server. |
|
||||
// | local-rtc | When a server is booted the virtual BIOS receives the current date and time from the host node. The BIOS does not have an explicit timezone, so the timezone used is implicit and must be understood by the operating system. Most operating systems other than Windows expect the time to be UTC since it allows the operating system to control the timezone used when displaying the time. Our Windows installations have also been customized to use UTC, but when using your own installation of Windows this should be set to the host node's local timezone. |
|
||||
// | emulated-tpm | When enabled this provides an emulated TPM v1.2 device to your Cloud Server. Warning: the TPM state is not backed up. |
|
||||
// | cloud-init | (Read-Only) When this option is enabled the Cloud Server will be provided a datasource for the cloud-init service. |
|
||||
// | qemu-guest-agent | (Read-Only) When this option is enabled the server will allow QEMU Guest Agent to perform password reset without rebooting. |
|
||||
// | uefi-boot | (Read-Only) When this option is enabled the Cloud Server will use UEFI instead of legacy PC BIOS. |
|
||||
type AdvancedFeature string
|
||||
|
||||
// AdvancedFirewallRule defines model for AdvancedFirewallRule.
|
||||
type AdvancedFirewallRule struct {
|
||||
// Action The action to take when there is a match on this rule.
|
||||
//
|
||||
// | Value | Description |
|
||||
// | ----- | ----------- |
|
||||
// | drop | Traffic matching this rule will be dropped. |
|
||||
// | accept | Traffic matching this rule will be accepted. |
|
||||
//
|
||||
Action AdvancedFirewallRuleAction `json:"action" tfsdk:"action"`
|
||||
|
||||
// Description A description to assist in identifying this rule. Commonly used to record the reason for the rule or the intent behind it, e.g. "Block access to RDP" or "Allow access from HQ".
|
||||
@@ -598,6 +589,14 @@ type AdvancedFirewallRule struct {
|
||||
DestinationPorts *[]string `json:"destination_ports" tfsdk:"destination_ports"`
|
||||
|
||||
// Protocol The protocol to match for this rule.
|
||||
//
|
||||
// | Value | Description |
|
||||
// | ----- | ----------- |
|
||||
// | all | This rule will match any protocol. |
|
||||
// | icmp | This rule will match ICMP traffic only. |
|
||||
// | tcp | This rule will match TCP traffic only. |
|
||||
// | udp | This rule will match UDP traffic only. |
|
||||
//
|
||||
Protocol AdvancedFirewallRuleProtocol `json:"protocol" tfsdk:"protocol"`
|
||||
|
||||
// SourceAddresses The source addresses to match for this rule. Each address may be an individual IPv4 address or a range in IPv4 CIDR notation.
|
||||
@@ -620,6 +619,41 @@ type AdvancedFirewallRuleAction string
|
||||
// | udp | This rule will match UDP traffic only. |
|
||||
type AdvancedFirewallRuleProtocol string
|
||||
|
||||
// AdvancedFirewallRuleRequest defines model for AdvancedFirewallRuleRequest.
|
||||
type AdvancedFirewallRuleRequest struct {
|
||||
// Action The action to take when there is a match on this rule.
|
||||
//
|
||||
// | Value | Description |
|
||||
// | ----- | ----------- |
|
||||
// | drop | Traffic matching this rule will be dropped. |
|
||||
// | accept | Traffic matching this rule will be accepted. |
|
||||
//
|
||||
Action AdvancedFirewallRuleAction `json:"action" tfsdk:"action"`
|
||||
|
||||
// Description A description to assist in identifying this rule. Commonly used to record the reason for the rule or the intent behind it, e.g. "Block access to RDP" or "Allow access from HQ".
|
||||
Description *string `json:"description" tfsdk:"description"`
|
||||
|
||||
// DestinationAddresses The destination addresses to match for this rule. Each address may be an individual IPv4 address or a range in IPv4 CIDR notation.
|
||||
DestinationAddresses []string `json:"destination_addresses" tfsdk:"destination_addresses"`
|
||||
|
||||
// DestinationPorts The destination ports to match for this rule. Leave null or empty to match on all ports.
|
||||
DestinationPorts *[]string `json:"destination_ports" tfsdk:"destination_ports"`
|
||||
|
||||
// Protocol The protocol to match for this rule.
|
||||
//
|
||||
// | Value | Description |
|
||||
// | ----- | ----------- |
|
||||
// | all | This rule will match any protocol. |
|
||||
// | icmp | This rule will match ICMP traffic only. |
|
||||
// | tcp | This rule will match TCP traffic only. |
|
||||
// | udp | This rule will match UDP traffic only. |
|
||||
//
|
||||
Protocol AdvancedFirewallRuleProtocol `json:"protocol" tfsdk:"protocol"`
|
||||
|
||||
// SourceAddresses The source addresses to match for this rule. Each address may be an individual IPv4 address or a range in IPv4 CIDR notation.
|
||||
SourceAddresses []string `json:"source_addresses" tfsdk:"source_addresses"`
|
||||
}
|
||||
|
||||
// AdvancedFirewallRulesResponse defines model for AdvancedFirewallRulesResponse.
|
||||
type AdvancedFirewallRulesResponse struct {
|
||||
// FirewallRules The advanced firewall rules for the selected server. Please note that the order of the rules is critical as the first matching rule is applied, and if no rules match the traffic is permitted.
|
||||
@@ -629,10 +663,22 @@ type AdvancedFirewallRulesResponse struct {
|
||||
// AdvancedServerFeatures defines model for AdvancedServerFeatures.
|
||||
type AdvancedServerFeatures struct {
|
||||
// EnabledAdvancedFeatures A list of the currently enabled advanced features for this server.
|
||||
EnabledAdvancedFeatures *[]AdvancedFeature `json:"enabled_advanced_features,omitempty"`
|
||||
EnabledAdvancedFeatures *[]string `json:"enabled_advanced_features,omitempty"`
|
||||
|
||||
// MachineType The machine_type (corresponding to a KVM version) used for this server.
|
||||
// A null value indicates automatic selection of the best KVM machine type supported by the host node.
|
||||
//
|
||||
// | Value | Description |
|
||||
// | ----- | ----------- |
|
||||
// | pc_i440fx_1point5 | PC i440FX 1.5 |
|
||||
// | pc_i440fx_2point11 | PC i440FX 2.11 |
|
||||
// | pc_i440fx_4point1 | PC i440FX 4.1 |
|
||||
// | pc_i440fx_4point2 | PC i440FX 4.2 |
|
||||
// | pc_i440fx_5point0 | PC i440FX 5.0 |
|
||||
// | pc_i440fx_5point1 | PC i440FX 5.1 |
|
||||
// | pc_i440fx_7point2 | PC i440FX 7.2 |
|
||||
// | pc_i440fx_8point2 | PC i440FX 8.2 |
|
||||
//
|
||||
MachineType *VmMachineType `json:"machine_type"`
|
||||
|
||||
// ProcessorModel The ID of the processor model (and therefore CPU flags) available for this server.
|
||||
@@ -680,7 +726,7 @@ type AttachedBackup struct {
|
||||
// AvailableAdvancedServerFeatures defines model for AvailableAdvancedServerFeatures.
|
||||
type AvailableAdvancedServerFeatures struct {
|
||||
// AdvancedFeatures A list of the advanced features available for this server.
|
||||
AdvancedFeatures *[]AdvancedFeature `json:"advanced_features,omitempty"`
|
||||
AdvancedFeatures *[]string `json:"advanced_features,omitempty"`
|
||||
|
||||
// MachineTypes A list of the machine types available for this server.
|
||||
MachineTypes *[]VmMachineType `json:"machine_types,omitempty"`
|
||||
@@ -809,9 +855,21 @@ type ChangeAdvancedFeatures struct {
|
||||
AutomaticProcessorModel *bool `json:"automatic_processor_model"`
|
||||
|
||||
// EnabledAdvancedFeatures Do not provide or set to null to keep existing advanced features. Provide an empty array to disable all advanced features, otherwise provide an array with selected advanced features. If provided, any currently enabled advanced features that aren't included will be disabled.
|
||||
EnabledAdvancedFeatures *[]AdvancedFeature `json:"enabled_advanced_features"`
|
||||
EnabledAdvancedFeatures *[]string `json:"enabled_advanced_features"`
|
||||
|
||||
// MachineType Do not provide or set to null to keep existing machine type.
|
||||
//
|
||||
// | Value | Description |
|
||||
// | ----- | ----------- |
|
||||
// | pc_i440fx_1point5 | PC i440FX 1.5 |
|
||||
// | pc_i440fx_2point11 | PC i440FX 2.11 |
|
||||
// | pc_i440fx_4point1 | PC i440FX 4.1 |
|
||||
// | pc_i440fx_4point2 | PC i440FX 4.2 |
|
||||
// | pc_i440fx_5point0 | PC i440FX 5.0 |
|
||||
// | pc_i440fx_5point1 | PC i440FX 5.1 |
|
||||
// | pc_i440fx_7point2 | PC i440FX 7.2 |
|
||||
// | pc_i440fx_8point2 | PC i440FX 8.2 |
|
||||
//
|
||||
MachineType *VmMachineType `json:"machine_type"`
|
||||
|
||||
// ProcessorModel Do not provide or set to null to keep existing processor model.
|
||||
@@ -819,6 +877,14 @@ type ChangeAdvancedFeatures struct {
|
||||
Type ChangeAdvancedFeaturesType `json:"type"`
|
||||
|
||||
// VideoDevice Do not provide or set to null to keep existing video device.
|
||||
//
|
||||
// | Value | Description |
|
||||
// | ----- | ----------- |
|
||||
// | cirrus-logic | Cirrus Logic GD5446 |
|
||||
// | standard | Standard VGA with VESA 2.0 extensions |
|
||||
// | virtio | Virtio VGA (800x600) |
|
||||
// | virtio-wide | Virtio VGA (1600x900) |
|
||||
//
|
||||
VideoDevice *VideoDevice `json:"video_device"`
|
||||
}
|
||||
|
||||
@@ -828,7 +894,7 @@ type ChangeAdvancedFeaturesType string
|
||||
// ChangeAdvancedFirewallRules Change the Advanced Firewall Rules for a Server
|
||||
type ChangeAdvancedFirewallRules struct {
|
||||
// FirewallRules A list of rules for the server. NB: that any existing rules that are not included will be removed. Submit an empty list to clear all rules.
|
||||
FirewallRules []AdvancedFirewallRule `json:"firewall_rules"`
|
||||
FirewallRules []AdvancedFirewallRuleRequest `json:"firewall_rules"`
|
||||
Type ChangeAdvancedFirewallRulesType `json:"type"`
|
||||
}
|
||||
|
||||
@@ -1123,10 +1189,10 @@ type ConsoleResponse struct {
|
||||
// CreateLoadBalancerRequest defines model for CreateLoadBalancerRequest.
|
||||
type CreateLoadBalancerRequest struct {
|
||||
// ForwardingRules The rules that control which traffic the load balancer will forward to servers in the pool. Leave null to accept a default "HTTP" only forwarding rule.
|
||||
ForwardingRules *[]ForwardingRule `json:"forwarding_rules" tfsdk:"forwarding_rules"`
|
||||
ForwardingRules *[]ForwardingRuleRequest `json:"forwarding_rules" tfsdk:"forwarding_rules"`
|
||||
|
||||
// HealthCheck The rules that determine which servers are considered 'healthy' and in the server pool for the load balancer. Leave this null to accept appropriate defaults based on the forwarding_rules.
|
||||
HealthCheck *HealthCheck `json:"health_check"`
|
||||
HealthCheck *HealthCheckRequest `json:"health_check"`
|
||||
|
||||
// Name The hostname of the load balancer.
|
||||
Name string `json:"name"`
|
||||
@@ -1415,16 +1481,16 @@ type DomainRecord struct {
|
||||
Weight *int32 `json:"weight"`
|
||||
}
|
||||
|
||||
// DomainRecordRequest If this is used to update an existing DomainRecord any values not provided will be retained. Provide empty strings to clear existing string values, nulls to retain the existing values.
|
||||
// DomainRecordRequest defines model for DomainRecordRequest.
|
||||
type DomainRecordRequest struct {
|
||||
// Data A general data field that has different functions depending on the record type.
|
||||
Data *string `json:"data"`
|
||||
Data string `json:"data"`
|
||||
|
||||
// Flags An unsigned integer between 0-255 that is only relevant for CAA records.
|
||||
Flags *int32 `json:"flags"`
|
||||
|
||||
// Name The subdomain for this record. Use @ for records on the domain itself, and * to create a wildcard record.
|
||||
Name *string `json:"name"`
|
||||
Name string `json:"name"`
|
||||
|
||||
// Port A port value that is only relevant for SRV records.
|
||||
Port *int32 `json:"port"`
|
||||
@@ -1435,11 +1501,24 @@ type DomainRecordRequest struct {
|
||||
// Tag A parameter tag that is only relevant for CAA records.
|
||||
Tag *string `json:"tag"`
|
||||
|
||||
// Ttl This value is the time to live for the record, in seconds.
|
||||
// Ttl This value is the time to live for the record, in seconds. The default and only supported value is 3600. Leave null to accept this default.
|
||||
Ttl *int32 `json:"ttl"`
|
||||
|
||||
// Type The type of the DNS record.
|
||||
Type *DomainRecordType `json:"type"`
|
||||
//
|
||||
// | Value | Description |
|
||||
// | ----- | ----------- |
|
||||
// | A | Map an IPv4 address to a hostname. |
|
||||
// | AAAA | Map an IPv6 address to a hostname. |
|
||||
// | CAA | Restrict which certificate authorities are permitted to issue certificates for a domain. |
|
||||
// | CNAME | Define an alias for your canonical hostname. |
|
||||
// | MX | Define the mail exchanges that handle mail for the domain. |
|
||||
// | NS | Define the nameservers that manage the domain. |
|
||||
// | SOA | The Start of Authority record for the zone. |
|
||||
// | SRV | Specify a server by hostname and port to handle a service or services. |
|
||||
// | TXT | Define a string of text that is associated with a hostname. |
|
||||
//
|
||||
Type DomainRecordType `json:"type"`
|
||||
|
||||
// Weight The weight value that is only relevant for SRV records.
|
||||
Weight *int32 `json:"weight"`
|
||||
@@ -1473,6 +1552,12 @@ type DomainRecordsResponse struct {
|
||||
Meta Meta `json:"meta"`
|
||||
}
|
||||
|
||||
// DomainRefreshRequest defines model for DomainRefreshRequest.
|
||||
type DomainRefreshRequest struct {
|
||||
// DomainNames The domain names to refresh.
|
||||
DomainNames []string `json:"domain_names"`
|
||||
}
|
||||
|
||||
// DomainRequest defines model for DomainRequest.
|
||||
type DomainRequest struct {
|
||||
// IpAddress An optional IPv4 address that will be used to create an A record for the root domain.
|
||||
@@ -1518,19 +1603,38 @@ type ForwardingRule struct {
|
||||
EntryProtocol LoadBalancerRuleProtocol `json:"entry_protocol" tfsdk:"entry_protocol"`
|
||||
}
|
||||
|
||||
// ForwardingRuleRequest defines model for ForwardingRuleRequest.
|
||||
type ForwardingRuleRequest struct {
|
||||
// EntryProtocol The protocol that traffic must match for this load balancer to forward traffic according to this rule.
|
||||
//
|
||||
// | Value | Description |
|
||||
// | ----- | ----------- |
|
||||
// | http | The load balancer will forward HTTP traffic that matches this rule. |
|
||||
// | https | The load balancer will forward HTTPS traffic that matches this rule. |
|
||||
//
|
||||
EntryProtocol LoadBalancerRuleProtocol `json:"entry_protocol" tfsdk:"entry_protocol"`
|
||||
}
|
||||
|
||||
// ForwardingRulesRequest defines model for ForwardingRulesRequest.
|
||||
type ForwardingRulesRequest struct {
|
||||
// ForwardingRules The rules that control which traffic the load balancer will forward to servers in the pool.
|
||||
ForwardingRules []ForwardingRule `json:"forwarding_rules"`
|
||||
ForwardingRules []ForwardingRuleRequest `json:"forwarding_rules"`
|
||||
}
|
||||
|
||||
// HealthCheck defines model for HealthCheck.
|
||||
type HealthCheck struct {
|
||||
// Path Leave null to accept the default '/' path.
|
||||
Path *string `json:"path"`
|
||||
// Path The path to the health check endpoint.
|
||||
Path string `json:"path"`
|
||||
|
||||
// Protocol Leave null to accept the default HTTP protocol.
|
||||
Protocol *HealthCheckProtocol `json:"protocol"`
|
||||
// Protocol The protocol used for the health check.
|
||||
//
|
||||
// | Value | Description |
|
||||
// | ----- | ----------- |
|
||||
// | http | The health check will be performed via HTTP. |
|
||||
// | https | The health check will be performed via HTTPS. |
|
||||
// | both | The health check will be performed via both HTTP and HTTPS. Failing a health check on one protocol will remove the server from the pool of servers only for that protocol. |
|
||||
//
|
||||
Protocol HealthCheckProtocol `json:"protocol"`
|
||||
}
|
||||
|
||||
// HealthCheckProtocol
|
||||
@@ -1541,6 +1645,22 @@ type HealthCheck struct {
|
||||
// | both | The health check will be performed via both HTTP and HTTPS. Failing a health check on one protocol will remove the server from the pool of servers only for that protocol. |
|
||||
type HealthCheckProtocol = string
|
||||
|
||||
// HealthCheckRequest defines model for HealthCheckRequest.
|
||||
type HealthCheckRequest struct {
|
||||
// Path Leave null to accept the default '/' path.
|
||||
Path *string `json:"path"`
|
||||
|
||||
// Protocol Leave null to accept the default HTTP protocol.
|
||||
//
|
||||
// | Value | Description |
|
||||
// | ----- | ----------- |
|
||||
// | http | The health check will be performed via HTTP. |
|
||||
// | https | The health check will be performed via HTTPS. |
|
||||
// | both | The health check will be performed via both HTTP and HTTPS. Failing a health check on one protocol will remove the server from the pool of servers only for that protocol. |
|
||||
//
|
||||
Protocol *HealthCheckProtocol `json:"protocol"`
|
||||
}
|
||||
|
||||
// Host defines model for Host.
|
||||
type Host struct {
|
||||
// DisplayName The name for this host. If this is a dedicated host this property will be empty.
|
||||
@@ -1795,6 +1915,11 @@ type License struct {
|
||||
|
||||
// LicensedSoftware defines model for LicensedSoftware.
|
||||
type LicensedSoftware struct {
|
||||
// Incompatible Software that is incompatible with the server will be automatically removed at the next plan change.
|
||||
// Servers may have incompatible software due to changes made by support. Software is not incompatible merely because it is disabled;
|
||||
// disabled software may be retained by servers that already have it, incompatible software will be removed.
|
||||
Incompatible bool `json:"incompatible"`
|
||||
|
||||
// LicenceCount The current licence count for the software.
|
||||
LicenceCount int32 `json:"licence_count"`
|
||||
|
||||
@@ -1820,29 +1945,38 @@ type Links struct {
|
||||
// LoadBalancer defines model for LoadBalancer.
|
||||
type LoadBalancer struct {
|
||||
// CreatedAt The date and time in ISO8601 format of the creation of the load balancer.
|
||||
CreatedAt *time.Time `json:"created_at,omitempty"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
|
||||
// ForwardingRules The rules that control which traffic the load balancer will forward to servers in the pool.
|
||||
ForwardingRules *[]ForwardingRule `json:"forwarding_rules,omitempty"`
|
||||
ForwardingRules []ForwardingRule `json:"forwarding_rules"`
|
||||
|
||||
// HealthCheck The rules that determine which servers are considered 'healthy' and in the server pool for the load balancer.
|
||||
HealthCheck *HealthCheck `json:"health_check,omitempty" tfsdk:"health_check"`
|
||||
HealthCheck HealthCheck `json:"health_check" tfsdk:"health_check"`
|
||||
|
||||
// Id The ID of the load balancer.
|
||||
Id *int64 `json:"id,omitempty"`
|
||||
Id int64 `json:"id"`
|
||||
|
||||
// Ip The IPv4 address of the load balancer.
|
||||
Ip *string `json:"ip,omitempty"`
|
||||
Ip string `json:"ip"`
|
||||
|
||||
// Name The hostname of the load balancer.
|
||||
Name *string `json:"name,omitempty"`
|
||||
Name string `json:"name"`
|
||||
|
||||
// Region The region the load balancer is located in. If this value is null the load balancer is an 'AnyCast' load balancer.
|
||||
Region *Region `json:"region"`
|
||||
|
||||
// ServerIds The server IDs of the servers that are currently in the load balancer pool (regardless of their current 'health').
|
||||
ServerIds *[]int64 `json:"server_ids,omitempty"`
|
||||
Status *LoadBalancerStatus `json:"status,omitempty"`
|
||||
ServerIds []int64 `json:"server_ids"`
|
||||
|
||||
// Status The current status of the load balancer.
|
||||
//
|
||||
// | Value | Description |
|
||||
// | ----- | ----------- |
|
||||
// | new | The load balancer is currently being built and is not ready to accept connections. |
|
||||
// | active | The load balancer is available. |
|
||||
// | errored | The load balancer is in an errored state. |
|
||||
//
|
||||
Status LoadBalancerStatus `json:"status"`
|
||||
}
|
||||
|
||||
// LoadBalancerAvailabilityOption defines model for LoadBalancerAvailabilityOption.
|
||||
@@ -1854,7 +1988,7 @@ type LoadBalancerAvailabilityOption struct {
|
||||
PriceHourly *float64 `json:"price_hourly,omitempty"`
|
||||
|
||||
// PriceMonthly Monthly Price in AU$.
|
||||
PriceMonthly *float64 `json:"price_monthly,omitempty"`
|
||||
PriceMonthly float64 `json:"price_monthly"`
|
||||
|
||||
// Regions The slugs of regions where this load balancer option is available. If this is an Anycast load balancer option this will be null.
|
||||
Regions *[]string `json:"regions"`
|
||||
@@ -2187,7 +2321,7 @@ type Resize struct {
|
||||
// ChangeImage This may be left null to keep the current base image for the server. If this is provided the server disks will be destroyed and the server will be rebuilt from the selected image.
|
||||
ChangeImage *ChangeImage `json:"change_image"`
|
||||
|
||||
// ChangeLicenses This may be left null to keep the current licenses for the server. If this is provided any licenses that are not included will be removed.
|
||||
// ChangeLicenses This may be left null to keep the current licenses for the server. If this is provided any licenses that are not included will be removed. Any licences that are invalid will be removed regardless, see the documentation for `servers/{server_id}/software` for more information.
|
||||
ChangeLicenses *ChangeLicenses `json:"change_licenses"`
|
||||
|
||||
// Options If this is null and the server has no selected size options the defaults for the size will be used. If this is null and the server has currently selected size options those will be preserved. If this is provided any option fields that are not included will be removed from the existing server.
|
||||
@@ -2795,12 +2929,28 @@ type TakeBackup struct {
|
||||
BackupIdToReplace *int64 `json:"backup_id_to_replace"`
|
||||
|
||||
// BackupType If replacement_strategy is anything other than 'specified', this must be provided.
|
||||
//
|
||||
// | Value | Description |
|
||||
// | ----- | ----------- |
|
||||
// | daily | A backup which is scheduled to be taken each day. |
|
||||
// | weekly | A backup which is scheduled to be taken each week. |
|
||||
// | monthly | A backup which is scheduled to be taken each month. |
|
||||
// | temporary | A backup which is created on demand and only retained for a maximum of seven days. |
|
||||
//
|
||||
BackupType *BackupSlot `json:"backup_type"`
|
||||
|
||||
// Label An optional label to identify the backup.
|
||||
Label *string `json:"label"`
|
||||
|
||||
// ReplacementStrategy The strategy for selecting which backup to replace (if any).
|
||||
//
|
||||
// | Value | Description |
|
||||
// | ----- | ----------- |
|
||||
// | none | Do not replace any existing backup: use a free slot of the provided backup type. If there are no free slots an error will occur. |
|
||||
// | specified | Replace the specific backup id provided. |
|
||||
// | oldest | Use any free slots of the provided backup type, and if there are no free slots replace the oldest unlocked and un-attached backup of the provided backup type. |
|
||||
// | newest | Use any free slots of the provided backup type, and if there are no free slots replace the newest unlocked and un-attached backup of the provided backup type. |
|
||||
//
|
||||
ReplacementStrategy BackupReplacementStrategy `json:"replacement_strategy"`
|
||||
Type TakeBackupType `json:"type"`
|
||||
}
|
||||
@@ -2894,13 +3044,56 @@ type UnpaidFailedInvoicesResponse struct {
|
||||
Invoices *[]Invoice `json:"invoices,omitempty"`
|
||||
}
|
||||
|
||||
// UpdateDomainRecordRequest Any values not provided will be retained. Provide empty strings to clear existing string values, nulls to retain the existing values.
|
||||
type UpdateDomainRecordRequest struct {
|
||||
// Data A general data field that has different functions depending on the record type.
|
||||
Data *string `json:"data"`
|
||||
|
||||
// Flags An unsigned integer between 0-255 that is only relevant for CAA records.
|
||||
Flags *int32 `json:"flags"`
|
||||
|
||||
// Name The subdomain for this record. Use @ for records on the domain itself, and * to create a wildcard record.
|
||||
Name *string `json:"name"`
|
||||
|
||||
// Port A port value that is only relevant for SRV records.
|
||||
Port *int32 `json:"port"`
|
||||
|
||||
// Priority A priority value that is only relevant for SRV and MX records.
|
||||
Priority *int32 `json:"priority"`
|
||||
|
||||
// Tag A parameter tag that is only relevant for CAA records.
|
||||
Tag *string `json:"tag"`
|
||||
|
||||
// Ttl This value is the time to live for the record, in seconds.
|
||||
Ttl *int32 `json:"ttl"`
|
||||
|
||||
// Type The type of the DNS record.
|
||||
//
|
||||
// | Value | Description |
|
||||
// | ----- | ----------- |
|
||||
// | A | Map an IPv4 address to a hostname. |
|
||||
// | AAAA | Map an IPv6 address to a hostname. |
|
||||
// | CAA | Restrict which certificate authorities are permitted to issue certificates for a domain. |
|
||||
// | CNAME | Define an alias for your canonical hostname. |
|
||||
// | MX | Define the mail exchanges that handle mail for the domain. |
|
||||
// | NS | Define the nameservers that manage the domain. |
|
||||
// | SOA | The Start of Authority record for the zone. |
|
||||
// | SRV | Specify a server by hostname and port to handle a service or services. |
|
||||
// | TXT | Define a string of text that is associated with a hostname. |
|
||||
//
|
||||
Type *DomainRecordType `json:"type"`
|
||||
|
||||
// Weight The weight value that is only relevant for SRV records.
|
||||
Weight *int32 `json:"weight"`
|
||||
}
|
||||
|
||||
// UpdateLoadBalancerRequest defines model for UpdateLoadBalancerRequest.
|
||||
type UpdateLoadBalancerRequest struct {
|
||||
// ForwardingRules The rules that control which traffic the load balancer will forward to servers in the pool. Leave null to accept a default "HTTP" only forwarding rule.
|
||||
ForwardingRules *[]ForwardingRule `json:"forwarding_rules"`
|
||||
ForwardingRules *[]ForwardingRuleRequest `json:"forwarding_rules"`
|
||||
|
||||
// HealthCheck The rules that determine which servers are considered 'healthy' and in the server pool for the load balancer. Leave this null to accept appropriate defaults based on the forwarding_rules.
|
||||
HealthCheck *HealthCheck `json:"health_check"`
|
||||
HealthCheck *HealthCheckRequest `json:"health_check"`
|
||||
|
||||
// Name The hostname of the load balancer.
|
||||
Name string `json:"name"`
|
||||
@@ -2940,12 +3133,28 @@ type UploadImageRequest struct {
|
||||
BackupIdToReplace *int64 `json:"backup_id_to_replace"`
|
||||
|
||||
// BackupType If replacement_strategy is anything other than 'specified', this must be provided.
|
||||
//
|
||||
// | Value | Description |
|
||||
// | ----- | ----------- |
|
||||
// | daily | A backup which is scheduled to be taken each day. |
|
||||
// | weekly | A backup which is scheduled to be taken each week. |
|
||||
// | monthly | A backup which is scheduled to be taken each month. |
|
||||
// | temporary | A backup which is created on demand and only retained for a maximum of seven days. |
|
||||
//
|
||||
BackupType *BackupSlot `json:"backup_type"`
|
||||
|
||||
// Label An optional label to identify the backup.
|
||||
Label *string `json:"label"`
|
||||
|
||||
// ReplacementStrategy The strategy for selecting which backup to replace (if any).
|
||||
//
|
||||
// | Value | Description |
|
||||
// | ----- | ----------- |
|
||||
// | none | Do not replace any existing backup: use a free slot of the provided backup type. If there are no free slots an error will occur. |
|
||||
// | specified | Replace the specific backup id provided. |
|
||||
// | oldest | Use any free slots of the provided backup type, and if there are no free slots replace the oldest unlocked and un-attached backup of the provided backup type. |
|
||||
// | newest | Use any free slots of the provided backup type, and if there are no free slots replace the newest unlocked and un-attached backup of the provided backup type. |
|
||||
//
|
||||
ReplacementStrategy BackupReplacementStrategy `json:"replacement_strategy"`
|
||||
|
||||
// Url The source URL for the image to upload. Only HTTP and HTTPS sources are currently supported.
|
||||
@@ -2990,13 +3199,14 @@ type VideoDevice string
|
||||
// VmMachineType
|
||||
// | Value | Description |
|
||||
// | ----- | ----------- |
|
||||
// | pc_i440fx_1point5 | PC I440 FX 1.5 |
|
||||
// | pc_i440fx_2point11 | PC I440 FX 2.11 |
|
||||
// | pc_i440fx_4point1 | PC I440 FX 4.1 |
|
||||
// | pc_i440fx_4point2 | PC I440 FX 4.2 |
|
||||
// | pc_i440fx_5point0 | PC I440 FX 5.0 |
|
||||
// | pc_i440fx_5point1 | PC I440 FX 5.1 |
|
||||
// | pc_i440fx_7point2 | PC I440 FX 7.2 |
|
||||
// | pc_i440fx_1point5 | PC i440FX 1.5 |
|
||||
// | pc_i440fx_2point11 | PC i440FX 2.11 |
|
||||
// | pc_i440fx_4point1 | PC i440FX 4.1 |
|
||||
// | pc_i440fx_4point2 | PC i440FX 4.2 |
|
||||
// | pc_i440fx_5point0 | PC i440FX 5.0 |
|
||||
// | pc_i440fx_5point1 | PC i440FX 5.1 |
|
||||
// | pc_i440fx_7point2 | PC i440FX 7.2 |
|
||||
// | pc_i440fx_8point2 | PC i440FX 8.2 |
|
||||
type VmMachineType string
|
||||
|
||||
// Vpc defines model for Vpc.
|
||||
@@ -3107,6 +3317,9 @@ type GetDomainsParams struct {
|
||||
// PostDomainsJSONBody defines parameters for PostDomains.
|
||||
type PostDomainsJSONBody = DomainRequest
|
||||
|
||||
// PostDomainsRefreshNameserverCacheJSONBody defines parameters for PostDomainsRefreshNameserverCache.
|
||||
type PostDomainsRefreshNameserverCacheJSONBody = DomainRefreshRequest
|
||||
|
||||
// DeleteDomainsDomainNameParamsDomainName0 defines parameters for DeleteDomainsDomainName.
|
||||
type DeleteDomainsDomainNameParamsDomainName0 = int
|
||||
|
||||
@@ -3174,7 +3387,7 @@ type GetDomainsDomainNameRecordsRecordIdParamsDomainName0 = int
|
||||
type GetDomainsDomainNameRecordsRecordIdParamsDomainName1 = string
|
||||
|
||||
// PutDomainsDomainNameRecordsRecordIdJSONBody defines parameters for PutDomainsDomainNameRecordsRecordId.
|
||||
type PutDomainsDomainNameRecordsRecordIdJSONBody = DomainRecordRequest
|
||||
type PutDomainsDomainNameRecordsRecordIdJSONBody = UpdateDomainRecordRequest
|
||||
|
||||
// PutDomainsDomainNameRecordsRecordIdParamsDomainName0 defines parameters for PutDomainsDomainNameRecordsRecordId.
|
||||
type PutDomainsDomainNameRecordsRecordIdParamsDomainName0 = int
|
||||
@@ -3455,6 +3668,9 @@ type PostActionsActionIdProceedJSONRequestBody = PostActionsActionIdProceedJSONB
|
||||
// PostDomainsJSONRequestBody defines body for PostDomains for application/json ContentType.
|
||||
type PostDomainsJSONRequestBody = PostDomainsJSONBody
|
||||
|
||||
// PostDomainsRefreshNameserverCacheJSONRequestBody defines body for PostDomainsRefreshNameserverCache for application/json ContentType.
|
||||
type PostDomainsRefreshNameserverCacheJSONRequestBody = PostDomainsRefreshNameserverCacheJSONBody
|
||||
|
||||
// PostDomainsDomainNameRecordsJSONRequestBody defines body for PostDomainsDomainNameRecords for application/json ContentType.
|
||||
type PostDomainsDomainNameRecordsJSONRequestBody = PostDomainsDomainNameRecordsJSONBody
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"terraform-provider-binarylane/internal/resources"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-framework/datasource"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -22,8 +23,9 @@ type loadBalancerDataSource struct {
|
||||
bc *BinarylaneClient
|
||||
}
|
||||
|
||||
type loadBalancerDataSourceModel struct {
|
||||
type loadBalancerDataModel struct {
|
||||
resources.LoadBalancerModel
|
||||
Ip types.String `tfsdk:"ip"`
|
||||
}
|
||||
|
||||
func (d *loadBalancerDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
|
||||
@@ -52,7 +54,7 @@ func (d *loadBalancerDataSource) Configure(
|
||||
|
||||
func (d *loadBalancerDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) {
|
||||
ds, err := convertResourceSchemaToDataSourceSchema(
|
||||
resources.LoadBalancerResourceSchema(ctx),
|
||||
loadBalancerSchema(ctx),
|
||||
AttributeConfig{
|
||||
RequiredAttributes: &[]string{"id"},
|
||||
},
|
||||
@@ -63,10 +65,11 @@ func (d *loadBalancerDataSource) Schema(ctx context.Context, req datasource.Sche
|
||||
}
|
||||
resp.Schema = *ds
|
||||
resp.Schema.Description = "Retrieve details about a BinaryLane Load Balancer."
|
||||
resp.Schema.MarkdownDescription = resp.Schema.Description
|
||||
}
|
||||
|
||||
func (d *loadBalancerDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
|
||||
var data loadBalancerDataSourceModel
|
||||
var data loadBalancerDataModel
|
||||
|
||||
// Read Terraform prior state data into the model
|
||||
resp.Diagnostics.Append(req.Config.Get(ctx, &data)...)
|
||||
@@ -93,7 +96,7 @@ func (d *loadBalancerDataSource) Read(ctx context.Context, req datasource.ReadRe
|
||||
return
|
||||
}
|
||||
|
||||
diags := setLoadBalancerModelState(ctx, &data.LoadBalancerModel, lbResp.JSON200.LoadBalancer)
|
||||
diags := setLoadBalancerModelState(ctx, &data, lbResp.JSON200.LoadBalancer)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
|
||||
@@ -10,14 +10,17 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-framework-timeouts/resource/timeouts"
|
||||
"github.com/hashicorp/terraform-plugin-framework-validators/listvalidator"
|
||||
"github.com/hashicorp/terraform-plugin-framework/attr"
|
||||
"github.com/hashicorp/terraform-plugin-framework/diag"
|
||||
"github.com/hashicorp/terraform-plugin-framework/path"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/int64planmodifier"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/listdefault"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
|
||||
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||
"github.com/hashicorp/terraform-plugin-log/tflog"
|
||||
)
|
||||
@@ -37,7 +40,7 @@ type loadBalancerResource struct {
|
||||
}
|
||||
|
||||
type loadBalancerResourceModel struct {
|
||||
resources.LoadBalancerModel
|
||||
loadBalancerDataModel
|
||||
Timeouts timeouts.Value `tfsdk:"timeouts"`
|
||||
}
|
||||
|
||||
@@ -60,15 +63,15 @@ func (d *loadBalancerResource) Configure(_ context.Context, req resource.Configu
|
||||
d.bc = &bc
|
||||
}
|
||||
|
||||
func (r *loadBalancerResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
|
||||
resp.Schema = resources.LoadBalancerResourceSchema(ctx)
|
||||
resp.Schema.Description = "Provides a BinaryLane Load Balancer resource. This can be used to create, update, and delete load balancers."
|
||||
resp.Schema.MarkdownDescription = resp.Schema.Description +
|
||||
func loadBalancerSchema(ctx context.Context) schema.Schema {
|
||||
s := resources.LoadBalancerResourceSchema(ctx)
|
||||
s.Description = "Provides a BinaryLane Load Balancer resource. This can be used to create, update, and delete load balancers."
|
||||
s.MarkdownDescription = s.Description +
|
||||
" See [the docs](https://support.binarylane.com.au/support/solutions/articles/1000025661-load-balancer) for more information."
|
||||
|
||||
// Overrides
|
||||
id := resp.Schema.Attributes["id"]
|
||||
resp.Schema.Attributes["id"] = &schema.Int64Attribute{
|
||||
id := s.Attributes["id"]
|
||||
s.Attributes["id"] = schema.Int64Attribute{
|
||||
Description: id.GetDescription(),
|
||||
MarkdownDescription: id.GetMarkdownDescription(),
|
||||
// read only
|
||||
@@ -80,8 +83,8 @@ func (r *loadBalancerResource) Schema(ctx context.Context, req resource.SchemaRe
|
||||
},
|
||||
}
|
||||
|
||||
region := resp.Schema.Attributes["region"]
|
||||
resp.Schema.Attributes["region"] = &schema.StringAttribute{
|
||||
region := s.Attributes["region"]
|
||||
s.Attributes["region"] = schema.StringAttribute{
|
||||
Description: region.GetDescription(),
|
||||
MarkdownDescription: region.GetMarkdownDescription(),
|
||||
Optional: true,
|
||||
@@ -91,6 +94,49 @@ func (r *loadBalancerResource) Schema(ctx context.Context, req resource.SchemaRe
|
||||
},
|
||||
}
|
||||
|
||||
forwardingRules := s.Attributes["forwarding_rules"].(schema.ListNestedAttribute)
|
||||
s.Attributes["forwarding_rules"] = schema.ListNestedAttribute{
|
||||
NestedObject: forwardingRules.NestedObject,
|
||||
Description: forwardingRules.GetDescription(),
|
||||
MarkdownDescription: forwardingRules.GetMarkdownDescription(),
|
||||
Required: false,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
Default: listdefault.StaticValue(types.ListValueMust(
|
||||
types.ObjectType{
|
||||
AttrTypes: resources.ForwardingRulesValue{}.AttributeTypes(ctx),
|
||||
},
|
||||
[]attr.Value{
|
||||
types.ObjectValueMust(
|
||||
map[string]attr.Type{
|
||||
"entry_protocol": types.StringType,
|
||||
},
|
||||
map[string]attr.Value{
|
||||
"entry_protocol": types.StringValue("http"),
|
||||
},
|
||||
),
|
||||
},
|
||||
)),
|
||||
Validators: []validator.List{
|
||||
listvalidator.SizeAtLeast(1),
|
||||
},
|
||||
}
|
||||
|
||||
// Additional attributes
|
||||
s.Attributes["ip"] = schema.StringAttribute{
|
||||
Description: "The IPv4 address of the load balancer.",
|
||||
MarkdownDescription: "The IPv4 address of the load balancer.",
|
||||
Required: false,
|
||||
Optional: false,
|
||||
Computed: true,
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
func (r *loadBalancerResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
|
||||
resp.Schema = loadBalancerSchema(ctx)
|
||||
|
||||
resp.Schema.Attributes["timeouts"] =
|
||||
timeouts.Attributes(ctx, timeouts.Opts{
|
||||
Create: true,
|
||||
@@ -108,7 +154,7 @@ func (r *loadBalancerResource) Create(ctx context.Context, req resource.CreateRe
|
||||
}
|
||||
|
||||
// Create API call logic
|
||||
forwardingRules := []binarylane.ForwardingRule{}
|
||||
forwardingRules := []binarylane.ForwardingRuleRequest{}
|
||||
diags := data.LoadBalancerModel.ForwardingRules.ElementsAs(ctx, &forwardingRules, false)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
@@ -129,7 +175,7 @@ func (r *loadBalancerResource) Create(ctx context.Context, req resource.CreateRe
|
||||
}
|
||||
|
||||
if data.HealthCheck.Path.ValueStringPointer() != nil || data.HealthCheck.Protocol.ValueStringPointer() != nil {
|
||||
body.HealthCheck = &binarylane.HealthCheck{
|
||||
body.HealthCheck = &binarylane.HealthCheckRequest{
|
||||
Path: data.HealthCheck.Path.ValueStringPointer(),
|
||||
Protocol: data.HealthCheck.Protocol.ValueStringPointer(),
|
||||
}
|
||||
@@ -154,7 +200,7 @@ func (r *loadBalancerResource) Create(ctx context.Context, req resource.CreateRe
|
||||
return
|
||||
}
|
||||
|
||||
diags = setLoadBalancerModelState(ctx, &data.LoadBalancerModel, lbResp.JSON200.LoadBalancer)
|
||||
diags = setLoadBalancerModelState(ctx, &data.loadBalancerDataModel, lbResp.JSON200.LoadBalancer)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
@@ -253,7 +299,7 @@ func (r *loadBalancerResource) Read(ctx context.Context, req resource.ReadReques
|
||||
return
|
||||
}
|
||||
|
||||
diags := setLoadBalancerModelState(ctx, &data.LoadBalancerModel, lbResp.JSON200.LoadBalancer)
|
||||
diags := setLoadBalancerModelState(ctx, &data.loadBalancerDataModel, lbResp.JSON200.LoadBalancer)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
@@ -274,7 +320,7 @@ func (r *loadBalancerResource) Update(ctx context.Context, req resource.UpdateRe
|
||||
}
|
||||
|
||||
// Update API call logic
|
||||
forwardingRules := &[]binarylane.ForwardingRule{}
|
||||
forwardingRules := &[]binarylane.ForwardingRuleRequest{}
|
||||
diags := data.LoadBalancerModel.ForwardingRules.ElementsAs(ctx, forwardingRules, true)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
@@ -293,7 +339,7 @@ func (r *loadBalancerResource) Update(ctx context.Context, req resource.UpdateRe
|
||||
body := binarylane.UpdateLoadBalancerRequest{
|
||||
Name: data.Name.ValueString(),
|
||||
ForwardingRules: forwardingRules,
|
||||
HealthCheck: &binarylane.HealthCheck{
|
||||
HealthCheck: &binarylane.HealthCheckRequest{
|
||||
Path: data.HealthCheck.Path.ValueStringPointer(),
|
||||
Protocol: data.HealthCheck.Protocol.ValueStringPointer(),
|
||||
},
|
||||
@@ -317,7 +363,7 @@ func (r *loadBalancerResource) Update(ctx context.Context, req resource.UpdateRe
|
||||
return
|
||||
}
|
||||
|
||||
diags = setLoadBalancerModelState(ctx, &data.LoadBalancerModel, lbResp.JSON200.LoadBalancer)
|
||||
diags = setLoadBalancerModelState(ctx, &data.loadBalancerDataModel, lbResp.JSON200.LoadBalancer)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
@@ -396,7 +442,7 @@ func (r *loadBalancerResource) ImportState(
|
||||
|
||||
loadBalancers := *lbResp.JSON200.LoadBalancers
|
||||
for _, lb := range loadBalancers {
|
||||
if *lb.Name == req.ID {
|
||||
if lb.Name == req.ID {
|
||||
loadBalancer = lb
|
||||
nextPage = false
|
||||
break
|
||||
@@ -410,23 +456,16 @@ func (r *loadBalancerResource) ImportState(
|
||||
page++
|
||||
}
|
||||
|
||||
if loadBalancer.Id == nil {
|
||||
resp.Diagnostics.AddError(
|
||||
"Could not find load balancer by name",
|
||||
fmt.Sprintf("Error finding load balancer: name=%s", req.ID),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
diags := resp.State.SetAttribute(ctx, path.Root("id"), *loadBalancer.Id)
|
||||
diags := resp.State.SetAttribute(ctx, path.Root("id"), loadBalancer.Id)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
}
|
||||
|
||||
func setLoadBalancerModelState(ctx context.Context, data *resources.LoadBalancerModel, lb *binarylane.LoadBalancer) diag.Diagnostics {
|
||||
func setLoadBalancerModelState(ctx context.Context, data *loadBalancerDataModel, lb *binarylane.LoadBalancer) diag.Diagnostics {
|
||||
var diags, diag diag.Diagnostics
|
||||
|
||||
data.Id = types.Int64Value(*lb.Id)
|
||||
data.Name = types.StringValue(*lb.Name)
|
||||
data.Id = types.Int64Value(lb.Id)
|
||||
data.Name = types.StringValue(lb.Name)
|
||||
data.Ip = types.StringValue(lb.Ip)
|
||||
|
||||
if lb.Region == nil {
|
||||
data.Region = types.StringNull()
|
||||
@@ -436,18 +475,14 @@ func setLoadBalancerModelState(ctx context.Context, data *resources.LoadBalancer
|
||||
|
||||
data.ServerIds, diags = types.ListValueFrom(ctx, types.Int64Type, lb.ServerIds)
|
||||
|
||||
if lb.HealthCheck == nil {
|
||||
data.HealthCheck = resources.NewHealthCheckValueNull()
|
||||
} else {
|
||||
data.HealthCheck, diag = resources.NewHealthCheckValue(
|
||||
resources.HealthCheckValue{}.AttributeTypes(ctx),
|
||||
map[string]attr.Value{
|
||||
"path": types.StringValue(*lb.HealthCheck.Path),
|
||||
"protocol": types.StringValue(*lb.HealthCheck.Protocol),
|
||||
},
|
||||
)
|
||||
diags.Append(diag...)
|
||||
}
|
||||
data.HealthCheck, diag = resources.NewHealthCheckValue(
|
||||
resources.HealthCheckValue{}.AttributeTypes(ctx),
|
||||
map[string]attr.Value{
|
||||
"path": types.StringValue(lb.HealthCheck.Path),
|
||||
"protocol": types.StringValue(lb.HealthCheck.Protocol),
|
||||
},
|
||||
)
|
||||
diags.Append(diag...)
|
||||
|
||||
data.ForwardingRules, diag = types.ListValueFrom(ctx,
|
||||
types.ObjectType{AttrTypes: resources.ForwardingRulesValue{}.AttributeTypes(ctx)},
|
||||
|
||||
@@ -2,8 +2,6 @@ package provider
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
@@ -16,13 +14,7 @@ import (
|
||||
|
||||
func TestLoadBalancerResource(t *testing.T) {
|
||||
// Must assign a password to the server or Binary Lane will send emails
|
||||
pw_bytes := make([]byte, 12)
|
||||
_, err := rand.Read(pw_bytes)
|
||||
if err != nil {
|
||||
t.Errorf("Failed to generate password: %s", err)
|
||||
return
|
||||
}
|
||||
password := base64.URLEncoding.EncodeToString(pw_bytes)
|
||||
password := GenerateTestPassword(t)
|
||||
|
||||
resource.ParallelTest(t, resource.TestCase{
|
||||
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
|
||||
@@ -43,7 +35,7 @@ resource "binarylane_server" "test" {
|
||||
resource "binarylane_load_balancer" "test" {
|
||||
name = "tf-test-lb"
|
||||
server_ids = [binarylane_server.test.0.id, binarylane_server.test.1.id]
|
||||
forwarding_rules = [{ entry_protocol = "http" }]
|
||||
# initially, skip defining forwarding_rules, health_check, to test default values
|
||||
}
|
||||
|
||||
data "binarylane_load_balancer" "test" {
|
||||
@@ -62,6 +54,9 @@ data "binarylane_load_balancer" "test" {
|
||||
resource.TestCheckResourceAttrPair("binarylane_load_balancer.test", "server_ids.1", "binarylane_server.test.1", "id"),
|
||||
resource.TestCheckResourceAttr("binarylane_load_balancer.test", "forwarding_rules.#", "1"),
|
||||
resource.TestCheckResourceAttr("binarylane_load_balancer.test", "forwarding_rules.0.entry_protocol", "http"),
|
||||
resource.TestCheckResourceAttr("binarylane_load_balancer.test", "health_check.path", "/"),
|
||||
resource.TestCheckResourceAttr("binarylane_load_balancer.test", "health_check.protocol", "http"),
|
||||
resource.TestCheckResourceAttrSet("binarylane_load_balancer.test", "ip"),
|
||||
|
||||
// Verify data source values
|
||||
resource.TestCheckResourceAttrPair("data.binarylane_load_balancer.test", "id", "binarylane_load_balancer.test", "id"),
|
||||
@@ -72,6 +67,9 @@ data "binarylane_load_balancer" "test" {
|
||||
resource.TestCheckResourceAttrPair("data.binarylane_load_balancer.test", "server_ids.1", "binarylane_server.test.1", "id"),
|
||||
resource.TestCheckResourceAttr("data.binarylane_load_balancer.test", "forwarding_rules.#", "1"),
|
||||
resource.TestCheckResourceAttr("data.binarylane_load_balancer.test", "forwarding_rules.0.entry_protocol", "http"),
|
||||
resource.TestCheckResourceAttr("data.binarylane_load_balancer.test", "health_check.path", "/"),
|
||||
resource.TestCheckResourceAttr("data.binarylane_load_balancer.test", "health_check.protocol", "http"),
|
||||
resource.TestCheckResourceAttrSet("data.binarylane_load_balancer.test", "ip"),
|
||||
),
|
||||
},
|
||||
// Test import by ID
|
||||
@@ -87,6 +85,63 @@ data "binarylane_load_balancer" "test" {
|
||||
ImportStateId: "tf-test-lb",
|
||||
ImportStateVerify: true,
|
||||
},
|
||||
{
|
||||
Config: providerConfig + `
|
||||
resource "binarylane_server" "test" {
|
||||
count = 2
|
||||
name = "tf-test-lb-server-${count.index}"
|
||||
region = "per"
|
||||
image = "debian-12"
|
||||
size = "std-min"
|
||||
password = "` + password + `"
|
||||
public_ipv4_count = 1
|
||||
}
|
||||
|
||||
resource "binarylane_load_balancer" "test" {
|
||||
name = "tf-test-lb"
|
||||
server_ids = [binarylane_server.test.0.id, binarylane_server.test.1.id]
|
||||
# updated
|
||||
forwarding_rules = [{ entry_protocol = "https" }]
|
||||
health_check = {
|
||||
path = "/test-health"
|
||||
protocol = "https"
|
||||
}
|
||||
}
|
||||
|
||||
data "binarylane_load_balancer" "test" {
|
||||
depends_on = [binarylane_load_balancer.test]
|
||||
|
||||
id = binarylane_load_balancer.test.id
|
||||
}
|
||||
`,
|
||||
Check: resource.ComposeAggregateTestCheckFunc(
|
||||
// Verify resource values
|
||||
resource.TestCheckResourceAttrSet("binarylane_load_balancer.test", "id"),
|
||||
resource.TestCheckResourceAttr("binarylane_load_balancer.test", "name", "tf-test-lb"),
|
||||
resource.TestCheckNoResourceAttr("binarylane_load_balancer.test", "region"),
|
||||
resource.TestCheckResourceAttr("binarylane_load_balancer.test", "server_ids.#", "2"),
|
||||
resource.TestCheckResourceAttrPair("binarylane_load_balancer.test", "server_ids.0", "binarylane_server.test.0", "id"),
|
||||
resource.TestCheckResourceAttrPair("binarylane_load_balancer.test", "server_ids.1", "binarylane_server.test.1", "id"),
|
||||
resource.TestCheckResourceAttr("binarylane_load_balancer.test", "forwarding_rules.#", "1"),
|
||||
resource.TestCheckResourceAttr("binarylane_load_balancer.test", "forwarding_rules.0.entry_protocol", "https"),
|
||||
resource.TestCheckResourceAttr("binarylane_load_balancer.test", "health_check.path", "/test-health"),
|
||||
resource.TestCheckResourceAttr("binarylane_load_balancer.test", "health_check.protocol", "https"),
|
||||
resource.TestCheckResourceAttrSet("binarylane_load_balancer.test", "ip"),
|
||||
|
||||
// Verify data source values
|
||||
resource.TestCheckResourceAttrPair("data.binarylane_load_balancer.test", "id", "binarylane_load_balancer.test", "id"),
|
||||
resource.TestCheckResourceAttr("data.binarylane_load_balancer.test", "name", "tf-test-lb"),
|
||||
resource.TestCheckNoResourceAttr("data.binarylane_load_balancer.test", "region"),
|
||||
resource.TestCheckResourceAttr("data.binarylane_load_balancer.test", "server_ids.#", "2"),
|
||||
resource.TestCheckResourceAttrPair("data.binarylane_load_balancer.test", "server_ids.0", "binarylane_server.test.0", "id"),
|
||||
resource.TestCheckResourceAttrPair("data.binarylane_load_balancer.test", "server_ids.1", "binarylane_server.test.1", "id"),
|
||||
resource.TestCheckResourceAttr("data.binarylane_load_balancer.test", "forwarding_rules.#", "1"),
|
||||
resource.TestCheckResourceAttr("data.binarylane_load_balancer.test", "forwarding_rules.0.entry_protocol", "https"),
|
||||
resource.TestCheckResourceAttr("data.binarylane_load_balancer.test", "health_check.path", "/test-health"),
|
||||
resource.TestCheckResourceAttr("data.binarylane_load_balancer.test", "health_check.protocol", "https"),
|
||||
resource.TestCheckResourceAttrSet("data.binarylane_load_balancer.test", "ip"),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -125,15 +180,15 @@ func init() {
|
||||
|
||||
loadBalancers := *listResp.JSON200.LoadBalancers
|
||||
for _, lb := range loadBalancers {
|
||||
if strings.HasPrefix(*lb.Name, "tf-test-") {
|
||||
deleteResp, err := client.DeleteLoadBalancersLoadBalancerIdWithResponse(ctx, *lb.Id)
|
||||
if strings.HasPrefix(lb.Name, "tf-test-") {
|
||||
deleteResp, err := client.DeleteLoadBalancersLoadBalancerIdWithResponse(ctx, lb.Id)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error deleting load balancer %d for test sweep: %w", *lb.Id, err)
|
||||
return fmt.Errorf("Error deleting load balancer %d for test sweep: %w", lb.Id, err)
|
||||
}
|
||||
if deleteResp.StatusCode() != http.StatusNoContent {
|
||||
return fmt.Errorf("Unexpected status %d deleting load balancer %d in test sweep: %s", deleteResp.StatusCode(), *lb.Id, deleteResp.Body)
|
||||
return fmt.Errorf("Unexpected status %d deleting load balancer %d in test sweep: %s", deleteResp.StatusCode(), lb.Id, deleteResp.Body)
|
||||
}
|
||||
log.Println("Deleted load balancer during test sweep:", *lb.Id)
|
||||
log.Println("Deleted load balancer during test sweep:", lb.Id)
|
||||
}
|
||||
}
|
||||
if listResp.JSON200.Links == nil || listResp.JSON200.Links.Pages == nil || listResp.JSON200.Links.Pages.Next == nil {
|
||||
|
||||
@@ -4,10 +4,12 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"slices"
|
||||
"terraform-provider-binarylane/internal/resources"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-framework/attr"
|
||||
"github.com/hashicorp/terraform-plugin-framework/datasource"
|
||||
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
|
||||
"github.com/hashicorp/terraform-plugin-framework/diag"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||
)
|
||||
|
||||
@@ -27,11 +29,14 @@ type serverDataSource struct {
|
||||
|
||||
type serverDataModel struct {
|
||||
resources.ServerModel
|
||||
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"`
|
||||
PublicIpv4Addresses types.List `tfsdk:"public_ipv4_addresses"`
|
||||
PrivateIPv4Addresses types.List `tfsdk:"private_ipv4_addresses"`
|
||||
PublicIpv6Addresses types.List `tfsdk:"public_ipv6_addresses"`
|
||||
PrivateIpv6Addresses types.List `tfsdk:"private_ipv6_addresses"`
|
||||
Permalink types.String `tfsdk:"permalink"`
|
||||
Memory types.Int32 `tfsdk:"memory"`
|
||||
Disk types.Int32 `tfsdk:"disk"`
|
||||
SourceAndDestinationCheck types.Bool `tfsdk:"source_and_destination_check"`
|
||||
}
|
||||
|
||||
func (d *serverDataSource) Configure(_ context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
|
||||
@@ -58,10 +63,10 @@ func (d *serverDataSource) Metadata(ctx context.Context, req datasource.Metadata
|
||||
|
||||
func (d *serverDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) {
|
||||
ds, err := convertResourceSchemaToDataSourceSchema(
|
||||
resources.ServerResourceSchema(ctx),
|
||||
serverSchema(ctx),
|
||||
AttributeConfig{
|
||||
RequiredAttributes: &[]string{"id"},
|
||||
ExcludedAttributes: &[]string{"password"},
|
||||
ExcludedAttributes: &[]string{"password", "public_ipv4_count", "password_change_supported", "timeouts"},
|
||||
})
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError("Failed to convert resource schema to data source schema", err.Error())
|
||||
@@ -69,110 +74,10 @@ func (d *serverDataSource) Schema(ctx context.Context, req datasource.SchemaRequ
|
||||
}
|
||||
resp.Schema = *ds
|
||||
resp.Schema.Description = "Retrieve details about a BinaryLane Server."
|
||||
|
||||
// Overrides
|
||||
id := resp.Schema.Attributes["id"]
|
||||
resp.Schema.Attributes["id"] = schema.Int64Attribute{
|
||||
Description: id.GetDescription(),
|
||||
MarkdownDescription: id.GetMarkdownDescription(),
|
||||
Required: true, // ID is required to find the server
|
||||
}
|
||||
|
||||
nameDescription := "The hostname of your server, such as vps01.yourcompany.com."
|
||||
resp.Schema.Attributes["name"] = &schema.StringAttribute{
|
||||
Description: nameDescription,
|
||||
MarkdownDescription: nameDescription,
|
||||
Optional: false,
|
||||
Required: false,
|
||||
Computed: true,
|
||||
}
|
||||
|
||||
backupsDescription := "If `true`, the server will be backed up twice per day. By default, backups are disabled."
|
||||
resp.Schema.Attributes["backups"] = &schema.BoolAttribute{
|
||||
Description: backupsDescription,
|
||||
MarkdownDescription: backupsDescription,
|
||||
Optional: false,
|
||||
Required: false,
|
||||
Computed: true,
|
||||
}
|
||||
|
||||
sshKeysDescription := "This is a list of SSH key ids that were added to the server during creation."
|
||||
resp.Schema.Attributes["ssh_keys"] = &schema.ListAttribute{
|
||||
ElementType: types.Int64Type,
|
||||
Description: sshKeysDescription,
|
||||
MarkdownDescription: sshKeysDescription,
|
||||
Optional: false,
|
||||
Required: false,
|
||||
Computed: true,
|
||||
}
|
||||
|
||||
userDataDescription := "A script or cloud-config YAML file to configure the server."
|
||||
resp.Schema.Attributes["user_data"] = &schema.StringAttribute{
|
||||
Description: userDataDescription,
|
||||
MarkdownDescription: userDataDescription,
|
||||
Optional: false,
|
||||
Required: false,
|
||||
Computed: true,
|
||||
}
|
||||
|
||||
vpcIdDescription := "ID of the Virtual Private Cloud (VPC) the server is connected to."
|
||||
resp.Schema.Attributes["vpc_id"] = &schema.Int64Attribute{
|
||||
Description: vpcIdDescription,
|
||||
MarkdownDescription: vpcIdDescription,
|
||||
Optional: false,
|
||||
Required: false,
|
||||
Computed: true,
|
||||
}
|
||||
|
||||
// Additional attributes
|
||||
resp.Schema.Attributes["permalink"] = &schema.StringAttribute{
|
||||
Description: "A randomly generated two-word identifier assigned to servers in regions that support this feature",
|
||||
MarkdownDescription: "A randomly generated two-word identifier assigned to servers in regions that support this feature",
|
||||
Optional: false,
|
||||
Required: false,
|
||||
Computed: true,
|
||||
}
|
||||
|
||||
publicIpv4AddressesDescription := "The public IPv4 addresses assigned to the server."
|
||||
resp.Schema.Attributes["public_ipv4_addresses"] = &schema.ListAttribute{
|
||||
Description: publicIpv4AddressesDescription,
|
||||
MarkdownDescription: publicIpv4AddressesDescription,
|
||||
ElementType: types.StringType,
|
||||
Optional: false,
|
||||
Required: false,
|
||||
Computed: true,
|
||||
}
|
||||
|
||||
privateIpv4AddressesDescription := "The private IPv4 addresses assigned to the server."
|
||||
resp.Schema.Attributes["private_ipv4_addresses"] = &schema.ListAttribute{
|
||||
Description: privateIpv4AddressesDescription,
|
||||
MarkdownDescription: privateIpv4AddressesDescription,
|
||||
ElementType: types.StringType,
|
||||
Optional: false,
|
||||
Required: false,
|
||||
Computed: true,
|
||||
}
|
||||
|
||||
memoryDescription := "The amount of memory in MB assigned to the server."
|
||||
resp.Schema.Attributes["memory"] = &schema.Int32Attribute{
|
||||
Description: memoryDescription,
|
||||
MarkdownDescription: memoryDescription,
|
||||
Optional: false,
|
||||
Required: false,
|
||||
Computed: true,
|
||||
}
|
||||
|
||||
diskDescription := "The amount of storage in GB assigned to the server."
|
||||
resp.Schema.Attributes["disk"] = &schema.Int32Attribute{
|
||||
Description: diskDescription,
|
||||
MarkdownDescription: diskDescription,
|
||||
Optional: false,
|
||||
Required: false,
|
||||
Computed: true,
|
||||
}
|
||||
}
|
||||
|
||||
func (d *serverDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
|
||||
var diag diag.Diagnostics
|
||||
var data serverDataModel
|
||||
|
||||
// Read Terraform configuration data into the model
|
||||
@@ -206,11 +111,33 @@ func (d *serverDataSource) Read(ctx context.Context, req datasource.ReadRequest,
|
||||
data.Region = types.StringValue(*serverResp.JSON200.Server.Region.Slug)
|
||||
data.Size = types.StringValue(*serverResp.JSON200.Server.Size.Slug)
|
||||
data.Backups = types.BoolValue(serverResp.JSON200.Server.NextBackupWindow != nil)
|
||||
data.Ipv6 = types.BoolValue(len(serverResp.JSON200.Server.Networks.V6) > 0)
|
||||
data.PortBlocking = types.BoolValue(serverResp.JSON200.Server.Networks.PortBlocking)
|
||||
data.VpcId = types.Int64PointerValue(serverResp.JSON200.Server.VpcId)
|
||||
data.Permalink = types.StringValue(*serverResp.JSON200.Server.Permalink)
|
||||
data.Memory = types.Int32Value(*serverResp.JSON200.Server.Memory)
|
||||
data.Disk = types.Int32Value(*serverResp.JSON200.Server.Disk)
|
||||
data.SourceAndDestinationCheck = types.BoolPointerValue(serverResp.JSON200.Server.Networks.SourceAndDestinationCheck)
|
||||
|
||||
advFeat := *serverResp.JSON200.Server.AdvancedFeatures.EnabledAdvancedFeatures
|
||||
data.AdvancedFeatures, diags = resources.NewAdvancedFeaturesValue(
|
||||
resources.AdvancedFeaturesValue{}.AttributeTypes(ctx),
|
||||
map[string]attr.Value{
|
||||
"emulated_hyperv": types.BoolValue(slices.Contains(advFeat, "emulated-hyperv")),
|
||||
"emulated_devices": types.BoolValue(slices.Contains(advFeat, "emulated-devices")),
|
||||
"nested_virt": types.BoolValue(slices.Contains(advFeat, "nested-virt")),
|
||||
"driver_disk": types.BoolValue(slices.Contains(advFeat, "driver-disk")),
|
||||
"unset_uuid": types.BoolValue(slices.Contains(advFeat, "unset-uuid")),
|
||||
"local_rtc": types.BoolValue(slices.Contains(advFeat, "local-rtc")),
|
||||
"emulated_tpm": types.BoolValue(slices.Contains(advFeat, "emulated-tpm")),
|
||||
"cloud_init": types.BoolValue(slices.Contains(advFeat, "cloud-init")),
|
||||
"qemu_guest_agent": types.BoolValue(slices.Contains(advFeat, "qemu-guest-agent")),
|
||||
"uefi_boot": types.BoolValue(slices.Contains(advFeat, "uefi-boot")),
|
||||
})
|
||||
if diags.HasError() {
|
||||
data.AdvancedFeatures = resources.NewAdvancedFeaturesValueUnknown()
|
||||
}
|
||||
|
||||
publicIpv4Addresses := []string{}
|
||||
privateIpv4Addresses := []string{}
|
||||
|
||||
@@ -238,6 +165,33 @@ func (d *serverDataSource) Read(ctx context.Context, req datasource.ReadRequest,
|
||||
data.PrivateIPv4Addresses = tfPrivateIpv4Addresses
|
||||
}
|
||||
|
||||
publicIpv6Addresses := []string{}
|
||||
privateIpv6Addresses := []string{}
|
||||
|
||||
for _, v6address := range serverResp.JSON200.Server.Networks.V6 {
|
||||
if v6address.Type == "public" {
|
||||
publicIpv6Addresses = append(publicIpv6Addresses, v6address.IpAddress)
|
||||
} else {
|
||||
privateIpv6Addresses = append(privateIpv6Addresses, v6address.IpAddress)
|
||||
}
|
||||
}
|
||||
|
||||
tfPublicIpv6Addresses, diag := types.ListValueFrom(ctx, types.StringType, publicIpv6Addresses)
|
||||
diags.Append(diag...)
|
||||
if diag.HasError() {
|
||||
data.PublicIpv6Addresses = types.ListUnknown(data.PublicIpv6Addresses.ElementType(ctx))
|
||||
} else {
|
||||
data.PublicIpv6Addresses = tfPublicIpv6Addresses
|
||||
}
|
||||
|
||||
tfPrivateIpv6Addresses, diag := types.ListValueFrom(ctx, types.StringType, privateIpv6Addresses)
|
||||
diags.Append(diag...)
|
||||
if diag.HasError() {
|
||||
data.PrivateIpv6Addresses = types.ListUnknown(data.PrivateIpv6Addresses.ElementType(ctx))
|
||||
} else {
|
||||
data.PrivateIpv6Addresses = tfPrivateIpv6Addresses
|
||||
}
|
||||
|
||||
// Get user data script
|
||||
userDataResp, err := d.bc.client.GetServersServerIdUserDataWithResponse(ctx, data.Id.ValueInt64())
|
||||
if err != nil {
|
||||
|
||||
@@ -63,7 +63,7 @@ func (r *serverFirewallRulesResource) Schema(ctx context.Context, req resource.S
|
||||
|
||||
// Overrides
|
||||
serverId := resp.Schema.Attributes["server_id"]
|
||||
resp.Schema.Attributes["server_id"] = &schema.Int64Attribute{
|
||||
resp.Schema.Attributes["server_id"] = schema.Int64Attribute{
|
||||
Description: serverId.GetDescription(),
|
||||
MarkdownDescription: serverId.GetMarkdownDescription(),
|
||||
Required: true, // Server ID is required to define the firewall rules
|
||||
@@ -83,7 +83,7 @@ func (r *serverFirewallRulesResource) Create(ctx context.Context, req resource.C
|
||||
}
|
||||
|
||||
// Create API call logic
|
||||
firewallRules := []binarylane.AdvancedFirewallRule{}
|
||||
firewallRules := []binarylane.AdvancedFirewallRuleRequest{}
|
||||
diags := data.FirewallRules.ElementsAs(ctx, &firewallRules, true)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
@@ -174,7 +174,7 @@ func (r *serverFirewallRulesResource) Update(ctx context.Context, req resource.U
|
||||
}
|
||||
|
||||
// Update API call logic
|
||||
firewallRules := []binarylane.AdvancedFirewallRule{}
|
||||
firewallRules := []binarylane.AdvancedFirewallRuleRequest{}
|
||||
diags := data.FirewallRules.ElementsAs(ctx, &firewallRules, true)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
@@ -228,7 +228,7 @@ func (r *serverFirewallRulesResource) Delete(ctx context.Context, req resource.D
|
||||
data.ServerId.ValueInt64(),
|
||||
binarylane.PostServersServerIdActionsChangeAdvancedFirewallRulesJSONRequestBody{
|
||||
Type: "change_advanced_firewall_rules",
|
||||
FirewallRules: []binarylane.AdvancedFirewallRule{},
|
||||
FirewallRules: []binarylane.AdvancedFirewallRuleRequest{},
|
||||
})
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError(
|
||||
@@ -251,7 +251,7 @@ func GetFirewallRulesState(ctx context.Context, firewallRules *[]binarylane.Adva
|
||||
firewallRulesValue := resources.FirewallRulesValue{}
|
||||
var firewallRulesValues []resources.FirewallRulesValue
|
||||
|
||||
if *firewallRules == nil || len(*firewallRules) == 0 {
|
||||
if len(*firewallRules) == 0 {
|
||||
firewallRulesValues = []resources.FirewallRulesValue{}
|
||||
} else {
|
||||
for _, rule := range *firewallRules {
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package provider
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
|
||||
@@ -11,9 +9,7 @@ import (
|
||||
|
||||
func TestServerFirewallRulesResource(t *testing.T) {
|
||||
// Must assign a password to the server or Binary Lane will send emails
|
||||
pw_bytes := make([]byte, 12)
|
||||
rand.Read(pw_bytes)
|
||||
password := base64.URLEncoding.EncodeToString(pw_bytes)
|
||||
password := GenerateTestPassword(t)
|
||||
|
||||
resource.ParallelTest(t, resource.TestCase{
|
||||
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
|
||||
|
||||
@@ -2,6 +2,7 @@ package provider
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"slices"
|
||||
@@ -53,11 +54,10 @@ type serverResource struct {
|
||||
type serverResourceModel struct {
|
||||
serverDataModel
|
||||
|
||||
PublicIpv4Count types.Int32 `tfsdk:"public_ipv4_count"`
|
||||
SourceAndDestinationCheck types.Bool `tfsdk:"source_and_destination_check"`
|
||||
Password types.String `tfsdk:"password"`
|
||||
PasswordChangeSupported types.Bool `tfsdk:"password_change_supported"`
|
||||
Timeouts timeouts.Value `tfsdk:"timeouts"`
|
||||
PublicIpv4Count types.Int32 `tfsdk:"public_ipv4_count"`
|
||||
Password types.String `tfsdk:"password"`
|
||||
PasswordChangeSupported types.Bool `tfsdk:"password_change_supported"`
|
||||
Timeouts timeouts.Value `tfsdk:"timeouts"`
|
||||
}
|
||||
|
||||
func (d *serverResource) Configure(_ context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) {
|
||||
@@ -82,12 +82,12 @@ func (r *serverResource) Metadata(ctx context.Context, req resource.MetadataRequ
|
||||
resp.TypeName = req.ProviderTypeName + "_server"
|
||||
}
|
||||
|
||||
func (r *serverResource) Schema(ctx context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
|
||||
resp.Schema = resources.ServerResourceSchema(ctx)
|
||||
func serverSchema(ctx context.Context) schema.Schema {
|
||||
s := resources.ServerResourceSchema(ctx)
|
||||
|
||||
// Overrides
|
||||
id := resp.Schema.Attributes["id"]
|
||||
resp.Schema.Attributes["id"] = &schema.Int64Attribute{
|
||||
id := s.Attributes["id"]
|
||||
s.Attributes["id"] = schema.Int64Attribute{
|
||||
Description: id.GetDescription(),
|
||||
MarkdownDescription: id.GetMarkdownDescription(),
|
||||
// read only
|
||||
@@ -100,8 +100,8 @@ func (r *serverResource) Schema(ctx context.Context, _ resource.SchemaRequest, r
|
||||
}
|
||||
|
||||
imageDescription := "The slug of the selected operating system, such as `debian-12`. You can fetch a full list of images from the BinaryLane API."
|
||||
image := resp.Schema.Attributes["image"]
|
||||
resp.Schema.Attributes["image"] = &schema.StringAttribute{
|
||||
image := s.Attributes["image"]
|
||||
s.Attributes["image"] = schema.StringAttribute{
|
||||
Description: imageDescription,
|
||||
MarkdownDescription: imageDescription,
|
||||
Required: image.IsRequired(),
|
||||
@@ -113,7 +113,7 @@ func (r *serverResource) Schema(ctx context.Context, _ resource.SchemaRequest, r
|
||||
}
|
||||
|
||||
backupsDescription := "If `true` this will enable two daily backups for the server. By default, backups are disabled."
|
||||
resp.Schema.Attributes["backups"] = &schema.BoolAttribute{
|
||||
s.Attributes["backups"] = schema.BoolAttribute{
|
||||
Description: backupsDescription,
|
||||
MarkdownDescription: backupsDescription,
|
||||
Optional: true,
|
||||
@@ -121,24 +121,24 @@ func (r *serverResource) Schema(ctx context.Context, _ resource.SchemaRequest, r
|
||||
Default: booldefault.StaticBool(false), // Add default to backups
|
||||
}
|
||||
|
||||
user_data := resp.Schema.Attributes["user_data"]
|
||||
resp.Schema.Attributes["user_data"] = &schema.StringAttribute{
|
||||
user_data := s.Attributes["user_data"]
|
||||
s.Attributes["user_data"] = schema.StringAttribute{
|
||||
Description: user_data.GetDescription(),
|
||||
MarkdownDescription: user_data.GetMarkdownDescription(),
|
||||
Optional: true, // Optional as not all servers have an initialization script
|
||||
Computed: false, // User defined
|
||||
}
|
||||
|
||||
vpcId := resp.Schema.Attributes["vpc_id"]
|
||||
resp.Schema.Attributes["vpc_id"] = &schema.Int64Attribute{
|
||||
vpcId := s.Attributes["vpc_id"]
|
||||
s.Attributes["vpc_id"] = schema.Int64Attribute{
|
||||
Description: vpcId.GetDescription(),
|
||||
MarkdownDescription: vpcId.GetMarkdownDescription(),
|
||||
Optional: vpcId.IsOptional(),
|
||||
Computed: false, // vpc_id is not computed, defined at creation
|
||||
}
|
||||
|
||||
portBlocking := resp.Schema.Attributes["port_blocking"]
|
||||
resp.Schema.Attributes["port_blocking"] = &schema.BoolAttribute{
|
||||
portBlocking := s.Attributes["port_blocking"]
|
||||
s.Attributes["port_blocking"] = schema.BoolAttribute{
|
||||
Description: portBlocking.GetDescription(),
|
||||
MarkdownDescription: portBlocking.GetMarkdownDescription(),
|
||||
Optional: portBlocking.IsOptional(),
|
||||
@@ -146,8 +146,8 @@ func (r *serverResource) Schema(ctx context.Context, _ resource.SchemaRequest, r
|
||||
Default: booldefault.StaticBool(true), // Add default to port_blocking
|
||||
}
|
||||
|
||||
region := resp.Schema.Attributes["region"].(schema.StringAttribute)
|
||||
resp.Schema.Attributes["region"] = &schema.StringAttribute{
|
||||
region := s.Attributes["region"].(schema.StringAttribute)
|
||||
s.Attributes["region"] = schema.StringAttribute{
|
||||
Description: region.GetDescription(),
|
||||
MarkdownDescription: region.GetMarkdownDescription(),
|
||||
Optional: region.IsOptional(),
|
||||
@@ -159,8 +159,8 @@ func (r *serverResource) Schema(ctx context.Context, _ resource.SchemaRequest, r
|
||||
},
|
||||
}
|
||||
|
||||
sshKeys := resp.Schema.Attributes["ssh_keys"]
|
||||
resp.Schema.Attributes["ssh_keys"] = &schema.ListAttribute{
|
||||
sshKeys := s.Attributes["ssh_keys"]
|
||||
s.Attributes["ssh_keys"] = schema.ListAttribute{
|
||||
ElementType: types.Int64Type,
|
||||
Description: sshKeys.GetMarkdownDescription(),
|
||||
MarkdownDescription: sshKeys.GetDescription(),
|
||||
@@ -173,8 +173,8 @@ func (r *serverResource) Schema(ctx context.Context, _ resource.SchemaRequest, r
|
||||
|
||||
userDataDescription := "A script or cloud-config YAML file to configure the server. Can only be specified if the OS image supports UserData (i.e. not Windows)." +
|
||||
" See more: https://cloudinit.readthedocs.io/en/latest/explanation/format.html#user-data-script"
|
||||
userData := resp.Schema.Attributes["user_data"]
|
||||
resp.Schema.Attributes["user_data"] = &schema.StringAttribute{
|
||||
userData := s.Attributes["user_data"]
|
||||
s.Attributes["user_data"] = schema.StringAttribute{
|
||||
Description: userDataDescription,
|
||||
MarkdownDescription: userDataDescription,
|
||||
Required: userData.IsRequired(),
|
||||
@@ -190,7 +190,7 @@ func (r *serverResource) Schema(ctx context.Context, _ resource.SchemaRequest, r
|
||||
"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."
|
||||
resp.Schema.Attributes["password"] = &schema.StringAttribute{
|
||||
s.Attributes["password"] = schema.StringAttribute{
|
||||
Description: pwDescription,
|
||||
MarkdownDescription: pwDescription,
|
||||
Optional: true, // Password optional, if not set will be emailed to user
|
||||
@@ -199,7 +199,7 @@ func (r *serverResource) Schema(ctx context.Context, _ resource.SchemaRequest, r
|
||||
}
|
||||
|
||||
publicIpv4CountDescription := "The number of public IPv4 addresses to assign to the server."
|
||||
resp.Schema.Attributes["public_ipv4_count"] = &schema.Int32Attribute{
|
||||
s.Attributes["public_ipv4_count"] = schema.Int32Attribute{
|
||||
Description: publicIpv4CountDescription,
|
||||
MarkdownDescription: publicIpv4CountDescription,
|
||||
Required: true,
|
||||
@@ -212,7 +212,7 @@ func (r *serverResource) Schema(ctx context.Context, _ resource.SchemaRequest, r
|
||||
}
|
||||
|
||||
publicIpv4AddressesDescription := "The public IPv4 addresses assigned to the server."
|
||||
resp.Schema.Attributes["public_ipv4_addresses"] = &schema.ListAttribute{
|
||||
s.Attributes["public_ipv4_addresses"] = schema.ListAttribute{
|
||||
Description: publicIpv4AddressesDescription,
|
||||
MarkdownDescription: publicIpv4AddressesDescription,
|
||||
ElementType: types.StringType,
|
||||
@@ -229,7 +229,7 @@ func (r *serverResource) Schema(ctx context.Context, _ resource.SchemaRequest, r
|
||||
"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."
|
||||
resp.Schema.Attributes["source_and_destination_check"] = &schema.BoolAttribute{
|
||||
s.Attributes["source_and_destination_check"] = schema.BoolAttribute{
|
||||
Description: sourceDestCheckDescription,
|
||||
MarkdownDescription: sourceDestCheckDescription,
|
||||
Optional: true,
|
||||
@@ -243,7 +243,7 @@ func (r *serverResource) Schema(ctx context.Context, _ resource.SchemaRequest, r
|
||||
}
|
||||
|
||||
privateIpv4AddressesDescription := "The private IPv4 addresses assigned to the server."
|
||||
resp.Schema.Attributes["private_ipv4_addresses"] = &schema.ListAttribute{
|
||||
s.Attributes["private_ipv4_addresses"] = schema.ListAttribute{
|
||||
Description: privateIpv4AddressesDescription,
|
||||
MarkdownDescription: privateIpv4AddressesDescription,
|
||||
ElementType: types.StringType,
|
||||
@@ -256,7 +256,41 @@ func (r *serverResource) Schema(ctx context.Context, _ resource.SchemaRequest, r
|
||||
},
|
||||
}
|
||||
|
||||
resp.Schema.Attributes["permalink"] = &schema.StringAttribute{
|
||||
ipv6Description := "If `true` this will add a public and private IPv6 address to the server. By default, IPv6 is disabled."
|
||||
s.Attributes["ipv6"] = schema.BoolAttribute{
|
||||
Description: ipv6Description,
|
||||
MarkdownDescription: ipv6Description,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
Default: booldefault.StaticBool(false), // Add default to ipv6
|
||||
}
|
||||
|
||||
publicIpv6AddressesDescription := "The public IPv6 addresses assigned to the server."
|
||||
s.Attributes["public_ipv6_addresses"] = schema.ListAttribute{
|
||||
Description: publicIpv6AddressesDescription,
|
||||
MarkdownDescription: publicIpv6AddressesDescription,
|
||||
ElementType: types.StringType,
|
||||
// read only
|
||||
Optional: false,
|
||||
Required: false,
|
||||
Computed: true,
|
||||
}
|
||||
|
||||
privateIpv6AddressesDescription := "The private IPv6 addresses assigned to the server."
|
||||
s.Attributes["private_ipv6_addresses"] = schema.ListAttribute{
|
||||
Description: privateIpv6AddressesDescription,
|
||||
MarkdownDescription: privateIpv6AddressesDescription,
|
||||
ElementType: types.StringType,
|
||||
// read only
|
||||
Optional: false,
|
||||
Required: false,
|
||||
Computed: true,
|
||||
PlanModifiers: []planmodifier.List{
|
||||
listplanmodifier.UseStateForUnknown(),
|
||||
},
|
||||
}
|
||||
|
||||
s.Attributes["permalink"] = schema.StringAttribute{
|
||||
Description: "A randomly generated two-word identifier assigned to servers in regions that support this feature",
|
||||
MarkdownDescription: "A randomly generated two-word identifier assigned to servers in regions that support this feature",
|
||||
// read only
|
||||
@@ -271,7 +305,7 @@ func (r *serverResource) Schema(ctx context.Context, _ resource.SchemaRequest, r
|
||||
pwChangeDescription := "If this is true then the `password` attribute can be changed with Terraform. " +
|
||||
"If this is false then the `password` attribute can only be replaced with a null/empty value, which will clear " +
|
||||
"the root/administrator password allowing the password to be changed via the web console."
|
||||
resp.Schema.Attributes["password_change_supported"] = &schema.BoolAttribute{
|
||||
s.Attributes["password_change_supported"] = schema.BoolAttribute{
|
||||
Description: pwChangeDescription,
|
||||
MarkdownDescription: pwChangeDescription,
|
||||
// read only
|
||||
@@ -293,7 +327,7 @@ func (r *serverResource) Schema(ctx context.Context, _ resource.SchemaRequest, r
|
||||
- \> 16384 MB must be a multiple of 2048
|
||||
- \> 24576 MB must be a multiple of 4096`
|
||||
|
||||
resp.Schema.Attributes["memory"] = &schema.Int32Attribute{
|
||||
s.Attributes["memory"] = schema.Int32Attribute{
|
||||
Description: memoryDescription + memoryValidValues,
|
||||
MarkdownDescription: memoryDescription + memoryValidValuesMarkdown,
|
||||
Optional: true,
|
||||
@@ -316,7 +350,7 @@ func (r *serverResource) Schema(ctx context.Context, _ resource.SchemaRequest, r
|
||||
- \> 60 GB must be a multiple of 10
|
||||
- \> 200 GB must be a multiple of 100`
|
||||
|
||||
resp.Schema.Attributes["disk"] = &schema.Int32Attribute{
|
||||
s.Attributes["disk"] = schema.Int32Attribute{
|
||||
Description: diskDescription + diskValidValues,
|
||||
MarkdownDescription: diskDescription + diskValidValuesMarkdown,
|
||||
Optional: true,
|
||||
@@ -330,15 +364,21 @@ func (r *serverResource) Schema(ctx context.Context, _ resource.SchemaRequest, r
|
||||
},
|
||||
}
|
||||
|
||||
resp.Schema.Attributes["timeouts"] =
|
||||
s.Attributes["timeouts"] =
|
||||
timeouts.Attributes(ctx, timeouts.Opts{
|
||||
Create: true,
|
||||
Update: true,
|
||||
})
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
func (r *serverResource) Schema(ctx context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
|
||||
resp.Schema = serverSchema(ctx)
|
||||
}
|
||||
|
||||
func (r *serverResource) ModifyPlan(ctx context.Context, req resource.ModifyPlanRequest, resp *resource.ModifyPlanResponse) {
|
||||
var plan, state serverResourceModel
|
||||
var config, plan, state serverResourceModel
|
||||
|
||||
if req.Plan.Raw.IsNull() {
|
||||
// Destruction plan, no modification needed
|
||||
@@ -346,6 +386,7 @@ func (r *serverResource) ModifyPlan(ctx context.Context, req resource.ModifyPlan
|
||||
}
|
||||
|
||||
// Read Terraform plan data into the model
|
||||
resp.Diagnostics.Append(req.Config.Get(ctx, &config)...)
|
||||
resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
@@ -407,6 +448,16 @@ func (r *serverResource) ModifyPlan(ctx context.Context, req resource.ModifyPlan
|
||||
)
|
||||
}
|
||||
|
||||
if !plan.Ipv6.Equal(state.Ipv6) {
|
||||
if plan.Ipv6.ValueBool() {
|
||||
plan.PublicIpv6Addresses = types.ListUnknown(state.PublicIpv6Addresses.ElementType(ctx))
|
||||
plan.PrivateIpv6Addresses = types.ListUnknown(state.PrivateIpv6Addresses.ElementType(ctx))
|
||||
} else {
|
||||
plan.PublicIpv6Addresses = types.ListNull(state.PublicIpv6Addresses.ElementType(ctx))
|
||||
plan.PrivateIpv6Addresses = types.ListNull(state.PrivateIpv6Addresses.ElementType(ctx))
|
||||
}
|
||||
}
|
||||
|
||||
// Use state for unknown disk/memory values, as long as server size is the same
|
||||
if (plan.Memory.IsNull() || plan.Memory.IsUnknown()) && plan.Size.Equal(state.Size) {
|
||||
plan.Memory = state.Memory
|
||||
@@ -415,16 +466,79 @@ func (r *serverResource) ModifyPlan(ctx context.Context, req resource.ModifyPlan
|
||||
plan.Disk = state.Disk
|
||||
}
|
||||
|
||||
if isAdvFeatChanged(&config.AdvancedFeatures, &state.AdvancedFeatures) {
|
||||
advFeatResp, err := r.bc.client.GetServersServerIdAvailableAdvancedFeaturesWithResponse(ctx, state.Id.ValueInt64())
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError(
|
||||
fmt.Sprintf("Error fetching available advanced features for server: id=%s", state.Id.String()),
|
||||
err.Error(),
|
||||
)
|
||||
} else if advFeatResp.StatusCode() != http.StatusOK {
|
||||
resp.Diagnostics.AddError(
|
||||
"Unexpected HTTP status code fetching available advanced features for server",
|
||||
fmt.Sprintf("Received %s fetching available advanced features for server: id=%s. Details: %s", advFeatResp.Status(), state.Id.String(), advFeatResp.Body))
|
||||
} else {
|
||||
debugAdvFeatResp, _ := json.Marshal(advFeatResp.JSON200)
|
||||
tflog.Debug(ctx, fmt.Sprintf("Recieved response for available advanced features: %s", debugAdvFeatResp))
|
||||
|
||||
availableAdvFeat := *advFeatResp.JSON200.AvailableAdvancedServerFeatures.AdvancedFeatures
|
||||
|
||||
if plan.AdvancedFeatures.EmulatedHyperv.ValueBool() && !slices.Contains(availableAdvFeat, "emulated-hyperv") {
|
||||
resp.Diagnostics.AddAttributeError(
|
||||
path.Root("advanced_features").AtName("emulated_hyperv"),
|
||||
"Emulated Hyper-V not available",
|
||||
fmt.Sprintf("Emulated Hyper-V is not available for server %s", state.Name.String()),
|
||||
)
|
||||
} else if plan.AdvancedFeatures.EmulatedDevices.ValueBool() && !slices.Contains(availableAdvFeat, "emulated-devices") {
|
||||
resp.Diagnostics.AddAttributeError(
|
||||
path.Root("advanced_features").AtName("emulated_devices"),
|
||||
"Emulated Devices not available",
|
||||
fmt.Sprintf("Emulated Devices is not available for server %s", state.Name.String()),
|
||||
)
|
||||
} else if plan.AdvancedFeatures.EmulatedTpm.ValueBool() && !slices.Contains(availableAdvFeat, "emulated-tpm") {
|
||||
resp.Diagnostics.AddAttributeError(
|
||||
path.Root("advanced_features").AtName("emulated_tpm"),
|
||||
"Emulated TPM not available",
|
||||
fmt.Sprintf("Emulated TPM is not available for server %s", state.Name.String()),
|
||||
)
|
||||
} else if plan.AdvancedFeatures.NestedVirt.ValueBool() && !slices.Contains(availableAdvFeat, "nested-virt") {
|
||||
resp.Diagnostics.AddAttributeError(
|
||||
path.Root("advanced_features").AtName("nested_virt"),
|
||||
"Nested Virtualization not available",
|
||||
fmt.Sprintf("Nested Virtualization is not available for server %s", state.Name.String()),
|
||||
)
|
||||
} else if plan.AdvancedFeatures.DriverDisk.ValueBool() && !slices.Contains(availableAdvFeat, "driver-disk") {
|
||||
resp.Diagnostics.AddAttributeError(
|
||||
path.Root("advanced_features").AtName("driver_disk"),
|
||||
"Driver Disk not available",
|
||||
fmt.Sprintf("Driver Disk is not available for server %s", state.Name.String()),
|
||||
)
|
||||
} else if plan.AdvancedFeatures.UnsetUuid.ValueBool() && !slices.Contains(availableAdvFeat, "unset-uuid") {
|
||||
resp.Diagnostics.AddAttributeError(
|
||||
path.Root("advanced_features").AtName("unset_uuid"),
|
||||
"Unset UUID not available",
|
||||
fmt.Sprintf("Unset UUID is not available for server %s", state.Name.String()),
|
||||
)
|
||||
} else if plan.AdvancedFeatures.LocalRtc.ValueBool() && !slices.Contains(availableAdvFeat, "local-rtc") {
|
||||
resp.Diagnostics.AddAttributeError(
|
||||
path.Root("advanced_features").AtName("local_rtc"),
|
||||
"Local RTC not available",
|
||||
fmt.Sprintf("Local RTC is not available for server %s", state.Name.String()),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Save data into Terraform state
|
||||
resp.Diagnostics.Append(resp.Plan.Set(ctx, &plan)...)
|
||||
}
|
||||
|
||||
func (r *serverResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
|
||||
var data serverResourceModel
|
||||
var config, data serverResourceModel
|
||||
|
||||
// Read Terraform plan data into the model
|
||||
diags := req.Plan.Get(ctx, &data)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
resp.Diagnostics.Append(req.Config.Get(ctx, &config)...)
|
||||
resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
@@ -457,6 +571,7 @@ func (r *serverResource) Create(ctx context.Context, req resource.CreateRequest,
|
||||
Ipv4Addresses: data.PublicIpv4Count.ValueInt32Pointer(),
|
||||
},
|
||||
Backups: data.Backups.ValueBoolPointer(),
|
||||
Ipv6: data.Ipv6.ValueBoolPointer(),
|
||||
}
|
||||
|
||||
if !data.Memory.IsNull() && !data.Memory.IsUnknown() {
|
||||
@@ -514,6 +629,7 @@ func (r *serverResource) Create(ctx context.Context, req resource.CreateRequest,
|
||||
data.Region = types.StringValue(*serverResp.JSON200.Server.Region.Slug)
|
||||
data.Size = types.StringValue(*serverResp.JSON200.Server.Size.Slug)
|
||||
data.Backups = types.BoolValue(serverResp.JSON200.Server.NextBackupWindow != nil)
|
||||
data.Ipv6 = types.BoolValue(len(serverResp.JSON200.Server.Networks.V6) > 0)
|
||||
data.PortBlocking = types.BoolValue(serverResp.JSON200.Server.Networks.PortBlocking)
|
||||
data.VpcId = types.Int64PointerValue(serverResp.JSON200.Server.VpcId)
|
||||
data.Permalink = types.StringValue(*serverResp.JSON200.Server.Permalink)
|
||||
@@ -524,6 +640,26 @@ func (r *serverResource) Create(ctx context.Context, req resource.CreateRequest,
|
||||
serverRespSourceDestCheck := types.BoolPointerValue(serverResp.JSON200.Server.Networks.SourceAndDestinationCheck)
|
||||
data.SourceAndDestinationCheck = serverRespSourceDestCheck
|
||||
|
||||
advFeat := *serverResp.JSON200.Server.AdvancedFeatures.EnabledAdvancedFeatures
|
||||
data.AdvancedFeatures, diags = resources.NewAdvancedFeaturesValue(
|
||||
resources.AdvancedFeaturesValue{}.AttributeTypes(ctx),
|
||||
map[string]attr.Value{
|
||||
"emulated_hyperv": types.BoolValue(slices.Contains(advFeat, "emulated-hyperv")),
|
||||
"emulated_devices": types.BoolValue(slices.Contains(advFeat, "emulated-devices")),
|
||||
"nested_virt": types.BoolValue(slices.Contains(advFeat, "nested-virt")),
|
||||
"driver_disk": types.BoolValue(slices.Contains(advFeat, "driver-disk")),
|
||||
"unset_uuid": types.BoolValue(slices.Contains(advFeat, "unset-uuid")),
|
||||
"local_rtc": types.BoolValue(slices.Contains(advFeat, "local-rtc")),
|
||||
"emulated_tpm": types.BoolValue(slices.Contains(advFeat, "emulated-tpm")),
|
||||
"cloud_init": types.BoolValue(slices.Contains(advFeat, "cloud-init")),
|
||||
"qemu_guest_agent": types.BoolValue(slices.Contains(advFeat, "qemu-guest-agent")),
|
||||
"uefi_boot": types.BoolValue(slices.Contains(advFeat, "uefi-boot")),
|
||||
})
|
||||
if diags.HasError() {
|
||||
resp.Diagnostics.Append(diags...)
|
||||
data.AdvancedFeatures = resources.NewAdvancedFeaturesValueUnknown()
|
||||
}
|
||||
|
||||
publicIpv4Addresses := []string{}
|
||||
privateIpv4Addresses := []string{}
|
||||
for _, v4address := range serverResp.JSON200.Server.Networks.V4 {
|
||||
@@ -540,6 +676,21 @@ func (r *serverResource) Create(ctx context.Context, req resource.CreateRequest,
|
||||
|
||||
// Save data into Terraform state
|
||||
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
// Update advanced features
|
||||
err = r.updateAdvancedFeatures(ctx, data.Id.ValueInt64(), &config.AdvancedFeatures, &data.AdvancedFeatures)
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError("Error updating advanced features", err.Error())
|
||||
}
|
||||
|
||||
// Save data into Terraform state
|
||||
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
// Update source_and_destination_check if needed
|
||||
if plannedSourceDestCheck.Equal(types.BoolPointerValue(Pointer(false))) {
|
||||
@@ -551,6 +702,11 @@ func (r *serverResource) Create(ctx context.Context, req resource.CreateRequest,
|
||||
data.SourceAndDestinationCheck = plannedSourceDestCheck
|
||||
}
|
||||
|
||||
// One extra read to check the final state of enabled_advanced_features, needed because
|
||||
// some flags (like "cloud-init") are not set until the server is fully created. See #13
|
||||
diag := r.fetchServerResourceState(ctx, &data)
|
||||
resp.Diagnostics.Append(diag...)
|
||||
|
||||
// Save data into Terraform state
|
||||
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
|
||||
}
|
||||
@@ -567,31 +723,7 @@ func (r *serverResource) Read(ctx context.Context, req resource.ReadRequest, res
|
||||
|
||||
// Read API call logic
|
||||
tflog.Debug(ctx, fmt.Sprintf("Reading server: id=%s, name=%s", data.Id.String(), data.Name.ValueString()))
|
||||
|
||||
serverResp, err := r.bc.client.GetServersServerIdWithResponse(ctx, data.Id.ValueInt64())
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError(
|
||||
fmt.Sprintf("Error reading server: id=%s, name=%s", data.Id.String(), data.Name.ValueString()),
|
||||
err.Error(),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
if serverResp.StatusCode() == http.StatusNotFound {
|
||||
tflog.Warn(ctx, fmt.Sprintf("Server not found, removing from state: id=%s, name=%s", data.Id.String(), data.Name.ValueString()))
|
||||
resp.State.RemoveResource(ctx)
|
||||
return
|
||||
}
|
||||
|
||||
if serverResp.StatusCode() != http.StatusOK {
|
||||
resp.Diagnostics.AddError(
|
||||
fmt.Sprintf("Unexpected HTTP status code %s reading server: name=%s, id=%s", serverResp.Status(), data.Name.ValueString(), data.Id.String()),
|
||||
string(serverResp.Body),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
diag := setServerResourceState(ctx, &data, serverResp.JSON200)
|
||||
diag := r.fetchServerResourceState(ctx, &data)
|
||||
resp.Diagnostics.Append(diag...)
|
||||
|
||||
// Get user data script
|
||||
@@ -617,9 +749,11 @@ func (r *serverResource) Read(ctx context.Context, req resource.ReadRequest, res
|
||||
}
|
||||
|
||||
func (r *serverResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
|
||||
var plan, state serverResourceModel
|
||||
var diag diag.Diagnostics
|
||||
var config, plan, state serverResourceModel
|
||||
|
||||
// Read Terraform plan data into the model
|
||||
resp.Diagnostics.Append(req.Config.Get(ctx, &config)...)
|
||||
resp.Diagnostics.Append(req.State.Get(ctx, &state)...)
|
||||
resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
@@ -639,23 +773,7 @@ func (r *serverResource) Update(ctx context.Context, req resource.UpdateRequest,
|
||||
return
|
||||
}
|
||||
|
||||
serverResp, err := r.bc.client.GetServersServerIdWithResponse(ctx, state.Id.ValueInt64())
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError(
|
||||
fmt.Sprintf("Error reading server: id=%s, name=%s", state.Id.String(), state.Name.ValueString()),
|
||||
err.Error(),
|
||||
)
|
||||
return
|
||||
}
|
||||
if serverResp.StatusCode() != http.StatusOK {
|
||||
resp.Diagnostics.AddError(
|
||||
fmt.Sprintf("Unexpected HTTP status code %s reading server: name=%s, id=%s", serverResp.Status(), state.Name.ValueString(), state.Id.String()),
|
||||
string(serverResp.Body),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
diag := setServerResourceState(ctx, &state, serverResp.JSON200)
|
||||
diag := r.fetchServerResourceState(ctx, &state)
|
||||
resp.Diagnostics.Append(diag...)
|
||||
|
||||
// Save updated data into Terraform state
|
||||
@@ -678,21 +796,14 @@ func (r *serverResource) Update(ctx context.Context, req resource.UpdateRequest,
|
||||
err.Error(),
|
||||
)
|
||||
return
|
||||
}
|
||||
if renameResp.StatusCode() != http.StatusOK {
|
||||
} else if renameResp.StatusCode() != http.StatusOK && renameResp.StatusCode() != http.StatusAccepted {
|
||||
resp.Diagnostics.AddError(
|
||||
"Unexpected HTTP status code renaming server",
|
||||
fmt.Sprintf("Received %s renaming server: server_id=%s. Details: %s", renameResp.Status(), state.Id.String(), renameResp.Body))
|
||||
return
|
||||
}
|
||||
if *renameResp.JSON200.Action.Status == "errored" {
|
||||
resp.Diagnostics.AddError(
|
||||
"Unexpected response with \"errored\" status when renaming server",
|
||||
fmt.Sprintf("Received %s renaming server: server_id=%s. Details: %s", renameResp.Status(), state.Id.String(), renameResp.Body))
|
||||
return
|
||||
}
|
||||
|
||||
// TODO - Currently, the API does not support polling for the rename to complete, because the action ID returns a 404 response (see #13)
|
||||
// TODO - Currently, the API does not support polling for the rename to complete, because there is no action ID in 202 accepted response (see #13)
|
||||
|
||||
state.Name = types.StringValue(plan.Name.ValueString())
|
||||
}
|
||||
@@ -825,6 +936,43 @@ func (r *serverResource) Update(ctx context.Context, req resource.UpdateRequest,
|
||||
}
|
||||
}
|
||||
|
||||
// Change ipv6
|
||||
if !plan.Ipv6.Equal(state.Ipv6) {
|
||||
ipv6Resp, err := r.bc.client.PostServersServerIdActionsChangeIpv6WithResponse(
|
||||
ctx,
|
||||
state.Id.ValueInt64(),
|
||||
binarylane.PostServersServerIdActionsChangeIpv6JSONRequestBody{
|
||||
Type: "change_ipv6",
|
||||
Enabled: plan.Ipv6.ValueBool(),
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError("Error changing IPv6", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
err = r.waitForServerAction(ctx, state.Id.ValueInt64(), *ipv6Resp.JSON200.Action.Id)
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError("Error waiting for changing IPv6", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
state.Ipv6 = plan.Ipv6
|
||||
state.PublicIpv6Addresses = plan.PublicIpv6Addresses
|
||||
state.PrivateIpv6Addresses = plan.PrivateIpv6Addresses
|
||||
|
||||
if state.PublicIpv6Addresses.IsUnknown() || state.PrivateIpv6Addresses.IsUnknown() || listContainsUnknown(ctx, state.PublicIpv6Addresses) || listContainsUnknown(ctx, state.PrivateIpv6Addresses) {
|
||||
refreshNeeded = true
|
||||
}
|
||||
|
||||
// Save updated data into Terraform state
|
||||
resp.Diagnostics.Append(resp.State.Set(ctx, &state)...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Rebuild operation
|
||||
if !plan.SshKeys.Equal(state.SshKeys) || !plan.UserData.IsNull() && !plan.UserData.Equal(state.UserData) {
|
||||
var rebuildReq *binarylane.PostServersServerIdActionsRebuildJSONRequestBody
|
||||
@@ -904,6 +1052,17 @@ func (r *serverResource) Update(ctx context.Context, req resource.UpdateRequest,
|
||||
}
|
||||
}
|
||||
|
||||
err := r.updateAdvancedFeatures(ctx, state.Id.ValueInt64(), &config.AdvancedFeatures, &state.AdvancedFeatures)
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError("Error updating advanced features", err.Error())
|
||||
return
|
||||
}
|
||||
resp.Diagnostics.Append(diag...)
|
||||
resp.Diagnostics.Append(resp.State.Set(ctx, &state)...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
// Check source_and_destination_check
|
||||
if !plan.SourceAndDestinationCheck.Equal(state.SourceAndDestinationCheck) {
|
||||
if !plan.SourceAndDestinationCheck.IsNull() {
|
||||
@@ -1084,7 +1243,7 @@ func (r *serverResource) waitForServerAction(ctx context.Context, serverId int64
|
||||
return fmt.Errorf("unexpected error waiting for server action: server_id=%d, action_id=%d, error: %w", serverId, actionId, err)
|
||||
}
|
||||
if readyResp.StatusCode() == http.StatusOK && *readyResp.JSON200.Action.Status == binarylane.Errored {
|
||||
return fmt.Errorf("server action failed to with error: server_id=%d, action_id=%d, error: %s", serverId, actionId, *readyResp.JSON200.Action.ResultData)
|
||||
return fmt.Errorf("server action failed to with error: server_id=%d, action_id=%d, error: %s", serverId, actionId, readyResp.Body)
|
||||
}
|
||||
if readyResp.StatusCode() == http.StatusOK && readyResp.JSON200.Action.CompletedAt != nil {
|
||||
return nil
|
||||
@@ -1147,31 +1306,69 @@ func (r *serverResource) updateSourceDestCheck(
|
||||
return nil
|
||||
}
|
||||
|
||||
func setServerResourceState(ctx context.Context, data *serverResourceModel, serverResp *binarylane.ServerResponse) diag.Diagnostics {
|
||||
func (r *serverResource) fetchServerResourceState(ctx context.Context, state *serverResourceModel) diag.Diagnostics {
|
||||
var diags diag.Diagnostics
|
||||
|
||||
data.Id = types.Int64Value(*serverResp.Server.Id)
|
||||
data.Name = types.StringValue(*serverResp.Server.Name)
|
||||
data.Image = types.StringValue(*serverResp.Server.Image.Slug)
|
||||
data.Region = types.StringValue(*serverResp.Server.Region.Slug)
|
||||
data.Size = types.StringValue(*serverResp.Server.Size.Slug)
|
||||
data.Backups = types.BoolValue(serverResp.Server.NextBackupWindow != nil)
|
||||
data.PortBlocking = types.BoolValue(serverResp.Server.Networks.PortBlocking)
|
||||
data.VpcId = types.Int64PointerValue(serverResp.Server.VpcId)
|
||||
data.Permalink = types.StringValue(*serverResp.Server.Permalink)
|
||||
data.PasswordChangeSupported = types.BoolValue(*serverResp.Server.PasswordChangeSupported)
|
||||
data.SourceAndDestinationCheck = types.BoolPointerValue(serverResp.Server.Networks.SourceAndDestinationCheck)
|
||||
data.Memory = types.Int32Value(*serverResp.Server.Memory)
|
||||
data.Disk = types.Int32Value(*serverResp.Server.Disk)
|
||||
data.Backups = types.BoolValue(serverResp.Server.NextBackupWindow != nil)
|
||||
serverResp, err := r.bc.client.GetServersServerIdWithResponse(ctx, state.Id.ValueInt64())
|
||||
if err != nil {
|
||||
return diag.Diagnostics{
|
||||
diag.NewErrorDiagnostic(
|
||||
fmt.Sprintf("Error reading server: id=%s, name=%s", state.Id.String(), state.Name.ValueString()),
|
||||
err.Error(),
|
||||
),
|
||||
}
|
||||
}
|
||||
if serverResp.StatusCode() != http.StatusOK {
|
||||
return diag.Diagnostics{
|
||||
diag.NewErrorDiagnostic(
|
||||
fmt.Sprintf("Unexpected HTTP status code %s reading server: name=%s, id=%s", serverResp.Status(), state.Name.ValueString(), state.Id.String()),
|
||||
string(serverResp.Body),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
state.Id = types.Int64Value(*serverResp.JSON200.Server.Id)
|
||||
state.Name = types.StringValue(*serverResp.JSON200.Server.Name)
|
||||
state.Image = types.StringValue(*serverResp.JSON200.Server.Image.Slug)
|
||||
state.Region = types.StringValue(*serverResp.JSON200.Server.Region.Slug)
|
||||
state.Size = types.StringValue(*serverResp.JSON200.Server.Size.Slug)
|
||||
state.Backups = types.BoolValue(serverResp.JSON200.Server.NextBackupWindow != nil)
|
||||
state.PortBlocking = types.BoolValue(serverResp.JSON200.Server.Networks.PortBlocking)
|
||||
state.VpcId = types.Int64PointerValue(serverResp.JSON200.Server.VpcId)
|
||||
state.Permalink = types.StringValue(*serverResp.JSON200.Server.Permalink)
|
||||
state.PasswordChangeSupported = types.BoolValue(*serverResp.JSON200.Server.PasswordChangeSupported)
|
||||
state.SourceAndDestinationCheck = types.BoolPointerValue(serverResp.JSON200.Server.Networks.SourceAndDestinationCheck)
|
||||
state.Memory = types.Int32Value(*serverResp.JSON200.Server.Memory)
|
||||
state.Disk = types.Int32Value(*serverResp.JSON200.Server.Disk)
|
||||
state.Backups = types.BoolValue(serverResp.JSON200.Server.NextBackupWindow != nil)
|
||||
state.Ipv6 = types.BoolValue(len(serverResp.JSON200.Server.Networks.V6) > 0)
|
||||
|
||||
advFeat := *serverResp.JSON200.Server.AdvancedFeatures.EnabledAdvancedFeatures
|
||||
state.AdvancedFeatures, diags = resources.NewAdvancedFeaturesValue(
|
||||
resources.AdvancedFeaturesValue{}.AttributeTypes(ctx),
|
||||
map[string]attr.Value{
|
||||
"emulated_hyperv": types.BoolValue(slices.Contains(advFeat, "emulated-hyperv")),
|
||||
"emulated_devices": types.BoolValue(slices.Contains(advFeat, "emulated-devices")),
|
||||
"nested_virt": types.BoolValue(slices.Contains(advFeat, "nested-virt")),
|
||||
"driver_disk": types.BoolValue(slices.Contains(advFeat, "driver-disk")),
|
||||
"unset_uuid": types.BoolValue(slices.Contains(advFeat, "unset-uuid")),
|
||||
"local_rtc": types.BoolValue(slices.Contains(advFeat, "local-rtc")),
|
||||
"emulated_tpm": types.BoolValue(slices.Contains(advFeat, "emulated-tpm")),
|
||||
"cloud_init": types.BoolValue(slices.Contains(advFeat, "cloud-init")),
|
||||
"qemu_guest_agent": types.BoolValue(slices.Contains(advFeat, "qemu-guest-agent")),
|
||||
"uefi_boot": types.BoolValue(slices.Contains(advFeat, "uefi-boot")),
|
||||
})
|
||||
if diags.HasError() {
|
||||
state.AdvancedFeatures = resources.NewAdvancedFeaturesValueUnknown()
|
||||
}
|
||||
|
||||
publicIpv4Addresses := []string{}
|
||||
privateIpv4Addresses := []string{}
|
||||
|
||||
for _, v4address := range serverResp.Server.Networks.V4 {
|
||||
for _, v4address := range serverResp.JSON200.Server.Networks.V4 {
|
||||
if v4address.Type == "public" {
|
||||
publicIpv4Addresses = append(publicIpv4Addresses, v4address.IpAddress)
|
||||
} else {
|
||||
} else if v4address.Type == "private" {
|
||||
privateIpv4Addresses = append(privateIpv4Addresses, v4address.IpAddress)
|
||||
}
|
||||
}
|
||||
@@ -1179,20 +1376,151 @@ func setServerResourceState(ctx context.Context, data *serverResourceModel, serv
|
||||
tfPublicIpv4Addresses, diag := types.ListValueFrom(ctx, types.StringType, publicIpv4Addresses)
|
||||
diags.Append(diag...)
|
||||
if diag.HasError() {
|
||||
data.PublicIpv4Addresses = types.ListUnknown(data.PublicIpv4Addresses.ElementType(ctx))
|
||||
data.PublicIpv4Count = types.Int32Unknown()
|
||||
state.PublicIpv4Addresses = types.ListUnknown(state.PublicIpv4Addresses.ElementType(ctx))
|
||||
state.PublicIpv4Count = types.Int32Unknown()
|
||||
} else {
|
||||
data.PublicIpv4Addresses = tfPublicIpv4Addresses
|
||||
data.PublicIpv4Count = types.Int32Value(int32(len(publicIpv4Addresses)))
|
||||
state.PublicIpv4Addresses = tfPublicIpv4Addresses
|
||||
state.PublicIpv4Count = types.Int32Value(int32(len(publicIpv4Addresses)))
|
||||
}
|
||||
|
||||
tfPrivateIpv4Addresses, diag := types.ListValueFrom(ctx, types.StringType, privateIpv4Addresses)
|
||||
diags.Append(diag...)
|
||||
if diag.HasError() {
|
||||
data.PrivateIPv4Addresses = types.ListUnknown(data.PrivateIPv4Addresses.ElementType(ctx))
|
||||
state.PrivateIPv4Addresses = types.ListUnknown(state.PrivateIPv4Addresses.ElementType(ctx))
|
||||
} else {
|
||||
data.PrivateIPv4Addresses = tfPrivateIpv4Addresses
|
||||
state.PrivateIPv4Addresses = tfPrivateIpv4Addresses
|
||||
}
|
||||
|
||||
publicIpv6Addresses := []string{}
|
||||
privateIpv6Addresses := []string{}
|
||||
|
||||
for _, v6address := range serverResp.JSON200.Server.Networks.V6 {
|
||||
if v6address.Type == "public" {
|
||||
publicIpv6Addresses = append(publicIpv6Addresses, v6address.IpAddress)
|
||||
} else {
|
||||
privateIpv6Addresses = append(privateIpv6Addresses, v6address.IpAddress)
|
||||
}
|
||||
}
|
||||
|
||||
tfPublicIpv6Addresses, diag := types.ListValueFrom(ctx, types.StringType, publicIpv6Addresses)
|
||||
diags.Append(diag...)
|
||||
if diag.HasError() || tfPublicIpv6Addresses.IsNull() {
|
||||
state.PublicIpv6Addresses = types.ListUnknown(state.PublicIpv6Addresses.ElementType(ctx))
|
||||
} else {
|
||||
state.PublicIpv6Addresses = tfPublicIpv6Addresses
|
||||
}
|
||||
|
||||
tfPrivateIpv6Addresses, diag := types.ListValueFrom(ctx, types.StringType, privateIpv6Addresses)
|
||||
diags.Append(diag...)
|
||||
if diag.HasError() || tfPrivateIpv6Addresses.IsNull() {
|
||||
state.PrivateIpv6Addresses = types.ListUnknown(state.PrivateIpv6Addresses.ElementType(ctx))
|
||||
} else {
|
||||
state.PrivateIpv6Addresses = tfPrivateIpv6Addresses
|
||||
}
|
||||
|
||||
return diags
|
||||
}
|
||||
|
||||
func isAdvFeatChanged(config *resources.AdvancedFeaturesValue, data *resources.AdvancedFeaturesValue) bool {
|
||||
// Check if any of the writable advanced features have been modified by the user
|
||||
return (!config.EmulatedHyperv.IsNull() && !config.EmulatedHyperv.Equal(data.EmulatedHyperv)) ||
|
||||
(!config.EmulatedDevices.IsNull() && !config.EmulatedDevices.Equal(data.EmulatedDevices)) ||
|
||||
(!config.EmulatedTpm.IsNull() && !config.EmulatedTpm.Equal(data.EmulatedTpm)) ||
|
||||
(!config.NestedVirt.IsNull() && !config.NestedVirt.Equal(data.NestedVirt)) ||
|
||||
(!config.DriverDisk.IsNull() && !config.DriverDisk.Equal(data.DriverDisk)) ||
|
||||
(!config.UnsetUuid.IsNull() && !config.UnsetUuid.Equal(data.UnsetUuid)) ||
|
||||
(!config.LocalRtc.IsNull() && !config.LocalRtc.Equal(data.LocalRtc))
|
||||
}
|
||||
|
||||
func (r *serverResource) updateAdvancedFeatures(
|
||||
ctx context.Context,
|
||||
serverId int64,
|
||||
config *resources.AdvancedFeaturesValue,
|
||||
data *resources.AdvancedFeaturesValue,
|
||||
) error {
|
||||
// If none of the writable advanced features have been modified by the user, we can skip the update
|
||||
if !isAdvFeatChanged(config, data) {
|
||||
return nil
|
||||
}
|
||||
|
||||
tflog.Info(ctx, fmt.Sprintf("Changing advanced features for server: server_id=%d", serverId))
|
||||
|
||||
enabledAdvancedFeatures := []string{}
|
||||
|
||||
// The enabled advanced features are flags that the user has configured, or are configured by default
|
||||
emulatedHyperV := config.EmulatedHyperv.ValueBool() || config.EmulatedHyperv.IsNull() && data.EmulatedDevices.ValueBool()
|
||||
if emulatedHyperV {
|
||||
enabledAdvancedFeatures = append(enabledAdvancedFeatures, "emulated-hyperv")
|
||||
}
|
||||
emulatedDevices := config.EmulatedDevices.ValueBool() || config.EmulatedDevices.IsNull() && data.EmulatedDevices.ValueBool()
|
||||
if emulatedDevices {
|
||||
enabledAdvancedFeatures = append(enabledAdvancedFeatures, "emulated-devices")
|
||||
}
|
||||
emulatedTPM := config.EmulatedTpm.ValueBool() || config.EmulatedTpm.IsNull() && data.EmulatedTpm.ValueBool()
|
||||
if emulatedTPM {
|
||||
enabledAdvancedFeatures = append(enabledAdvancedFeatures, "emulated-tpm")
|
||||
}
|
||||
nestedVirt := config.NestedVirt.ValueBool() || config.NestedVirt.IsNull() && data.NestedVirt.ValueBool()
|
||||
if nestedVirt {
|
||||
enabledAdvancedFeatures = append(enabledAdvancedFeatures, "nested-virt")
|
||||
}
|
||||
driverDisk := config.DriverDisk.ValueBool() || config.DriverDisk.IsNull() && data.DriverDisk.ValueBool()
|
||||
if driverDisk {
|
||||
enabledAdvancedFeatures = append(enabledAdvancedFeatures, "driver-disk")
|
||||
}
|
||||
unsetUUID := config.UnsetUuid.ValueBool() || config.UnsetUuid.IsNull() && data.UnsetUuid.ValueBool()
|
||||
if unsetUUID {
|
||||
enabledAdvancedFeatures = append(enabledAdvancedFeatures, "unset-uuid")
|
||||
}
|
||||
localRTC := config.LocalRtc.ValueBool() || config.LocalRtc.IsNull() && data.LocalRtc.ValueBool()
|
||||
if localRTC {
|
||||
enabledAdvancedFeatures = append(enabledAdvancedFeatures, "local-rtc")
|
||||
}
|
||||
|
||||
// Include the current value of read-only advanced features in the payload to the server
|
||||
cloudInit := data.CloudInit.ValueBool()
|
||||
if cloudInit {
|
||||
enabledAdvancedFeatures = append(enabledAdvancedFeatures, "cloud-init")
|
||||
}
|
||||
qemuGuestAgent := data.QemuGuestAgent.ValueBool()
|
||||
if qemuGuestAgent {
|
||||
enabledAdvancedFeatures = append(enabledAdvancedFeatures, "qemu-guest-agent")
|
||||
}
|
||||
uefiBoot := data.UefiBoot.ValueBool()
|
||||
if uefiBoot {
|
||||
enabledAdvancedFeatures = append(enabledAdvancedFeatures, "uefi-boot")
|
||||
}
|
||||
|
||||
resp, err := r.bc.client.PostServersServerIdActionsChangeAdvancedFeaturesWithResponse(
|
||||
ctx,
|
||||
serverId,
|
||||
binarylane.PostServersServerIdActionsChangeAdvancedFeaturesJSONRequestBody{
|
||||
Type: "change_advanced_features",
|
||||
EnabledAdvancedFeatures: &enabledAdvancedFeatures,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error changing advanced features for server: server_id=%d, error: %w", serverId, err)
|
||||
}
|
||||
if resp.StatusCode() != http.StatusOK {
|
||||
return fmt.Errorf("unexpected HTTP status code updating advanced features for server: server_id=%d, details: %s", serverId, resp.Body)
|
||||
}
|
||||
|
||||
err = r.waitForServerAction(ctx, serverId, *resp.JSON200.Action.Id)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to confirm advanced features for server was successful: %w", err)
|
||||
}
|
||||
|
||||
data.EmulatedHyperv = types.BoolValue(emulatedHyperV)
|
||||
data.EmulatedDevices = types.BoolValue(emulatedDevices)
|
||||
data.EmulatedTpm = types.BoolValue(emulatedTPM)
|
||||
data.NestedVirt = types.BoolValue(nestedVirt)
|
||||
data.DriverDisk = types.BoolValue(driverDisk)
|
||||
data.UnsetUuid = types.BoolValue(unsetUUID)
|
||||
data.LocalRtc = types.BoolValue(localRTC)
|
||||
data.CloudInit = types.BoolValue(cloudInit)
|
||||
data.QemuGuestAgent = types.BoolValue(qemuGuestAgent)
|
||||
data.UefiBoot = types.BoolValue(uefiBoot)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -16,16 +16,11 @@ import (
|
||||
|
||||
func TestServerResource(t *testing.T) {
|
||||
// Must assign a password to the server or Binary Lane will send emails
|
||||
pwBytes := make([]byte, 12)
|
||||
rand.Read(pwBytes)
|
||||
password := base64.URLEncoding.EncodeToString(pwBytes)
|
||||
password1 := GenerateTestPassword(t)
|
||||
password2 := GenerateTestPassword(t)
|
||||
|
||||
pwBytes2 := make([]byte, 12)
|
||||
rand.Read(pwBytes2)
|
||||
password2 := base64.URLEncoding.EncodeToString(pwBytes2)
|
||||
|
||||
sshPublicKeyInitial := GeneratePublicKey(t)
|
||||
sshPublicKeyUpdated := GeneratePublicKey(t)
|
||||
sshPublicKeyInitial := GenerateTestPublicKey(t)
|
||||
sshPublicKeyUpdated := GenerateTestPublicKey(t)
|
||||
|
||||
resource.ParallelTest(t, resource.TestCase{
|
||||
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
|
||||
@@ -57,7 +52,7 @@ resource "binarylane_server" "test" {
|
||||
image = "debian-11"
|
||||
size = "std-min"
|
||||
memory = 1152
|
||||
password = "` + password + `"
|
||||
password = "` + password1 + `"
|
||||
vpc_id = binarylane_vpc.test.id
|
||||
public_ipv4_count = 1
|
||||
ssh_keys = [binarylane_ssh_key.initial.id]
|
||||
@@ -87,7 +82,7 @@ data "binarylane_server" "test" {
|
||||
resource.TestCheckResourceAttr("binarylane_server.test", "disk", "20"),
|
||||
resource.TestCheckResourceAttrSet("binarylane_server.test", "vpc_id"),
|
||||
resource.TestCheckResourceAttr("binarylane_server.test", "public_ipv4_count", "1"),
|
||||
resource.TestCheckResourceAttr("binarylane_server.test", "password", password),
|
||||
resource.TestCheckResourceAttr("binarylane_server.test", "password", password1),
|
||||
resource.TestCheckResourceAttr("binarylane_server.test", "user_data", `#cloud-config
|
||||
echo "Hello World" > /var/tmp/output.txt
|
||||
`),
|
||||
@@ -99,6 +94,18 @@ echo "Hello World" > /var/tmp/output.txt
|
||||
resource.TestCheckResourceAttrSet("binarylane_server.test", "permalink"),
|
||||
resource.TestCheckResourceAttr("binarylane_server.test", "source_and_destination_check", "false"),
|
||||
resource.TestCheckResourceAttr("binarylane_server.test", "backups", "true"),
|
||||
resource.TestCheckResourceAttr("binarylane_server.test", "advanced_features.emulated_hyperv", "false"),
|
||||
resource.TestCheckResourceAttr("binarylane_server.test", "advanced_features.emulated_devices", "false"),
|
||||
resource.TestCheckResourceAttr("binarylane_server.test", "advanced_features.nested_virt", "false"),
|
||||
resource.TestCheckResourceAttr("binarylane_server.test", "advanced_features.driver_disk", "false"),
|
||||
resource.TestCheckResourceAttr("binarylane_server.test", "advanced_features.unset_uuid", "false"),
|
||||
resource.TestCheckResourceAttr("binarylane_server.test", "advanced_features.local_rtc", "false"),
|
||||
resource.TestCheckResourceAttr("binarylane_server.test", "advanced_features.emulated_tpm", "false"),
|
||||
resource.TestCheckResourceAttr("binarylane_server.test", "advanced_features.cloud_init", "true"),
|
||||
resource.TestCheckResourceAttr("binarylane_server.test", "advanced_features.qemu_guest_agent", "false"),
|
||||
resource.TestCheckResourceAttr("binarylane_server.test", "advanced_features.uefi_boot", "false"),
|
||||
resource.TestCheckResourceAttr("binarylane_server.test", "ipv6", "false"),
|
||||
resource.TestCheckResourceAttr("binarylane_server.test", "public_ipv6_addresses.#", "0"),
|
||||
|
||||
// Verify data source values
|
||||
resource.TestCheckResourceAttrPair("data.binarylane_server.test", "id", "binarylane_server.test", "id"),
|
||||
@@ -115,6 +122,18 @@ echo "Hello World" > /var/tmp/output.txt
|
||||
resource.TestCheckResourceAttr("data.binarylane_server.test", "disk", "20"),
|
||||
resource.TestCheckResourceAttr("data.binarylane_server.test", "backups", "true"),
|
||||
resource.TestCheckResourceAttr("data.binarylane_server.test", "port_blocking", "false"),
|
||||
resource.TestCheckResourceAttr("data.binarylane_server.test", "advanced_features.emulated_hyperv", "false"),
|
||||
resource.TestCheckResourceAttr("data.binarylane_server.test", "advanced_features.emulated_devices", "false"),
|
||||
resource.TestCheckResourceAttr("data.binarylane_server.test", "advanced_features.nested_virt", "false"),
|
||||
resource.TestCheckResourceAttr("data.binarylane_server.test", "advanced_features.driver_disk", "false"),
|
||||
resource.TestCheckResourceAttr("data.binarylane_server.test", "advanced_features.unset_uuid", "false"),
|
||||
resource.TestCheckResourceAttr("data.binarylane_server.test", "advanced_features.local_rtc", "false"),
|
||||
resource.TestCheckResourceAttr("data.binarylane_server.test", "advanced_features.emulated_tpm", "false"),
|
||||
resource.TestCheckResourceAttr("data.binarylane_server.test", "advanced_features.cloud_init", "true"),
|
||||
resource.TestCheckResourceAttr("data.binarylane_server.test", "advanced_features.qemu_guest_agent", "false"),
|
||||
resource.TestCheckResourceAttr("data.binarylane_server.test", "advanced_features.uefi_boot", "false"),
|
||||
resource.TestCheckResourceAttr("data.binarylane_server.test", "ipv6", "false"),
|
||||
resource.TestCheckResourceAttr("data.binarylane_server.test", "public_ipv6_addresses.#", "0"),
|
||||
),
|
||||
},
|
||||
// Test import by ID
|
||||
@@ -158,10 +177,14 @@ resource "binarylane_server" "test" {
|
||||
image = "debian-12"
|
||||
size = "std-1vcpu"
|
||||
disk = "45"
|
||||
password = "` + password + `"
|
||||
password = "` + password1 + `"
|
||||
vpc_id = null
|
||||
public_ipv4_count = 0
|
||||
ssh_keys = [binarylane_ssh_key.updated.id]
|
||||
advanced_features = {
|
||||
emulated_hyperv = true
|
||||
}
|
||||
ipv6 = true
|
||||
|
||||
# source_and_destination_check = null # defaults to null
|
||||
# backups = false # defaults to false
|
||||
@@ -186,6 +209,7 @@ EOT
|
||||
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.TestCheckResourceAttr("binarylane_server.test", "advanced_features.emulated_hyperv", "true"),
|
||||
resource.TestCheckNoResourceAttr("binarylane_server.test", "source_and_destination_check"),
|
||||
resource.TestCheckResourceAttr("binarylane_server.test", "backups", "false"),
|
||||
resource.TestCheckResourceAttr("binarylane_server.test", "port_blocking", "true"),
|
||||
@@ -195,6 +219,9 @@ echo "Hello Whitespace" > /var/tmp/output.txt
|
||||
|
||||
|
||||
`),
|
||||
resource.TestCheckResourceAttr("binarylane_server.test", "ipv6", "true"),
|
||||
resource.TestCheckResourceAttr("binarylane_server.test", "public_ipv6_addresses.#", "1"),
|
||||
resource.TestCheckResourceAttr("binarylane_server.test", "private_ipv6_addresses.#", "1"),
|
||||
),
|
||||
},
|
||||
// Change password testing (Cannot run at same time as Rebuild operation, so it has it's own test)
|
||||
@@ -249,6 +276,61 @@ EOT
|
||||
})
|
||||
}
|
||||
|
||||
func TestServerResourceRename(t *testing.T) {
|
||||
// Must assign a password to the server or Binary Lane will send emails
|
||||
password := GenerateTestPassword(t)
|
||||
|
||||
resource.ParallelTest(t, resource.TestCase{
|
||||
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
|
||||
Steps: []resource.TestStep{
|
||||
// Setup
|
||||
{
|
||||
Config: providerConfig + `
|
||||
|
||||
resource "binarylane_server" "test" {
|
||||
name = "tf-test-server-rename-1"
|
||||
region = "per"
|
||||
image = "debian-11"
|
||||
size = "std-min"
|
||||
public_ipv4_count = 0
|
||||
password = "` + password + `"
|
||||
}
|
||||
`,
|
||||
},
|
||||
// Rename
|
||||
{
|
||||
Config: providerConfig + `
|
||||
resource "binarylane_server" "test" {
|
||||
name = "tf-test-server-rename-2"
|
||||
region = "per"
|
||||
image = "debian-11"
|
||||
size = "std-min"
|
||||
public_ipv4_count = 0
|
||||
password = "` + password + `"
|
||||
}
|
||||
`,
|
||||
Check: resource.ComposeAggregateTestCheckFunc(
|
||||
resource.TestCheckResourceAttr("binarylane_server.test", "name", "tf-test-server-rename-2"),
|
||||
resource.TestCheckResourceAttr("binarylane_server.test", "region", "per"),
|
||||
resource.TestCheckResourceAttr("binarylane_server.test", "image", "debian-11"),
|
||||
resource.TestCheckResourceAttr("binarylane_server.test", "size", "std-min"),
|
||||
resource.TestCheckResourceAttr("binarylane_server.test", "password", password),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func GenerateTestPassword(t *testing.T) string {
|
||||
t.Helper()
|
||||
pwBytes := make([]byte, 12)
|
||||
_, err := rand.Read(pwBytes)
|
||||
if err != nil {
|
||||
t.Errorf("Failed to generate password: %s", err)
|
||||
}
|
||||
return base64.URLEncoding.EncodeToString(pwBytes)
|
||||
}
|
||||
|
||||
func init() {
|
||||
resource.AddTestSweepers("server", &resource.Sweeper{
|
||||
Name: "server",
|
||||
|
||||
@@ -72,8 +72,17 @@ func (d *sshKeyDataSource) Schema(ctx context.Context, req datasource.SchemaRequ
|
||||
}
|
||||
|
||||
// Additional attributes
|
||||
publicKeyDescription := "The public key in OpenSSH \"authorized_keys\" format. This should be a valid public key, " +
|
||||
"such as one generated by `ssh-keygen`."
|
||||
resp.Schema.Attributes["public_key"] = schema.StringAttribute{
|
||||
Description: publicKeyDescription,
|
||||
MarkdownDescription: publicKeyDescription,
|
||||
CustomType: TrimmedStringType{},
|
||||
Computed: true,
|
||||
}
|
||||
|
||||
fingerprintDescription := "The fingerprint of the SSH key."
|
||||
resp.Schema.Attributes["fingerprint"] = &schema.StringAttribute{
|
||||
resp.Schema.Attributes["fingerprint"] = schema.StringAttribute{
|
||||
Description: fingerprintDescription,
|
||||
MarkdownDescription: fingerprintDescription,
|
||||
Optional: false,
|
||||
@@ -112,7 +121,9 @@ func (d *sshKeyDataSource) Read(ctx context.Context, req datasource.ReadRequest,
|
||||
data.Id = types.Int64Value(*sshResp.JSON200.SshKey.Id)
|
||||
data.Default = types.BoolValue(*sshResp.JSON200.SshKey.Default)
|
||||
data.Name = types.StringValue(*sshResp.JSON200.SshKey.Name)
|
||||
data.PublicKey = types.StringValue(*sshResp.JSON200.SshKey.PublicKey)
|
||||
data.PublicKey = TrimmedStringValue{
|
||||
StringValue: types.StringValue(*sshResp.JSON200.SshKey.PublicKey),
|
||||
}
|
||||
data.Fingerprint = types.StringValue(*sshResp.JSON200.SshKey.Fingerprint)
|
||||
|
||||
// Save data into Terraform state
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/int64planmodifier"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||
@@ -35,7 +36,8 @@ type sshKeyResource struct {
|
||||
|
||||
type sshKeyModel struct {
|
||||
resources.SshKeyModel
|
||||
Fingerprint types.String `tfsdk:"fingerprint"`
|
||||
Fingerprint types.String `tfsdk:"fingerprint"`
|
||||
PublicKey TrimmedStringValue `tfsdk:"public_key"`
|
||||
}
|
||||
|
||||
func (d *sshKeyResource) Configure(_ context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) {
|
||||
@@ -71,11 +73,15 @@ func (r *sshKeyResource) Schema(ctx context.Context, req resource.SchemaRequest,
|
||||
Computed: true,
|
||||
Description: idDescription,
|
||||
MarkdownDescription: idDescription,
|
||||
PlanModifiers: []planmodifier.Int64{
|
||||
int64planmodifier.UseStateForUnknown(),
|
||||
},
|
||||
}
|
||||
|
||||
defaultDescription := "If `true`, this SSH key will be included on all new server installations (if the operating " +
|
||||
"system supports SSH key injection). Default is `false`."
|
||||
resp.Schema.Attributes["default"] = schema.BoolAttribute{
|
||||
Required: false,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
Description: defaultDescription,
|
||||
@@ -83,22 +89,31 @@ func (r *sshKeyResource) Schema(ctx context.Context, req resource.SchemaRequest,
|
||||
Default: booldefault.StaticBool(false), // Add default to backups
|
||||
}
|
||||
|
||||
public_key := resp.Schema.Attributes["public_key"]
|
||||
// Additional attributes
|
||||
publicKeyDescription := "The public key in OpenSSH \"authorized_keys\" format. This should be a valid public key, " +
|
||||
"such as one generated by `ssh-keygen`."
|
||||
resp.Schema.Attributes["public_key"] = schema.StringAttribute{
|
||||
Required: true,
|
||||
Description: public_key.GetDescription(),
|
||||
MarkdownDescription: public_key.GetMarkdownDescription(),
|
||||
PlanModifiers: []planmodifier.String{stringplanmodifier.RequiresReplace()},
|
||||
Optional: false,
|
||||
Computed: false,
|
||||
Description: publicKeyDescription,
|
||||
MarkdownDescription: publicKeyDescription,
|
||||
PlanModifiers: []planmodifier.String{
|
||||
RequiresReplaceForTrimmedStringModifier{},
|
||||
},
|
||||
CustomType: TrimmedStringType{}, // Ignore leading/trailing whitespace
|
||||
}
|
||||
|
||||
// Additional attributes
|
||||
fingerprintDescription := "The fingerprint of the SSH key."
|
||||
resp.Schema.Attributes["fingerprint"] = &schema.StringAttribute{
|
||||
resp.Schema.Attributes["fingerprint"] = schema.StringAttribute{
|
||||
Description: fingerprintDescription,
|
||||
MarkdownDescription: fingerprintDescription,
|
||||
Optional: false,
|
||||
Required: false,
|
||||
Computed: true,
|
||||
PlanModifiers: []planmodifier.String{
|
||||
stringplanmodifier.UseStateForUnknown(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,9 +169,6 @@ func (r *sshKeyResource) Read(ctx context.Context, req resource.ReadRequest, res
|
||||
|
||||
// Read Terraform prior state data into the model
|
||||
resp.Diagnostics.Append(req.State.Get(ctx, &data)...)
|
||||
|
||||
data.PublicKey = types.StringValue(data.PublicKey.ValueString())
|
||||
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
@@ -182,7 +194,9 @@ func (r *sshKeyResource) Read(ctx context.Context, req resource.ReadRequest, res
|
||||
data.Id = types.Int64Value(*sshResp.JSON200.SshKey.Id)
|
||||
data.Default = types.BoolValue(*sshResp.JSON200.SshKey.Default)
|
||||
data.Name = types.StringValue(*sshResp.JSON200.SshKey.Name)
|
||||
data.PublicKey = types.StringValue(*sshResp.JSON200.SshKey.PublicKey)
|
||||
data.PublicKey = TrimmedStringValue{
|
||||
StringValue: types.StringValue(*sshResp.JSON200.SshKey.PublicKey),
|
||||
}
|
||||
data.Fingerprint = types.StringValue(*sshResp.JSON200.SshKey.Fingerprint)
|
||||
|
||||
// Save updated data into Terraform state
|
||||
@@ -205,27 +219,31 @@ func (r *sshKeyResource) Update(ctx context.Context, req resource.UpdateRequest,
|
||||
}
|
||||
|
||||
// Update API call logic
|
||||
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", plan.Name.ValueString()),
|
||||
err.Error(),
|
||||
)
|
||||
return
|
||||
}
|
||||
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(), plan.Name.ValueString(), sshResp.Body),
|
||||
)
|
||||
return
|
||||
if !state.Name.Equal(plan.Name) || !state.Default.Equal(plan.Default) {
|
||||
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", plan.Name.ValueString()),
|
||||
err.Error(),
|
||||
)
|
||||
return
|
||||
}
|
||||
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(), plan.Name.ValueString(), sshResp.Body),
|
||||
)
|
||||
return
|
||||
}
|
||||
state.Name = plan.Name
|
||||
state.Default = plan.Default
|
||||
}
|
||||
|
||||
// Save updated data into Terraform state
|
||||
resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...)
|
||||
resp.Diagnostics.Append(resp.State.Set(ctx, &state)...)
|
||||
}
|
||||
|
||||
func (r *sshKeyResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
|
||||
|
||||
@@ -12,11 +12,12 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
|
||||
"github.com/hashicorp/terraform-plugin-testing/plancheck"
|
||||
"github.com/hashicorp/terraform-plugin-testing/terraform"
|
||||
)
|
||||
|
||||
func TestSshKeyResource(t *testing.T) {
|
||||
publicKey := GeneratePublicKey(t)
|
||||
publicKey := GenerateTestPublicKey(t)
|
||||
|
||||
resource.ParallelTest(t, resource.TestCase{
|
||||
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
|
||||
@@ -40,12 +41,14 @@ data "binarylane_ssh_key" "test" {
|
||||
// Verify resource values
|
||||
resource.TestCheckResourceAttr("binarylane_ssh_key.test", "name", "tf-test-key-resource-test"),
|
||||
resource.TestCheckResourceAttr("binarylane_ssh_key.test", "public_key", publicKey),
|
||||
resource.TestCheckResourceAttrSet("binarylane_ssh_key.test", "fingerprint"),
|
||||
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-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", "public_key", publicKey),
|
||||
resource.TestCheckResourceAttrSet("data.binarylane_ssh_key.test", "fingerprint"),
|
||||
resource.TestCheckResourceAttr("data.binarylane_ssh_key.test", "default", "false"),
|
||||
resource.TestCheckResourceAttrSet("data.binarylane_ssh_key.test", "id"),
|
||||
),
|
||||
@@ -64,27 +67,27 @@ data "binarylane_ssh_key" "test" {
|
||||
ImportStateVerify: true,
|
||||
ImportStateVerifyIgnore: []string{}, // nothing to ignore
|
||||
},
|
||||
// TODO: Update and Read testing
|
||||
// {
|
||||
// Config: providerConfig + `
|
||||
// resource "binarylane_ssh_key" "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-test-key-resource-test"),
|
||||
// resource.TestCheckResourceAttr("data.binarylane_ssh_key.test", "default", "true"),
|
||||
// ),
|
||||
// },
|
||||
// Delete testing automatically occurs in TestCase
|
||||
// Whitespace changes should not recreate the resource
|
||||
{
|
||||
Config: `
|
||||
resource "binarylane_ssh_key" "test" {
|
||||
name = "tf-test-key-resource-test"
|
||||
# Test public key with a newline to ensure it does not get recreated
|
||||
public_key = <<EOT
|
||||
` + publicKey + `
|
||||
EOT
|
||||
}`,
|
||||
ConfigPlanChecks: resource.ConfigPlanChecks{
|
||||
PreApply: []plancheck.PlanCheck{
|
||||
plancheck.ExpectEmptyPlan(),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func GeneratePublicKey(t *testing.T) string {
|
||||
func GenerateTestPublicKey(t *testing.T) string {
|
||||
t.Helper()
|
||||
|
||||
pub, _, err := ed25519.GenerateKey(nil)
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
package provider
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-framework/attr"
|
||||
"github.com/hashicorp/terraform-plugin-framework/diag"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types/basetypes"
|
||||
"github.com/hashicorp/terraform-plugin-go/tftypes"
|
||||
"github.com/hashicorp/terraform-plugin-log/tflog"
|
||||
)
|
||||
|
||||
// TrimmedStringType
|
||||
|
||||
// Ensure the implementation satisfies the expected interfaces
|
||||
var _ basetypes.StringTypable = TrimmedStringType{}
|
||||
|
||||
type TrimmedStringType struct {
|
||||
basetypes.StringType
|
||||
}
|
||||
|
||||
func (t TrimmedStringType) Equal(o attr.Type) bool {
|
||||
other, ok := o.(TrimmedStringType)
|
||||
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
return t.StringType.Equal(other.StringType)
|
||||
}
|
||||
|
||||
func (t TrimmedStringType) String() string {
|
||||
return "TrimmedStringType"
|
||||
}
|
||||
|
||||
func (t TrimmedStringType) ValueFromString(ctx context.Context, in basetypes.StringValue) (basetypes.StringValuable, diag.Diagnostics) {
|
||||
value := TrimmedStringValue{
|
||||
StringValue: in,
|
||||
}
|
||||
|
||||
return value, nil
|
||||
}
|
||||
|
||||
func (t TrimmedStringType) ValueFromTerraform(ctx context.Context, in tftypes.Value) (attr.Value, error) {
|
||||
attrValue, err := t.StringType.ValueFromTerraform(ctx, in)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
stringValue, ok := attrValue.(basetypes.StringValue)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected value type of %T", attrValue)
|
||||
}
|
||||
|
||||
stringValuable, diags := t.ValueFromString(ctx, stringValue)
|
||||
if diags.HasError() {
|
||||
return nil, fmt.Errorf("unexpected error converting StringValue to StringValuable: %v", diags)
|
||||
}
|
||||
|
||||
return stringValuable, nil
|
||||
}
|
||||
|
||||
func (t TrimmedStringType) ValueType(ctx context.Context) attr.Value {
|
||||
return TrimmedStringValue{}
|
||||
}
|
||||
|
||||
// TrimmedStringValue
|
||||
|
||||
var _ basetypes.StringValuable = TrimmedStringValue{}
|
||||
var _ basetypes.StringValuableWithSemanticEquals = TrimmedStringValue{}
|
||||
|
||||
type TrimmedStringValue struct {
|
||||
basetypes.StringValue
|
||||
}
|
||||
|
||||
func (v TrimmedStringValue) Equal(o attr.Value) bool {
|
||||
other, ok := o.(TrimmedStringValue)
|
||||
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
return v.StringValue.Equal(other.StringValue)
|
||||
}
|
||||
|
||||
func (v TrimmedStringValue) Type(ctx context.Context) attr.Type {
|
||||
return TrimmedStringType{}
|
||||
}
|
||||
|
||||
func (v TrimmedStringValue) StringSemanticEquals(ctx context.Context, newValuable basetypes.StringValuable) (bool, diag.Diagnostics) {
|
||||
var diags diag.Diagnostics
|
||||
|
||||
// The framework should always pass the correct value type, but always check
|
||||
newValue, ok := newValuable.(TrimmedStringValue)
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Semantic Equality Check Error",
|
||||
"An unexpected value type was received while performing semantic equality checks. "+
|
||||
"Please report this to the provider developers.\n\n"+
|
||||
"Expected Value Type: "+fmt.Sprintf("%T", v)+"\n"+
|
||||
"Got Value Type: "+fmt.Sprintf("%T", newValuable),
|
||||
)
|
||||
|
||||
return false, diags
|
||||
}
|
||||
|
||||
priorString := strings.TrimSpace(v.StringValue.ValueString())
|
||||
newString := strings.TrimSpace(newValue.ValueString())
|
||||
|
||||
// If the strings are equivalent, keep the prior value
|
||||
return priorString == newString, diags
|
||||
}
|
||||
|
||||
// PlanModifier
|
||||
var _ planmodifier.String = RequiresReplaceForTrimmedStringModifier{}
|
||||
|
||||
type RequiresReplaceForTrimmedStringModifier struct{}
|
||||
|
||||
func (m RequiresReplaceForTrimmedStringModifier) Description(_ context.Context) string {
|
||||
return "If the value of this attribute changes, Terraform will destroy and recreate the resource."
|
||||
}
|
||||
|
||||
func (m RequiresReplaceForTrimmedStringModifier) MarkdownDescription(_ context.Context) string {
|
||||
return "If the value of this attribute changes, Terraform will destroy and recreate the resource."
|
||||
}
|
||||
|
||||
func (m RequiresReplaceForTrimmedStringModifier) PlanModifyString(ctx context.Context, req planmodifier.StringRequest, resp *planmodifier.StringResponse) {
|
||||
// Do not replace on resource creation.
|
||||
if req.State.Raw.IsNull() {
|
||||
return
|
||||
}
|
||||
// Do not replace on resource destroy.
|
||||
if req.Plan.Raw.IsNull() {
|
||||
return
|
||||
}
|
||||
// Do not replace if the plan and state values are equal.
|
||||
if req.PlanValue.Equal(req.StateValue) {
|
||||
return
|
||||
}
|
||||
|
||||
// Create Normalized values for the state and plan.
|
||||
stateNormalized := TrimmedStringValue{
|
||||
StringValue: req.StateValue,
|
||||
}
|
||||
planNormalized := TrimmedStringValue{
|
||||
StringValue: req.PlanValue,
|
||||
}
|
||||
|
||||
// Perform semantic equality check.
|
||||
semanticallyEqual, diags := stateNormalized.StringSemanticEquals(ctx, planNormalized)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
if diags.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
if semanticallyEqual {
|
||||
tflog.Info(ctx, "Plan and state values are semantically equal. Suppressing differences.")
|
||||
resp.PlanValue = req.StateValue
|
||||
} else {
|
||||
resp.RequiresReplace = true
|
||||
}
|
||||
}
|
||||
@@ -125,6 +125,7 @@ func convertResourceAttrToDataSourceAttr(name string, attribute r_schema.Attribu
|
||||
MarkdownDescription: attribute.GetMarkdownDescription(),
|
||||
DeprecationMessage: attribute.GetDeprecationMessage(),
|
||||
}, nil
|
||||
|
||||
default:
|
||||
if t, isList := attribute.(r_schema.ListNestedAttribute); isList {
|
||||
nestedObjectAttrs := make(map[string]d_schema.Attribute)
|
||||
@@ -135,13 +136,13 @@ func convertResourceAttrToDataSourceAttr(name string, attribute r_schema.Attribu
|
||||
}
|
||||
nestedObjectAttrs[name] = nestedAttribute
|
||||
}
|
||||
|
||||
return d_schema.ListNestedAttribute{
|
||||
NestedObject: d_schema.NestedAttributeObject{
|
||||
Attributes: nestedObjectAttrs,
|
||||
CustomType: t.NestedObject.CustomType,
|
||||
Validators: t.NestedObject.Validators,
|
||||
},
|
||||
CustomType: t.CustomType,
|
||||
Description: attribute.GetDescription(),
|
||||
Required: required,
|
||||
Optional: optional,
|
||||
@@ -164,7 +165,6 @@ func convertResourceAttrToDataSourceAttr(name string, attribute r_schema.Attribu
|
||||
DeprecationMessage: attribute.GetDeprecationMessage(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
if t, isObject := attribute.(r_schema.SingleNestedAttribute); isObject {
|
||||
attributeTypes := make(map[string]attr.Type, len(t.GetAttributes()))
|
||||
for name, attribute := range t.GetAttributes() {
|
||||
@@ -183,6 +183,18 @@ func convertResourceAttrToDataSourceAttr(name string, attribute r_schema.Attribu
|
||||
AttributeTypes: attributeTypes,
|
||||
}, nil
|
||||
}
|
||||
if t, isObject := attribute.GetType().(types.ObjectType); isObject {
|
||||
return d_schema.ObjectAttribute{
|
||||
AttributeTypes: t.AttrTypes,
|
||||
Description: attribute.GetDescription(),
|
||||
Required: required,
|
||||
Optional: optional,
|
||||
Computed: !required,
|
||||
Sensitive: attribute.IsSensitive(),
|
||||
MarkdownDescription: attribute.GetMarkdownDescription(),
|
||||
DeprecationMessage: attribute.GetDeprecationMessage(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("conversion of attribute type is not implemented: name=%s, type=%s", name, attribute.GetType())
|
||||
}
|
||||
|
||||
@@ -12,6 +12,9 @@ import (
|
||||
"github.com/hashicorp/terraform-plugin-framework/path"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringdefault"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||
"github.com/hashicorp/terraform-plugin-log/tflog"
|
||||
)
|
||||
@@ -60,7 +63,7 @@ func (r *vpcResource) Schema(ctx context.Context, req resource.SchemaRequest, re
|
||||
|
||||
// Overrides
|
||||
id := resp.Schema.Attributes["id"]
|
||||
resp.Schema.Attributes["id"] = &schema.Int64Attribute{
|
||||
resp.Schema.Attributes["id"] = schema.Int64Attribute{
|
||||
Description: id.GetDescription(),
|
||||
MarkdownDescription: id.GetMarkdownDescription(),
|
||||
// read only
|
||||
@@ -68,6 +71,19 @@ func (r *vpcResource) Schema(ctx context.Context, req resource.SchemaRequest, re
|
||||
Required: false,
|
||||
Computed: true,
|
||||
}
|
||||
|
||||
ipRange := resp.Schema.Attributes["ip_range"]
|
||||
resp.Schema.Attributes["ip_range"] = schema.StringAttribute{
|
||||
Description: ipRange.GetDescription(),
|
||||
MarkdownDescription: ipRange.GetMarkdownDescription(),
|
||||
Required: false,
|
||||
Computed: true,
|
||||
Optional: true,
|
||||
PlanModifiers: []planmodifier.String{
|
||||
stringplanmodifier.RequiresReplace(),
|
||||
},
|
||||
Default: stringdefault.StaticString("10.240.0.0/16"),
|
||||
}
|
||||
}
|
||||
|
||||
func (r *vpcResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
|
||||
|
||||
@@ -47,7 +47,7 @@ func (d *vpcRouteEntriesDataSource) Schema(ctx context.Context, req datasource.S
|
||||
|
||||
// Overrides
|
||||
vpcId := resp.Schema.Attributes["vpc_id"]
|
||||
resp.Schema.Attributes["vpc_id"] = &schema.Int64Attribute{
|
||||
resp.Schema.Attributes["vpc_id"] = schema.Int64Attribute{
|
||||
Description: vpcId.GetDescription(),
|
||||
MarkdownDescription: vpcId.GetMarkdownDescription(),
|
||||
Required: true, // vpc_id is required to define the route entries
|
||||
@@ -55,7 +55,7 @@ func (d *vpcRouteEntriesDataSource) Schema(ctx context.Context, req datasource.S
|
||||
|
||||
vpcRouteEntries := resp.Schema.Attributes["route_entries"].(schema.ListNestedAttribute)
|
||||
vpcRouteEntriesDescription := "The route entries that control how network traffic is directed through the VPC environment."
|
||||
resp.Schema.Attributes["route_entries"] = &schema.ListNestedAttribute{
|
||||
resp.Schema.Attributes["route_entries"] = schema.ListNestedAttribute{
|
||||
Description: vpcRouteEntriesDescription,
|
||||
NestedObject: schema.NestedAttributeObject{
|
||||
CustomType: vpcRouteEntries.NestedObject.CustomType,
|
||||
|
||||
@@ -48,7 +48,7 @@ func (r *vpcRouteEntriesResource) Schema(ctx context.Context, req resource.Schem
|
||||
|
||||
// Overrides
|
||||
vpcId := resp.Schema.Attributes["vpc_id"]
|
||||
resp.Schema.Attributes["vpc_id"] = &schema.Int64Attribute{
|
||||
resp.Schema.Attributes["vpc_id"] = schema.Int64Attribute{
|
||||
Description: vpcId.GetDescription(),
|
||||
MarkdownDescription: vpcId.GetMarkdownDescription(),
|
||||
Required: true, // vpc_id is required to define the route entries
|
||||
@@ -246,7 +246,7 @@ func GetRouteEntriesState(ctx context.Context, routeEntries *[]binarylane.RouteE
|
||||
routeEntriesValue := resources.RouteEntriesValue{}
|
||||
var routeEntriesValues []resources.RouteEntriesValue
|
||||
|
||||
if *routeEntries == nil || len(*routeEntries) == 0 {
|
||||
if len(*routeEntries) == 0 {
|
||||
routeEntriesValues = []resources.RouteEntriesValue{}
|
||||
} else {
|
||||
for _, route := range *routeEntries {
|
||||
|
||||
@@ -26,8 +26,8 @@ func LoadBalancerResourceSchema(ctx context.Context) schema.Schema {
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"entry_protocol": schema.StringAttribute{
|
||||
Required: true,
|
||||
Description: "The protocol that traffic must match for the load balancer to forward it. Valid values are \"http\" and \"https\".",
|
||||
MarkdownDescription: "The protocol that traffic must match for the load balancer to forward it. Valid values are \"http\" and \"https\".",
|
||||
Description: "The protocol that traffic must match for this load balancer to forward traffic according to this rule.\n\n| Value | Description |\n| ----- | ----------- |\n| http | The load balancer will forward HTTP traffic that matches this rule. |\n| https | The load balancer will forward HTTPS traffic that matches this rule. |\n\n",
|
||||
MarkdownDescription: "The protocol that traffic must match for this load balancer to forward traffic according to this rule.\n\n| Value | Description |\n| ----- | ----------- |\n| http | The load balancer will forward HTTP traffic that matches this rule. |\n| https | The load balancer will forward HTTPS traffic that matches this rule. |\n\n",
|
||||
Validators: []validator.String{
|
||||
stringvalidator.OneOf(
|
||||
"http",
|
||||
@@ -61,8 +61,8 @@ func LoadBalancerResourceSchema(ctx context.Context) schema.Schema {
|
||||
"protocol": schema.StringAttribute{
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
Description: "Leave null to accept the default HTTP protocol.",
|
||||
MarkdownDescription: "Leave null to accept the default HTTP protocol.",
|
||||
Description: "Leave null to accept the default HTTP protocol.\n\n| Value | Description |\n| ----- | ----------- |\n| http | The health check will be performed via HTTP. |\n| https | The health check will be performed via HTTPS. |\n| both | The health check will be performed via both HTTP and HTTPS. Failing a health check on one protocol will remove the server from the pool of servers only for that protocol. |\n\n",
|
||||
MarkdownDescription: "Leave null to accept the default HTTP protocol.\n\n| Value | Description |\n| ----- | ----------- |\n| http | The health check will be performed via HTTP. |\n| https | The health check will be performed via HTTPS. |\n| both | The health check will be performed via both HTTP and HTTPS. Failing a health check on one protocol will remove the server from the pool of servers only for that protocol. |\n\n",
|
||||
},
|
||||
},
|
||||
CustomType: HealthCheckType{
|
||||
|
||||
@@ -26,8 +26,8 @@ func ServerFirewallRulesResourceSchema(ctx context.Context) schema.Schema {
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"action": schema.StringAttribute{
|
||||
Required: true,
|
||||
Description: "The action to take when there is a match on this rule.",
|
||||
MarkdownDescription: "The action to take when there is a match on this rule.",
|
||||
Description: "The action to take when there is a match on this rule.\n\n| Value | Description |\n| ----- | ----------- |\n| drop | Traffic matching this rule will be dropped. |\n| accept | Traffic matching this rule will be accepted. |\n\n",
|
||||
MarkdownDescription: "The action to take when there is a match on this rule.\n\n| Value | Description |\n| ----- | ----------- |\n| drop | Traffic matching this rule will be dropped. |\n| accept | Traffic matching this rule will be accepted. |\n\n",
|
||||
Validators: []validator.String{
|
||||
stringvalidator.OneOf(
|
||||
"drop",
|
||||
@@ -62,8 +62,8 @@ func ServerFirewallRulesResourceSchema(ctx context.Context) schema.Schema {
|
||||
},
|
||||
"protocol": schema.StringAttribute{
|
||||
Required: true,
|
||||
Description: "The protocol to match for this rule.",
|
||||
MarkdownDescription: "The protocol to match for this rule.",
|
||||
Description: "The protocol to match for this rule.\n\n| Value | Description |\n| ----- | ----------- |\n| all | This rule will match any protocol. |\n| icmp | This rule will match ICMP traffic only. |\n| tcp | This rule will match TCP traffic only. |\n| udp | This rule will match UDP traffic only. |\n\n",
|
||||
MarkdownDescription: "The protocol to match for this rule.\n\n| Value | Description |\n| ----- | ----------- |\n| all | This rule will match any protocol. |\n| icmp | This rule will match ICMP traffic only. |\n| tcp | This rule will match TCP traffic only. |\n| udp | This rule will match UDP traffic only. |\n\n",
|
||||
Validators: []validator.String{
|
||||
stringvalidator.OneOf(
|
||||
"all",
|
||||
|
||||
@@ -4,9 +4,15 @@ package resources
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
|
||||
"github.com/hashicorp/terraform-plugin-framework/attr"
|
||||
"github.com/hashicorp/terraform-plugin-framework/diag"
|
||||
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types/basetypes"
|
||||
"github.com/hashicorp/terraform-plugin-go/tftypes"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
|
||||
)
|
||||
@@ -14,6 +20,74 @@ import (
|
||||
func ServerResourceSchema(ctx context.Context) schema.Schema {
|
||||
return schema.Schema{
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"advanced_features": schema.SingleNestedAttribute{
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"cloud_init": schema.BoolAttribute{
|
||||
Computed: true,
|
||||
Description: "When this option is enabled the Cloud Server will be provided a datasource for the cloud-init service.",
|
||||
MarkdownDescription: "When this option is enabled the Cloud Server will be provided a datasource for the cloud-init service.",
|
||||
},
|
||||
"driver_disk": schema.BoolAttribute{
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
Description: "When this option is enabled a copy of the KVM driver disc for Windows (\"virtio-win.iso\") will be attached to your server as a virtual CD. This option can also be used in combination with your own attached backup when installing Windows.",
|
||||
MarkdownDescription: "When this option is enabled a copy of the KVM driver disc for Windows (\"virtio-win.iso\") will be attached to your server as a virtual CD. This option can also be used in combination with your own attached backup when installing Windows.",
|
||||
},
|
||||
"emulated_devices": schema.BoolAttribute{
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
Description: "When emulated devices is enabled, the KVM specific \"VirtIO\" disk drive and network devices are removed, and replaced with emulated versions of physical hardware: an old IDE HDD and an Intel E1000 network card. Emulated devices are much slower than the VirtIO devices, and so this option should not be enabled unless absolutely necessary.",
|
||||
MarkdownDescription: "When emulated devices is enabled, the KVM specific \"VirtIO\" disk drive and network devices are removed, and replaced with emulated versions of physical hardware: an old IDE HDD and an Intel E1000 network card. Emulated devices are much slower than the VirtIO devices, and so this option should not be enabled unless absolutely necessary.",
|
||||
},
|
||||
"emulated_hyperv": schema.BoolAttribute{
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
Description: "Enable HyperV (a hypervisor produced by Microsoft) support. Enabled by default on Windows servers, generally of no value for non-Windows servers.",
|
||||
MarkdownDescription: "Enable HyperV (a hypervisor produced by Microsoft) support. Enabled by default on Windows servers, generally of no value for non-Windows servers.",
|
||||
},
|
||||
"emulated_tpm": schema.BoolAttribute{
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
Description: "When enabled this provides an emulated TPM v1.2 device to your Cloud Server. Warning: the TPM state is not backed up.",
|
||||
MarkdownDescription: "When enabled this provides an emulated TPM v1.2 device to your Cloud Server. Warning: the TPM state is not backed up.",
|
||||
},
|
||||
"local_rtc": schema.BoolAttribute{
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
Description: "When a server is booted the virtual BIOS receives the current date and time from the host node. The BIOS does not have an explicit timezone, so the timezone used is implicit and must be understood by the operating system. Most operating systems other than Windows expect the time to be UTC since it allows the operating system to control the timezone used when displaying the time. Our Windows installations have also been customized to use UTC, but when using your own installation of Windows this should be set to the host node's local timezone.",
|
||||
MarkdownDescription: "When a server is booted the virtual BIOS receives the current date and time from the host node. The BIOS does not have an explicit timezone, so the timezone used is implicit and must be understood by the operating system. Most operating systems other than Windows expect the time to be UTC since it allows the operating system to control the timezone used when displaying the time. Our Windows installations have also been customized to use UTC, but when using your own installation of Windows this should be set to the host node's local timezone.",
|
||||
},
|
||||
"nested_virt": schema.BoolAttribute{
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
Description: "When this option is enabled the functionality necessary to run your own KVM servers within your server is enabled. Note that all the networking limits - one MAC address per VPS, restricted to specific IPs - still apply to public cloud so this feature is generally only useful in combination with Virtual Private Cloud.",
|
||||
MarkdownDescription: "When this option is enabled the functionality necessary to run your own KVM servers within your server is enabled. Note that all the networking limits - one MAC address per VPS, restricted to specific IPs - still apply to public cloud so this feature is generally only useful in combination with Virtual Private Cloud.",
|
||||
},
|
||||
"qemu_guest_agent": schema.BoolAttribute{
|
||||
Computed: true,
|
||||
Description: "When this option is enabled the server will allow QEMU Guest Agent to perform password reset without rebooting.",
|
||||
MarkdownDescription: "When this option is enabled the server will allow QEMU Guest Agent to perform password reset without rebooting.",
|
||||
},
|
||||
"uefi_boot": schema.BoolAttribute{
|
||||
Computed: true,
|
||||
Description: "When this option is enabled the Cloud Server will use UEFI instead of legacy PC BIOS.",
|
||||
MarkdownDescription: "When this option is enabled the Cloud Server will use UEFI instead of legacy PC BIOS.",
|
||||
},
|
||||
"unset_uuid": schema.BoolAttribute{
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
Description: "When this option is NOT enabled a 128-bit unique identifier is exposed to your server through the virtual BIOS. Each server receives a different UUID. Some proprietary licensed software utilize this identifier to \"tie\" the license to a specific server.",
|
||||
MarkdownDescription: "When this option is NOT enabled a 128-bit unique identifier is exposed to your server through the virtual BIOS. Each server receives a different UUID. Some proprietary licensed software utilize this identifier to \"tie\" the license to a specific server.",
|
||||
},
|
||||
},
|
||||
CustomType: AdvancedFeaturesType{
|
||||
ObjectType: types.ObjectType{
|
||||
AttrTypes: AdvancedFeaturesValue{}.AttributeTypes(ctx),
|
||||
},
|
||||
},
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
},
|
||||
"backups": schema.BoolAttribute{
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
@@ -31,6 +105,12 @@ func ServerResourceSchema(ctx context.Context) schema.Schema {
|
||||
Description: "The slug of the selected operating system.",
|
||||
MarkdownDescription: "The slug of the selected operating system.",
|
||||
},
|
||||
"ipv6": schema.BoolAttribute{
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
Description: "If true this will enable IPv6 for this server.",
|
||||
MarkdownDescription: "If true this will enable IPv6 for this server.",
|
||||
},
|
||||
"name": schema.StringAttribute{
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
@@ -86,14 +166,835 @@ func ServerResourceSchema(ctx context.Context) schema.Schema {
|
||||
}
|
||||
|
||||
type ServerModel struct {
|
||||
Backups types.Bool `tfsdk:"backups"`
|
||||
Id types.Int64 `tfsdk:"id"`
|
||||
Image types.String `tfsdk:"image"`
|
||||
Name types.String `tfsdk:"name"`
|
||||
PortBlocking types.Bool `tfsdk:"port_blocking"`
|
||||
Region types.String `tfsdk:"region"`
|
||||
Size types.String `tfsdk:"size"`
|
||||
SshKeys types.List `tfsdk:"ssh_keys"`
|
||||
UserData types.String `tfsdk:"user_data"`
|
||||
VpcId types.Int64 `tfsdk:"vpc_id"`
|
||||
AdvancedFeatures AdvancedFeaturesValue `tfsdk:"advanced_features"`
|
||||
Backups types.Bool `tfsdk:"backups"`
|
||||
Id types.Int64 `tfsdk:"id"`
|
||||
Image types.String `tfsdk:"image"`
|
||||
Ipv6 types.Bool `tfsdk:"ipv6"`
|
||||
Name types.String `tfsdk:"name"`
|
||||
PortBlocking types.Bool `tfsdk:"port_blocking"`
|
||||
Region types.String `tfsdk:"region"`
|
||||
Size types.String `tfsdk:"size"`
|
||||
SshKeys types.List `tfsdk:"ssh_keys"`
|
||||
UserData types.String `tfsdk:"user_data"`
|
||||
VpcId types.Int64 `tfsdk:"vpc_id"`
|
||||
}
|
||||
|
||||
var _ basetypes.ObjectTypable = AdvancedFeaturesType{}
|
||||
|
||||
type AdvancedFeaturesType struct {
|
||||
basetypes.ObjectType
|
||||
}
|
||||
|
||||
func (t AdvancedFeaturesType) Equal(o attr.Type) bool {
|
||||
other, ok := o.(AdvancedFeaturesType)
|
||||
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
return t.ObjectType.Equal(other.ObjectType)
|
||||
}
|
||||
|
||||
func (t AdvancedFeaturesType) String() string {
|
||||
return "AdvancedFeaturesType"
|
||||
}
|
||||
|
||||
func (t AdvancedFeaturesType) ValueFromObject(ctx context.Context, in basetypes.ObjectValue) (basetypes.ObjectValuable, diag.Diagnostics) {
|
||||
var diags diag.Diagnostics
|
||||
|
||||
attributes := in.Attributes()
|
||||
|
||||
cloudInitAttribute, ok := attributes["cloud_init"]
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Missing",
|
||||
`cloud_init is missing from object`)
|
||||
|
||||
return nil, diags
|
||||
}
|
||||
|
||||
cloudInitVal, ok := cloudInitAttribute.(basetypes.BoolValue)
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Wrong Type",
|
||||
fmt.Sprintf(`cloud_init expected to be basetypes.BoolValue, was: %T`, cloudInitAttribute))
|
||||
}
|
||||
|
||||
driverDiskAttribute, ok := attributes["driver_disk"]
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Missing",
|
||||
`driver_disk is missing from object`)
|
||||
|
||||
return nil, diags
|
||||
}
|
||||
|
||||
driverDiskVal, ok := driverDiskAttribute.(basetypes.BoolValue)
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Wrong Type",
|
||||
fmt.Sprintf(`driver_disk expected to be basetypes.BoolValue, was: %T`, driverDiskAttribute))
|
||||
}
|
||||
|
||||
emulatedDevicesAttribute, ok := attributes["emulated_devices"]
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Missing",
|
||||
`emulated_devices is missing from object`)
|
||||
|
||||
return nil, diags
|
||||
}
|
||||
|
||||
emulatedDevicesVal, ok := emulatedDevicesAttribute.(basetypes.BoolValue)
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Wrong Type",
|
||||
fmt.Sprintf(`emulated_devices expected to be basetypes.BoolValue, was: %T`, emulatedDevicesAttribute))
|
||||
}
|
||||
|
||||
emulatedHypervAttribute, ok := attributes["emulated_hyperv"]
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Missing",
|
||||
`emulated_hyperv is missing from object`)
|
||||
|
||||
return nil, diags
|
||||
}
|
||||
|
||||
emulatedHypervVal, ok := emulatedHypervAttribute.(basetypes.BoolValue)
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Wrong Type",
|
||||
fmt.Sprintf(`emulated_hyperv expected to be basetypes.BoolValue, was: %T`, emulatedHypervAttribute))
|
||||
}
|
||||
|
||||
emulatedTpmAttribute, ok := attributes["emulated_tpm"]
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Missing",
|
||||
`emulated_tpm is missing from object`)
|
||||
|
||||
return nil, diags
|
||||
}
|
||||
|
||||
emulatedTpmVal, ok := emulatedTpmAttribute.(basetypes.BoolValue)
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Wrong Type",
|
||||
fmt.Sprintf(`emulated_tpm expected to be basetypes.BoolValue, was: %T`, emulatedTpmAttribute))
|
||||
}
|
||||
|
||||
localRtcAttribute, ok := attributes["local_rtc"]
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Missing",
|
||||
`local_rtc is missing from object`)
|
||||
|
||||
return nil, diags
|
||||
}
|
||||
|
||||
localRtcVal, ok := localRtcAttribute.(basetypes.BoolValue)
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Wrong Type",
|
||||
fmt.Sprintf(`local_rtc expected to be basetypes.BoolValue, was: %T`, localRtcAttribute))
|
||||
}
|
||||
|
||||
nestedVirtAttribute, ok := attributes["nested_virt"]
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Missing",
|
||||
`nested_virt is missing from object`)
|
||||
|
||||
return nil, diags
|
||||
}
|
||||
|
||||
nestedVirtVal, ok := nestedVirtAttribute.(basetypes.BoolValue)
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Wrong Type",
|
||||
fmt.Sprintf(`nested_virt expected to be basetypes.BoolValue, was: %T`, nestedVirtAttribute))
|
||||
}
|
||||
|
||||
qemuGuestAgentAttribute, ok := attributes["qemu_guest_agent"]
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Missing",
|
||||
`qemu_guest_agent is missing from object`)
|
||||
|
||||
return nil, diags
|
||||
}
|
||||
|
||||
qemuGuestAgentVal, ok := qemuGuestAgentAttribute.(basetypes.BoolValue)
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Wrong Type",
|
||||
fmt.Sprintf(`qemu_guest_agent expected to be basetypes.BoolValue, was: %T`, qemuGuestAgentAttribute))
|
||||
}
|
||||
|
||||
uefiBootAttribute, ok := attributes["uefi_boot"]
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Missing",
|
||||
`uefi_boot is missing from object`)
|
||||
|
||||
return nil, diags
|
||||
}
|
||||
|
||||
uefiBootVal, ok := uefiBootAttribute.(basetypes.BoolValue)
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Wrong Type",
|
||||
fmt.Sprintf(`uefi_boot expected to be basetypes.BoolValue, was: %T`, uefiBootAttribute))
|
||||
}
|
||||
|
||||
unsetUuidAttribute, ok := attributes["unset_uuid"]
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Missing",
|
||||
`unset_uuid is missing from object`)
|
||||
|
||||
return nil, diags
|
||||
}
|
||||
|
||||
unsetUuidVal, ok := unsetUuidAttribute.(basetypes.BoolValue)
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Wrong Type",
|
||||
fmt.Sprintf(`unset_uuid expected to be basetypes.BoolValue, was: %T`, unsetUuidAttribute))
|
||||
}
|
||||
|
||||
if diags.HasError() {
|
||||
return nil, diags
|
||||
}
|
||||
|
||||
return AdvancedFeaturesValue{
|
||||
CloudInit: cloudInitVal,
|
||||
DriverDisk: driverDiskVal,
|
||||
EmulatedDevices: emulatedDevicesVal,
|
||||
EmulatedHyperv: emulatedHypervVal,
|
||||
EmulatedTpm: emulatedTpmVal,
|
||||
LocalRtc: localRtcVal,
|
||||
NestedVirt: nestedVirtVal,
|
||||
QemuGuestAgent: qemuGuestAgentVal,
|
||||
UefiBoot: uefiBootVal,
|
||||
UnsetUuid: unsetUuidVal,
|
||||
state: attr.ValueStateKnown,
|
||||
}, diags
|
||||
}
|
||||
|
||||
func NewAdvancedFeaturesValueNull() AdvancedFeaturesValue {
|
||||
return AdvancedFeaturesValue{
|
||||
state: attr.ValueStateNull,
|
||||
}
|
||||
}
|
||||
|
||||
func NewAdvancedFeaturesValueUnknown() AdvancedFeaturesValue {
|
||||
return AdvancedFeaturesValue{
|
||||
state: attr.ValueStateUnknown,
|
||||
}
|
||||
}
|
||||
|
||||
func NewAdvancedFeaturesValue(attributeTypes map[string]attr.Type, attributes map[string]attr.Value) (AdvancedFeaturesValue, diag.Diagnostics) {
|
||||
var diags diag.Diagnostics
|
||||
|
||||
// Reference: https://github.com/hashicorp/terraform-plugin-framework/issues/521
|
||||
ctx := context.Background()
|
||||
|
||||
for name, attributeType := range attributeTypes {
|
||||
attribute, ok := attributes[name]
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Missing AdvancedFeaturesValue Attribute Value",
|
||||
"While creating a AdvancedFeaturesValue value, a missing attribute value was detected. "+
|
||||
"A AdvancedFeaturesValue must contain values for all attributes, even if null or unknown. "+
|
||||
"This is always an issue with the provider and should be reported to the provider developers.\n\n"+
|
||||
fmt.Sprintf("AdvancedFeaturesValue Attribute Name (%s) Expected Type: %s", name, attributeType.String()),
|
||||
)
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
if !attributeType.Equal(attribute.Type(ctx)) {
|
||||
diags.AddError(
|
||||
"Invalid AdvancedFeaturesValue Attribute Type",
|
||||
"While creating a AdvancedFeaturesValue value, an invalid attribute value was detected. "+
|
||||
"A AdvancedFeaturesValue must use a matching attribute type for the value. "+
|
||||
"This is always an issue with the provider and should be reported to the provider developers.\n\n"+
|
||||
fmt.Sprintf("AdvancedFeaturesValue Attribute Name (%s) Expected Type: %s\n", name, attributeType.String())+
|
||||
fmt.Sprintf("AdvancedFeaturesValue Attribute Name (%s) Given Type: %s", name, attribute.Type(ctx)),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
for name := range attributes {
|
||||
_, ok := attributeTypes[name]
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Extra AdvancedFeaturesValue Attribute Value",
|
||||
"While creating a AdvancedFeaturesValue value, an extra attribute value was detected. "+
|
||||
"A AdvancedFeaturesValue must not contain values beyond the expected attribute types. "+
|
||||
"This is always an issue with the provider and should be reported to the provider developers.\n\n"+
|
||||
fmt.Sprintf("Extra AdvancedFeaturesValue Attribute Name: %s", name),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if diags.HasError() {
|
||||
return NewAdvancedFeaturesValueUnknown(), diags
|
||||
}
|
||||
|
||||
cloudInitAttribute, ok := attributes["cloud_init"]
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Missing",
|
||||
`cloud_init is missing from object`)
|
||||
|
||||
return NewAdvancedFeaturesValueUnknown(), diags
|
||||
}
|
||||
|
||||
cloudInitVal, ok := cloudInitAttribute.(basetypes.BoolValue)
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Wrong Type",
|
||||
fmt.Sprintf(`cloud_init expected to be basetypes.BoolValue, was: %T`, cloudInitAttribute))
|
||||
}
|
||||
|
||||
driverDiskAttribute, ok := attributes["driver_disk"]
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Missing",
|
||||
`driver_disk is missing from object`)
|
||||
|
||||
return NewAdvancedFeaturesValueUnknown(), diags
|
||||
}
|
||||
|
||||
driverDiskVal, ok := driverDiskAttribute.(basetypes.BoolValue)
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Wrong Type",
|
||||
fmt.Sprintf(`driver_disk expected to be basetypes.BoolValue, was: %T`, driverDiskAttribute))
|
||||
}
|
||||
|
||||
emulatedDevicesAttribute, ok := attributes["emulated_devices"]
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Missing",
|
||||
`emulated_devices is missing from object`)
|
||||
|
||||
return NewAdvancedFeaturesValueUnknown(), diags
|
||||
}
|
||||
|
||||
emulatedDevicesVal, ok := emulatedDevicesAttribute.(basetypes.BoolValue)
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Wrong Type",
|
||||
fmt.Sprintf(`emulated_devices expected to be basetypes.BoolValue, was: %T`, emulatedDevicesAttribute))
|
||||
}
|
||||
|
||||
emulatedHypervAttribute, ok := attributes["emulated_hyperv"]
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Missing",
|
||||
`emulated_hyperv is missing from object`)
|
||||
|
||||
return NewAdvancedFeaturesValueUnknown(), diags
|
||||
}
|
||||
|
||||
emulatedHypervVal, ok := emulatedHypervAttribute.(basetypes.BoolValue)
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Wrong Type",
|
||||
fmt.Sprintf(`emulated_hyperv expected to be basetypes.BoolValue, was: %T`, emulatedHypervAttribute))
|
||||
}
|
||||
|
||||
emulatedTpmAttribute, ok := attributes["emulated_tpm"]
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Missing",
|
||||
`emulated_tpm is missing from object`)
|
||||
|
||||
return NewAdvancedFeaturesValueUnknown(), diags
|
||||
}
|
||||
|
||||
emulatedTpmVal, ok := emulatedTpmAttribute.(basetypes.BoolValue)
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Wrong Type",
|
||||
fmt.Sprintf(`emulated_tpm expected to be basetypes.BoolValue, was: %T`, emulatedTpmAttribute))
|
||||
}
|
||||
|
||||
localRtcAttribute, ok := attributes["local_rtc"]
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Missing",
|
||||
`local_rtc is missing from object`)
|
||||
|
||||
return NewAdvancedFeaturesValueUnknown(), diags
|
||||
}
|
||||
|
||||
localRtcVal, ok := localRtcAttribute.(basetypes.BoolValue)
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Wrong Type",
|
||||
fmt.Sprintf(`local_rtc expected to be basetypes.BoolValue, was: %T`, localRtcAttribute))
|
||||
}
|
||||
|
||||
nestedVirtAttribute, ok := attributes["nested_virt"]
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Missing",
|
||||
`nested_virt is missing from object`)
|
||||
|
||||
return NewAdvancedFeaturesValueUnknown(), diags
|
||||
}
|
||||
|
||||
nestedVirtVal, ok := nestedVirtAttribute.(basetypes.BoolValue)
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Wrong Type",
|
||||
fmt.Sprintf(`nested_virt expected to be basetypes.BoolValue, was: %T`, nestedVirtAttribute))
|
||||
}
|
||||
|
||||
qemuGuestAgentAttribute, ok := attributes["qemu_guest_agent"]
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Missing",
|
||||
`qemu_guest_agent is missing from object`)
|
||||
|
||||
return NewAdvancedFeaturesValueUnknown(), diags
|
||||
}
|
||||
|
||||
qemuGuestAgentVal, ok := qemuGuestAgentAttribute.(basetypes.BoolValue)
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Wrong Type",
|
||||
fmt.Sprintf(`qemu_guest_agent expected to be basetypes.BoolValue, was: %T`, qemuGuestAgentAttribute))
|
||||
}
|
||||
|
||||
uefiBootAttribute, ok := attributes["uefi_boot"]
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Missing",
|
||||
`uefi_boot is missing from object`)
|
||||
|
||||
return NewAdvancedFeaturesValueUnknown(), diags
|
||||
}
|
||||
|
||||
uefiBootVal, ok := uefiBootAttribute.(basetypes.BoolValue)
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Wrong Type",
|
||||
fmt.Sprintf(`uefi_boot expected to be basetypes.BoolValue, was: %T`, uefiBootAttribute))
|
||||
}
|
||||
|
||||
unsetUuidAttribute, ok := attributes["unset_uuid"]
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Missing",
|
||||
`unset_uuid is missing from object`)
|
||||
|
||||
return NewAdvancedFeaturesValueUnknown(), diags
|
||||
}
|
||||
|
||||
unsetUuidVal, ok := unsetUuidAttribute.(basetypes.BoolValue)
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Wrong Type",
|
||||
fmt.Sprintf(`unset_uuid expected to be basetypes.BoolValue, was: %T`, unsetUuidAttribute))
|
||||
}
|
||||
|
||||
if diags.HasError() {
|
||||
return NewAdvancedFeaturesValueUnknown(), diags
|
||||
}
|
||||
|
||||
return AdvancedFeaturesValue{
|
||||
CloudInit: cloudInitVal,
|
||||
DriverDisk: driverDiskVal,
|
||||
EmulatedDevices: emulatedDevicesVal,
|
||||
EmulatedHyperv: emulatedHypervVal,
|
||||
EmulatedTpm: emulatedTpmVal,
|
||||
LocalRtc: localRtcVal,
|
||||
NestedVirt: nestedVirtVal,
|
||||
QemuGuestAgent: qemuGuestAgentVal,
|
||||
UefiBoot: uefiBootVal,
|
||||
UnsetUuid: unsetUuidVal,
|
||||
state: attr.ValueStateKnown,
|
||||
}, diags
|
||||
}
|
||||
|
||||
func NewAdvancedFeaturesValueMust(attributeTypes map[string]attr.Type, attributes map[string]attr.Value) AdvancedFeaturesValue {
|
||||
object, diags := NewAdvancedFeaturesValue(attributeTypes, attributes)
|
||||
|
||||
if diags.HasError() {
|
||||
// This could potentially be added to the diag package.
|
||||
diagsStrings := make([]string, 0, len(diags))
|
||||
|
||||
for _, diagnostic := range diags {
|
||||
diagsStrings = append(diagsStrings, fmt.Sprintf(
|
||||
"%s | %s | %s",
|
||||
diagnostic.Severity(),
|
||||
diagnostic.Summary(),
|
||||
diagnostic.Detail()))
|
||||
}
|
||||
|
||||
panic("NewAdvancedFeaturesValueMust received error(s): " + strings.Join(diagsStrings, "\n"))
|
||||
}
|
||||
|
||||
return object
|
||||
}
|
||||
|
||||
func (t AdvancedFeaturesType) ValueFromTerraform(ctx context.Context, in tftypes.Value) (attr.Value, error) {
|
||||
if in.Type() == nil {
|
||||
return NewAdvancedFeaturesValueNull(), nil
|
||||
}
|
||||
|
||||
if !in.Type().Equal(t.TerraformType(ctx)) {
|
||||
return nil, fmt.Errorf("expected %s, got %s", t.TerraformType(ctx), in.Type())
|
||||
}
|
||||
|
||||
if !in.IsKnown() {
|
||||
return NewAdvancedFeaturesValueUnknown(), nil
|
||||
}
|
||||
|
||||
if in.IsNull() {
|
||||
return NewAdvancedFeaturesValueNull(), nil
|
||||
}
|
||||
|
||||
attributes := map[string]attr.Value{}
|
||||
|
||||
val := map[string]tftypes.Value{}
|
||||
|
||||
err := in.As(&val)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for k, v := range val {
|
||||
a, err := t.AttrTypes[k].ValueFromTerraform(ctx, v)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
attributes[k] = a
|
||||
}
|
||||
|
||||
return NewAdvancedFeaturesValueMust(AdvancedFeaturesValue{}.AttributeTypes(ctx), attributes), nil
|
||||
}
|
||||
|
||||
func (t AdvancedFeaturesType) ValueType(ctx context.Context) attr.Value {
|
||||
return AdvancedFeaturesValue{}
|
||||
}
|
||||
|
||||
var _ basetypes.ObjectValuable = AdvancedFeaturesValue{}
|
||||
|
||||
type AdvancedFeaturesValue struct {
|
||||
CloudInit basetypes.BoolValue `tfsdk:"cloud_init"`
|
||||
DriverDisk basetypes.BoolValue `tfsdk:"driver_disk"`
|
||||
EmulatedDevices basetypes.BoolValue `tfsdk:"emulated_devices"`
|
||||
EmulatedHyperv basetypes.BoolValue `tfsdk:"emulated_hyperv"`
|
||||
EmulatedTpm basetypes.BoolValue `tfsdk:"emulated_tpm"`
|
||||
LocalRtc basetypes.BoolValue `tfsdk:"local_rtc"`
|
||||
NestedVirt basetypes.BoolValue `tfsdk:"nested_virt"`
|
||||
QemuGuestAgent basetypes.BoolValue `tfsdk:"qemu_guest_agent"`
|
||||
UefiBoot basetypes.BoolValue `tfsdk:"uefi_boot"`
|
||||
UnsetUuid basetypes.BoolValue `tfsdk:"unset_uuid"`
|
||||
state attr.ValueState
|
||||
}
|
||||
|
||||
func (v AdvancedFeaturesValue) ToTerraformValue(ctx context.Context) (tftypes.Value, error) {
|
||||
attrTypes := make(map[string]tftypes.Type, 10)
|
||||
|
||||
var val tftypes.Value
|
||||
var err error
|
||||
|
||||
attrTypes["cloud_init"] = basetypes.BoolType{}.TerraformType(ctx)
|
||||
attrTypes["driver_disk"] = basetypes.BoolType{}.TerraformType(ctx)
|
||||
attrTypes["emulated_devices"] = basetypes.BoolType{}.TerraformType(ctx)
|
||||
attrTypes["emulated_hyperv"] = basetypes.BoolType{}.TerraformType(ctx)
|
||||
attrTypes["emulated_tpm"] = basetypes.BoolType{}.TerraformType(ctx)
|
||||
attrTypes["local_rtc"] = basetypes.BoolType{}.TerraformType(ctx)
|
||||
attrTypes["nested_virt"] = basetypes.BoolType{}.TerraformType(ctx)
|
||||
attrTypes["qemu_guest_agent"] = basetypes.BoolType{}.TerraformType(ctx)
|
||||
attrTypes["uefi_boot"] = basetypes.BoolType{}.TerraformType(ctx)
|
||||
attrTypes["unset_uuid"] = basetypes.BoolType{}.TerraformType(ctx)
|
||||
|
||||
objectType := tftypes.Object{AttributeTypes: attrTypes}
|
||||
|
||||
switch v.state {
|
||||
case attr.ValueStateKnown:
|
||||
vals := make(map[string]tftypes.Value, 10)
|
||||
|
||||
val, err = v.CloudInit.ToTerraformValue(ctx)
|
||||
|
||||
if err != nil {
|
||||
return tftypes.NewValue(objectType, tftypes.UnknownValue), err
|
||||
}
|
||||
|
||||
vals["cloud_init"] = val
|
||||
|
||||
val, err = v.DriverDisk.ToTerraformValue(ctx)
|
||||
|
||||
if err != nil {
|
||||
return tftypes.NewValue(objectType, tftypes.UnknownValue), err
|
||||
}
|
||||
|
||||
vals["driver_disk"] = val
|
||||
|
||||
val, err = v.EmulatedDevices.ToTerraformValue(ctx)
|
||||
|
||||
if err != nil {
|
||||
return tftypes.NewValue(objectType, tftypes.UnknownValue), err
|
||||
}
|
||||
|
||||
vals["emulated_devices"] = val
|
||||
|
||||
val, err = v.EmulatedHyperv.ToTerraformValue(ctx)
|
||||
|
||||
if err != nil {
|
||||
return tftypes.NewValue(objectType, tftypes.UnknownValue), err
|
||||
}
|
||||
|
||||
vals["emulated_hyperv"] = val
|
||||
|
||||
val, err = v.EmulatedTpm.ToTerraformValue(ctx)
|
||||
|
||||
if err != nil {
|
||||
return tftypes.NewValue(objectType, tftypes.UnknownValue), err
|
||||
}
|
||||
|
||||
vals["emulated_tpm"] = val
|
||||
|
||||
val, err = v.LocalRtc.ToTerraformValue(ctx)
|
||||
|
||||
if err != nil {
|
||||
return tftypes.NewValue(objectType, tftypes.UnknownValue), err
|
||||
}
|
||||
|
||||
vals["local_rtc"] = val
|
||||
|
||||
val, err = v.NestedVirt.ToTerraformValue(ctx)
|
||||
|
||||
if err != nil {
|
||||
return tftypes.NewValue(objectType, tftypes.UnknownValue), err
|
||||
}
|
||||
|
||||
vals["nested_virt"] = val
|
||||
|
||||
val, err = v.QemuGuestAgent.ToTerraformValue(ctx)
|
||||
|
||||
if err != nil {
|
||||
return tftypes.NewValue(objectType, tftypes.UnknownValue), err
|
||||
}
|
||||
|
||||
vals["qemu_guest_agent"] = val
|
||||
|
||||
val, err = v.UefiBoot.ToTerraformValue(ctx)
|
||||
|
||||
if err != nil {
|
||||
return tftypes.NewValue(objectType, tftypes.UnknownValue), err
|
||||
}
|
||||
|
||||
vals["uefi_boot"] = val
|
||||
|
||||
val, err = v.UnsetUuid.ToTerraformValue(ctx)
|
||||
|
||||
if err != nil {
|
||||
return tftypes.NewValue(objectType, tftypes.UnknownValue), err
|
||||
}
|
||||
|
||||
vals["unset_uuid"] = val
|
||||
|
||||
if err := tftypes.ValidateValue(objectType, vals); err != nil {
|
||||
return tftypes.NewValue(objectType, tftypes.UnknownValue), err
|
||||
}
|
||||
|
||||
return tftypes.NewValue(objectType, vals), nil
|
||||
case attr.ValueStateNull:
|
||||
return tftypes.NewValue(objectType, nil), nil
|
||||
case attr.ValueStateUnknown:
|
||||
return tftypes.NewValue(objectType, tftypes.UnknownValue), nil
|
||||
default:
|
||||
panic(fmt.Sprintf("unhandled Object state in ToTerraformValue: %s", v.state))
|
||||
}
|
||||
}
|
||||
|
||||
func (v AdvancedFeaturesValue) IsNull() bool {
|
||||
return v.state == attr.ValueStateNull
|
||||
}
|
||||
|
||||
func (v AdvancedFeaturesValue) IsUnknown() bool {
|
||||
return v.state == attr.ValueStateUnknown
|
||||
}
|
||||
|
||||
func (v AdvancedFeaturesValue) String() string {
|
||||
return "AdvancedFeaturesValue"
|
||||
}
|
||||
|
||||
func (v AdvancedFeaturesValue) ToObjectValue(ctx context.Context) (basetypes.ObjectValue, diag.Diagnostics) {
|
||||
var diags diag.Diagnostics
|
||||
|
||||
attributeTypes := map[string]attr.Type{
|
||||
"cloud_init": basetypes.BoolType{},
|
||||
"driver_disk": basetypes.BoolType{},
|
||||
"emulated_devices": basetypes.BoolType{},
|
||||
"emulated_hyperv": basetypes.BoolType{},
|
||||
"emulated_tpm": basetypes.BoolType{},
|
||||
"local_rtc": basetypes.BoolType{},
|
||||
"nested_virt": basetypes.BoolType{},
|
||||
"qemu_guest_agent": basetypes.BoolType{},
|
||||
"uefi_boot": basetypes.BoolType{},
|
||||
"unset_uuid": basetypes.BoolType{},
|
||||
}
|
||||
|
||||
if v.IsNull() {
|
||||
return types.ObjectNull(attributeTypes), diags
|
||||
}
|
||||
|
||||
if v.IsUnknown() {
|
||||
return types.ObjectUnknown(attributeTypes), diags
|
||||
}
|
||||
|
||||
objVal, diags := types.ObjectValue(
|
||||
attributeTypes,
|
||||
map[string]attr.Value{
|
||||
"cloud_init": v.CloudInit,
|
||||
"driver_disk": v.DriverDisk,
|
||||
"emulated_devices": v.EmulatedDevices,
|
||||
"emulated_hyperv": v.EmulatedHyperv,
|
||||
"emulated_tpm": v.EmulatedTpm,
|
||||
"local_rtc": v.LocalRtc,
|
||||
"nested_virt": v.NestedVirt,
|
||||
"qemu_guest_agent": v.QemuGuestAgent,
|
||||
"uefi_boot": v.UefiBoot,
|
||||
"unset_uuid": v.UnsetUuid,
|
||||
})
|
||||
|
||||
return objVal, diags
|
||||
}
|
||||
|
||||
func (v AdvancedFeaturesValue) Equal(o attr.Value) bool {
|
||||
other, ok := o.(AdvancedFeaturesValue)
|
||||
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
if v.state != other.state {
|
||||
return false
|
||||
}
|
||||
|
||||
if v.state != attr.ValueStateKnown {
|
||||
return true
|
||||
}
|
||||
|
||||
if !v.CloudInit.Equal(other.CloudInit) {
|
||||
return false
|
||||
}
|
||||
|
||||
if !v.DriverDisk.Equal(other.DriverDisk) {
|
||||
return false
|
||||
}
|
||||
|
||||
if !v.EmulatedDevices.Equal(other.EmulatedDevices) {
|
||||
return false
|
||||
}
|
||||
|
||||
if !v.EmulatedHyperv.Equal(other.EmulatedHyperv) {
|
||||
return false
|
||||
}
|
||||
|
||||
if !v.EmulatedTpm.Equal(other.EmulatedTpm) {
|
||||
return false
|
||||
}
|
||||
|
||||
if !v.LocalRtc.Equal(other.LocalRtc) {
|
||||
return false
|
||||
}
|
||||
|
||||
if !v.NestedVirt.Equal(other.NestedVirt) {
|
||||
return false
|
||||
}
|
||||
|
||||
if !v.QemuGuestAgent.Equal(other.QemuGuestAgent) {
|
||||
return false
|
||||
}
|
||||
|
||||
if !v.UefiBoot.Equal(other.UefiBoot) {
|
||||
return false
|
||||
}
|
||||
|
||||
if !v.UnsetUuid.Equal(other.UnsetUuid) {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (v AdvancedFeaturesValue) Type(ctx context.Context) attr.Type {
|
||||
return AdvancedFeaturesType{
|
||||
basetypes.ObjectType{
|
||||
AttrTypes: v.AttributeTypes(ctx),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (v AdvancedFeaturesValue) AttributeTypes(ctx context.Context) map[string]attr.Type {
|
||||
return map[string]attr.Type{
|
||||
"cloud_init": basetypes.BoolType{},
|
||||
"driver_disk": basetypes.BoolType{},
|
||||
"emulated_devices": basetypes.BoolType{},
|
||||
"emulated_hyperv": basetypes.BoolType{},
|
||||
"emulated_tpm": basetypes.BoolType{},
|
||||
"local_rtc": basetypes.BoolType{},
|
||||
"nested_virt": basetypes.BoolType{},
|
||||
"qemu_guest_agent": basetypes.BoolType{},
|
||||
"uefi_boot": basetypes.BoolType{},
|
||||
"unset_uuid": basetypes.BoolType{},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,21 +34,12 @@ func SshKeyResourceSchema(ctx context.Context) schema.Schema {
|
||||
stringvalidator.LengthAtLeast(1),
|
||||
},
|
||||
},
|
||||
"public_key": schema.StringAttribute{
|
||||
Required: true,
|
||||
Description: "The public key in OpenSSH \"authorized_keys\" format.",
|
||||
MarkdownDescription: "The public key in OpenSSH \"authorized_keys\" format.",
|
||||
Validators: []validator.String{
|
||||
stringvalidator.LengthAtLeast(1),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type SshKeyModel struct {
|
||||
Default types.Bool `tfsdk:"default"`
|
||||
Id types.Int64 `tfsdk:"id"`
|
||||
Name types.String `tfsdk:"name"`
|
||||
PublicKey types.String `tfsdk:"public_key"`
|
||||
Default types.Bool `tfsdk:"default"`
|
||||
Id types.Int64 `tfsdk:"id"`
|
||||
Name types.String `tfsdk:"name"`
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"openapi": "3.0.1",
|
||||
"openapi": "3.0.4",
|
||||
"info": {
|
||||
"title": "BinaryLane API",
|
||||
"description": "\n\n# Introduction\n\nThis API is used by BinaryLane's 'mPanel' website, so you'll find everything you need here to automate your use of BinaryLane or develop tools for others. You could even build your own version of 'mPanel' if you wanted!\n\n\n## Getting Started Guide\n\nWe are working on a complete 'Getting Started' guide as well as this introductory section.\n\n\n# Developer Preview Notes\n\n**Warning: this specification is currently in active development.** Until this warning is removed breaking changes are possible without the version changing.\nHowever, this API is relatively mature and we are actively developing a new website and other tools against this API so breaking changes should be rare at this point.\n\nWe currently have a CLI (command line interface) tool in development and are in the early stage of planning other tools.\n\nWe welcome all feedback from API users at the support email address above.\n\n\n## Active Development Status\n\nThis is the list of BinaryLane features that are not yet available through the API but are currently under active development.\nIf you need an ETA on when these will be available please contact support.\n\n- Domains\n\n\n## Future Development Status\n\nThis is the list of BinaryLane features that are not yet available through the API and are not currently in active development. This list is in a rough order of priority.\nIf you need an ETA or want to ask for increased priority on any of these please contact support, we are happy to hear any feedback on this.\n\n- Account Updates\n- Payments\n\n\n\n# API Tools\n\nThis section will include links to tools to assist with consuming this API. We have a CLI tool and a GO library in active development, and are planning libraries for other languages.\n\n\n# Version Information\n\nThis section will contain a link to our changelog once the developer preview period is complete.\n\n",
|
||||
@@ -8,7 +8,7 @@
|
||||
"url": "https://support.binarylane.com.au",
|
||||
"email": "support@binarylane.com.au"
|
||||
},
|
||||
"version": "0.29.0",
|
||||
"version": "0.33.0",
|
||||
"x-logo": {
|
||||
"url": "https://www.binarylane.com.au/res/images/binarylane/logo.png",
|
||||
"backgroundColor": "#000000",
|
||||
@@ -466,6 +466,19 @@
|
||||
],
|
||||
"summary": "Refresh Cached Nameserver Domain Records",
|
||||
"description": "The nameservers for domains are cached. If you have recently altered the nameservers for a managed domain you may need to refresh the cached domain records.",
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/DomainRefreshRequest"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"204": {
|
||||
"description": "No Content"
|
||||
@@ -779,8 +792,7 @@
|
||||
{
|
||||
"$ref": "#/components/schemas/DomainRecordRequest"
|
||||
}
|
||||
],
|
||||
"description": "If this is used to update an existing DomainRecord any values not provided will be retained. Provide empty strings to clear existing string values, nulls to retain the existing values."
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -901,10 +913,10 @@
|
||||
"schema": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/DomainRecordRequest"
|
||||
"$ref": "#/components/schemas/UpdateDomainRecordRequest"
|
||||
}
|
||||
],
|
||||
"description": "If this is used to update an existing DomainRecord any values not provided will be retained. Provide empty strings to clear existing string values, nulls to retain the existing values."
|
||||
"description": "Any values not provided will be retained. Provide empty strings to clear existing string values, nulls to retain the existing values."
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5897,6 +5909,7 @@
|
||||
"schemas": {
|
||||
"Account": {
|
||||
"required": [
|
||||
"additional_ipv4_limit",
|
||||
"configured_payment_methods",
|
||||
"email",
|
||||
"email_verified",
|
||||
@@ -5947,6 +5960,12 @@
|
||||
},
|
||||
"description": "The payment methods that are configured (available) for this account.",
|
||||
"readOnly": true
|
||||
},
|
||||
"additional_ipv4_limit": {
|
||||
"type": "integer",
|
||||
"description": "The maximum additional IPv4 addresses this account may assign across all servers. You may contact support to request this limit be increased.",
|
||||
"format": "int32",
|
||||
"readOnly": true
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -6036,7 +6055,7 @@
|
||||
"$ref": "#/components/schemas/ResourceType"
|
||||
}
|
||||
],
|
||||
"description": "The resource type (if any) associated with this action.",
|
||||
"description": "The resource type (if any) associated with this action.\n\n| Value | Description |\n| ----- | ----------- |\n| server | Server |\n| load-balancer | Load Balancer |\n| ssh-key | SSH Key |\n| vpc | Virtual Private Network |\n| image | Backup or Operating System Image |\n| registered-domain-name | Registered Domain Name |\n\n",
|
||||
"nullable": true,
|
||||
"readOnly": true
|
||||
},
|
||||
@@ -6266,18 +6285,6 @@
|
||||
"description": "Create an Additional Disk for a Server"
|
||||
},
|
||||
"AdvancedFeature": {
|
||||
"enum": [
|
||||
"emulated-hyperv",
|
||||
"emulated-devices",
|
||||
"nested-virt",
|
||||
"driver-disk",
|
||||
"unset-uuid",
|
||||
"local-rtc",
|
||||
"emulated-tpm",
|
||||
"cloud-init",
|
||||
"qemu-guest-agent",
|
||||
"uefi-boot"
|
||||
],
|
||||
"type": "string",
|
||||
"description": "\n| Value | Description |\n| ----- | ----------- |\n| emulated-hyperv | Enable HyperV (a hypervisor produced by Microsoft) support. Enabled by default on Windows servers, generally of no value for non-Windows servers. |\n| emulated-devices | When emulated devices is enabled, the KVM specific \"VirtIO\" disk drive and network devices are removed, and replaced with emulated versions of physical hardware: an old IDE HDD and an Intel E1000 network card. Emulated devices are much slower than the VirtIO devices, and so this option should not be enabled unless absolutely necessary. |\n| nested-virt | When this option is enabled the functionality necessary to run your own KVM servers within your server is enabled. Note that all the networking limits - one MAC address per VPS, restricted to specific IPs - still apply to public cloud so this is feature is generally only useful in combination with Virtual Private Cloud. |\n| driver-disk | When this option is enabled a copy of the KVM driver disc for Windows (\"virtio-win.iso\") will be attached to your server as a virtual CD. This option can also be used in combination with your own attached backup when installing Windows. |\n| unset-uuid | When this option is NOT enabled a 128-bit unique identifier is exposed to your server through the virtual BIOS. Each server receives a different UUID. Some propriety licensed software utilise this identifier to \"tie\" the license to a specific server. |\n| local-rtc | When a server is booted the virtual BIOS receives the current date and time from the host node. The BIOS does not have an explicit timezone, so the timezone used is implicit and must be understood by the operating system. Most operating systems other than Windows expect the time to be UTC since it allows the operating system to control the timezone used when displaying the time. Our Windows installations have also been customized to use UTC, but when using your own installation of Windows this should be set to the host node's local timezone. |\n| emulated-tpm | When enabled this provides an emulated TPM v1.2 device to your Cloud Server. Warning: the TPM state is not backed up. |\n| cloud-init | (Read-Only) When this option is enabled the Cloud Server will be provided a datasource for the cloud-init service. |\n| qemu-guest-agent | (Read-Only) When this option is enabled the server will allow QEMU Guest Agent to perform password reset without rebooting. |\n| uefi-boot | (Read-Only) When this option is enabled the Cloud Server will use UEFI instead of legacy PC BIOS. |\n\n",
|
||||
"x-enum-descriptions": [
|
||||
@@ -6303,7 +6310,6 @@
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"source_addresses": {
|
||||
"minItems": 1,
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
@@ -6315,7 +6321,6 @@
|
||||
}
|
||||
},
|
||||
"destination_addresses": {
|
||||
"minItems": 1,
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
@@ -6344,7 +6349,7 @@
|
||||
"$ref": "#/components/schemas/AdvancedFirewallRuleProtocol"
|
||||
}
|
||||
],
|
||||
"description": "The protocol to match for this rule.",
|
||||
"description": "The protocol to match for this rule.\n\n| Value | Description |\n| ----- | ----------- |\n| all | This rule will match any protocol. |\n| icmp | This rule will match ICMP traffic only. |\n| tcp | This rule will match TCP traffic only. |\n| udp | This rule will match UDP traffic only. |\n\n",
|
||||
"x-cli-format": 3,
|
||||
"x-oapi-codegen-extra-tags": {
|
||||
"tfsdk": "protocol"
|
||||
@@ -6356,15 +6361,13 @@
|
||||
"$ref": "#/components/schemas/AdvancedFirewallRuleAction"
|
||||
}
|
||||
],
|
||||
"description": "The action to take when there is a match on this rule.",
|
||||
"description": "The action to take when there is a match on this rule.\n\n| Value | Description |\n| ----- | ----------- |\n| drop | Traffic matching this rule will be dropped. |\n| accept | Traffic matching this rule will be accepted. |\n\n",
|
||||
"x-cli-format": 5,
|
||||
"x-oapi-codegen-extra-tags": {
|
||||
"tfsdk": "action"
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"maxLength": 250,
|
||||
"minLength": 0,
|
||||
"type": "string",
|
||||
"description": "A description to assist in identifying this rule. Commonly used to record the reason for the rule or the intent behind it, e.g. \"Block access to RDP\" or \"Allow access from HQ\".",
|
||||
"nullable": true,
|
||||
@@ -6403,6 +6406,82 @@
|
||||
"This rule will match UDP traffic only."
|
||||
]
|
||||
},
|
||||
"AdvancedFirewallRuleRequest": {
|
||||
"required": [
|
||||
"action",
|
||||
"destination_addresses",
|
||||
"protocol",
|
||||
"source_addresses"
|
||||
],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"source_addresses": {
|
||||
"minItems": 1,
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "The source addresses to match for this rule. Each address may be an individual IPv4 address or a range in IPv4 CIDR notation.",
|
||||
"x-oapi-codegen-extra-tags": {
|
||||
"tfsdk": "source_addresses"
|
||||
}
|
||||
},
|
||||
"destination_addresses": {
|
||||
"minItems": 1,
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "The destination addresses to match for this rule. Each address may be an individual IPv4 address or a range in IPv4 CIDR notation.",
|
||||
"x-oapi-codegen-extra-tags": {
|
||||
"tfsdk": "destination_addresses"
|
||||
}
|
||||
},
|
||||
"destination_ports": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "The destination ports to match for this rule. Leave null or empty to match on all ports.",
|
||||
"nullable": true,
|
||||
"x-oapi-codegen-extra-tags": {
|
||||
"tfsdk": "destination_ports"
|
||||
}
|
||||
},
|
||||
"protocol": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/AdvancedFirewallRuleProtocol"
|
||||
}
|
||||
],
|
||||
"description": "The protocol to match for this rule.\n\n| Value | Description |\n| ----- | ----------- |\n| all | This rule will match any protocol. |\n| icmp | This rule will match ICMP traffic only. |\n| tcp | This rule will match TCP traffic only. |\n| udp | This rule will match UDP traffic only. |\n\n",
|
||||
"x-oapi-codegen-extra-tags": {
|
||||
"tfsdk": "protocol"
|
||||
}
|
||||
},
|
||||
"action": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/AdvancedFirewallRuleAction"
|
||||
}
|
||||
],
|
||||
"description": "The action to take when there is a match on this rule.\n\n| Value | Description |\n| ----- | ----------- |\n| drop | Traffic matching this rule will be dropped. |\n| accept | Traffic matching this rule will be accepted. |\n\n",
|
||||
"x-oapi-codegen-extra-tags": {
|
||||
"tfsdk": "action"
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"maxLength": 250,
|
||||
"minLength": 0,
|
||||
"type": "string",
|
||||
"description": "A description to assist in identifying this rule. Commonly used to record the reason for the rule or the intent behind it, e.g. \"Block access to RDP\" or \"Allow access from HQ\".",
|
||||
"nullable": true,
|
||||
"x-oapi-codegen-extra-tags": {
|
||||
"tfsdk": "description"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"AdvancedFirewallRulesResponse": {
|
||||
"required": [
|
||||
"firewall_rules"
|
||||
@@ -6438,7 +6517,7 @@
|
||||
"$ref": "#/components/schemas/VmMachineType"
|
||||
}
|
||||
],
|
||||
"description": "The machine_type (corresponding to a KVM version) used for this server.\nA null value indicates automatic selection of the best KVM machine type supported by the host node.",
|
||||
"description": "The machine_type (corresponding to a KVM version) used for this server.\nA null value indicates automatic selection of the best KVM machine type supported by the host node.\n\n| Value | Description |\n| ----- | ----------- |\n| pc_i440fx_1point5 | PC i440FX 1.5 |\n| pc_i440fx_2point11 | PC i440FX 2.11 |\n| pc_i440fx_4point1 | PC i440FX 4.1 |\n| pc_i440fx_4point2 | PC i440FX 4.2 |\n| pc_i440fx_5point0 | PC i440FX 5.0 |\n| pc_i440fx_5point1 | PC i440FX 5.1 |\n| pc_i440fx_7point2 | PC i440FX 7.2 |\n| pc_i440fx_8point2 | PC i440FX 8.2 |\n\n",
|
||||
"nullable": true,
|
||||
"readOnly": true
|
||||
},
|
||||
@@ -6454,7 +6533,7 @@
|
||||
"enabled_advanced_features": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/AdvancedFeature"
|
||||
"type": "string"
|
||||
},
|
||||
"description": "A list of the currently enabled advanced features for this server.",
|
||||
"readOnly": true
|
||||
@@ -6547,7 +6626,7 @@
|
||||
"advanced_features": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/AdvancedFeature"
|
||||
"type": "string"
|
||||
},
|
||||
"description": "A list of the advanced features available for this server.",
|
||||
"readOnly": true
|
||||
@@ -6846,7 +6925,7 @@
|
||||
"enabled_advanced_features": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/AdvancedFeature"
|
||||
"type": "string"
|
||||
},
|
||||
"description": "Do not provide or set to null to keep existing advanced features. Provide an empty array to disable all advanced features, otherwise provide an array with selected advanced features. If provided, any currently enabled advanced features that aren't included will be disabled.",
|
||||
"nullable": true
|
||||
@@ -6868,7 +6947,7 @@
|
||||
"$ref": "#/components/schemas/VmMachineType"
|
||||
}
|
||||
],
|
||||
"description": "Do not provide or set to null to keep existing machine type.",
|
||||
"description": "Do not provide or set to null to keep existing machine type.\n\n| Value | Description |\n| ----- | ----------- |\n| pc_i440fx_1point5 | PC i440FX 1.5 |\n| pc_i440fx_2point11 | PC i440FX 2.11 |\n| pc_i440fx_4point1 | PC i440FX 4.1 |\n| pc_i440fx_4point2 | PC i440FX 4.2 |\n| pc_i440fx_5point0 | PC i440FX 5.0 |\n| pc_i440fx_5point1 | PC i440FX 5.1 |\n| pc_i440fx_7point2 | PC i440FX 7.2 |\n| pc_i440fx_8point2 | PC i440FX 8.2 |\n\n",
|
||||
"nullable": true
|
||||
},
|
||||
"automatic_machine_type": {
|
||||
@@ -6882,7 +6961,7 @@
|
||||
"$ref": "#/components/schemas/VideoDevice"
|
||||
}
|
||||
],
|
||||
"description": "Do not provide or set to null to keep existing video device.",
|
||||
"description": "Do not provide or set to null to keep existing video device.\n\n| Value | Description |\n| ----- | ----------- |\n| cirrus-logic | Cirrus Logic GD5446 |\n| standard | Standard VGA with VESA 2.0 extensions |\n| virtio | Virtio VGA (800x600) |\n| virtio-wide | Virtio VGA (1600x900) |\n\n",
|
||||
"nullable": true
|
||||
}
|
||||
},
|
||||
@@ -6905,7 +6984,7 @@
|
||||
"firewall_rules": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/AdvancedFirewallRule"
|
||||
"$ref": "#/components/schemas/AdvancedFirewallRuleRequest"
|
||||
},
|
||||
"description": "A list of rules for the server. NB: that any existing rules that are not included will be removed. Submit an empty list to clear all rules."
|
||||
}
|
||||
@@ -7511,7 +7590,7 @@
|
||||
"forwarding_rules": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/ForwardingRule"
|
||||
"$ref": "#/components/schemas/ForwardingRuleRequest"
|
||||
},
|
||||
"description": "The rules that control which traffic the load balancer will forward to servers in the pool. Leave null to accept a default \"HTTP\" only forwarding rule.",
|
||||
"nullable": true,
|
||||
@@ -7522,7 +7601,7 @@
|
||||
"health_check": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/HealthCheck"
|
||||
"$ref": "#/components/schemas/HealthCheckRequest"
|
||||
}
|
||||
],
|
||||
"description": "The rules that determine which servers are considered 'healthy' and in the server pool for the load balancer. Leave this null to accept appropriate defaults based on the forwarding_rules.",
|
||||
@@ -8184,6 +8263,11 @@
|
||||
}
|
||||
},
|
||||
"DomainRecordRequest": {
|
||||
"required": [
|
||||
"data",
|
||||
"name",
|
||||
"type"
|
||||
],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
@@ -8192,18 +8276,17 @@
|
||||
"$ref": "#/components/schemas/DomainRecordType"
|
||||
}
|
||||
],
|
||||
"description": "The type of the DNS record.",
|
||||
"nullable": true
|
||||
"description": "The type of the DNS record.\n\n| Value | Description |\n| ----- | ----------- |\n| A | Map an IPv4 address to a hostname. |\n| AAAA | Map an IPv6 address to a hostname. |\n| CAA | Restrict which certificate authorities are permitted to issue certificates for a domain. |\n| CNAME | Define an alias for your canonical hostname. |\n| MX | Define the mail exchanges that handle mail for the domain. |\n| NS | Define the nameservers that manage the domain. |\n| SOA | The Start of Authority record for the zone. |\n| SRV | Specify a server by hostname and port to handle a service or services. |\n| TXT | Define a string of text that is associated with a hostname. |\n\n"
|
||||
},
|
||||
"name": {
|
||||
"minLength": 1,
|
||||
"type": "string",
|
||||
"description": "The subdomain for this record. Use @ for records on the domain itself, and * to create a wildcard record.",
|
||||
"nullable": true
|
||||
"description": "The subdomain for this record. Use @ for records on the domain itself, and * to create a wildcard record."
|
||||
},
|
||||
"data": {
|
||||
"minLength": 1,
|
||||
"type": "string",
|
||||
"description": "A general data field that has different functions depending on the record type.",
|
||||
"nullable": true
|
||||
"description": "A general data field that has different functions depending on the record type."
|
||||
},
|
||||
"priority": {
|
||||
"maximum": 65535,
|
||||
@@ -8223,7 +8306,7 @@
|
||||
},
|
||||
"ttl": {
|
||||
"type": "integer",
|
||||
"description": "This value is the time to live for the record, in seconds.",
|
||||
"description": "This value is the time to live for the record, in seconds. The default and only supported value is 3600. Leave null to accept this default.",
|
||||
"format": "int32",
|
||||
"nullable": true
|
||||
},
|
||||
@@ -8251,8 +8334,7 @@
|
||||
"description": "A parameter tag that is only relevant for CAA records.",
|
||||
"nullable": true
|
||||
}
|
||||
},
|
||||
"description": "If this is used to update an existing DomainRecord any values not provided will be retained. Provide empty strings to clear existing string values, nulls to retain the existing values."
|
||||
}
|
||||
},
|
||||
"DomainRecordResponse": {
|
||||
"required": [
|
||||
@@ -8328,6 +8410,21 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"DomainRefreshRequest": {
|
||||
"required": [
|
||||
"domain_names"
|
||||
],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"domain_names": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "The domain names to refresh."
|
||||
}
|
||||
}
|
||||
},
|
||||
"DomainRequest": {
|
||||
"required": [
|
||||
"name"
|
||||
@@ -8445,6 +8542,25 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"ForwardingRuleRequest": {
|
||||
"required": [
|
||||
"entry_protocol"
|
||||
],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"entry_protocol": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/LoadBalancerRuleProtocol"
|
||||
}
|
||||
],
|
||||
"description": "The protocol that traffic must match for this load balancer to forward traffic according to this rule.\n\n| Value | Description |\n| ----- | ----------- |\n| http | The load balancer will forward HTTP traffic that matches this rule. |\n| https | The load balancer will forward HTTPS traffic that matches this rule. |\n\n",
|
||||
"x-oapi-codegen-extra-tags": {
|
||||
"tfsdk": "entry_protocol"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"ForwardingRulesRequest": {
|
||||
"required": [
|
||||
"forwarding_rules"
|
||||
@@ -8454,13 +8570,17 @@
|
||||
"forwarding_rules": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/ForwardingRule"
|
||||
"$ref": "#/components/schemas/ForwardingRuleRequest"
|
||||
},
|
||||
"description": "The rules that control which traffic the load balancer will forward to servers in the pool."
|
||||
}
|
||||
}
|
||||
},
|
||||
"HealthCheck": {
|
||||
"required": [
|
||||
"path",
|
||||
"protocol"
|
||||
],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"protocol": {
|
||||
@@ -8469,14 +8589,12 @@
|
||||
"$ref": "#/components/schemas/HealthCheckProtocol"
|
||||
}
|
||||
],
|
||||
"description": "Leave null to accept the default HTTP protocol.",
|
||||
"nullable": true
|
||||
"description": "The protocol used for the health check.\n\n| Value | Description |\n| ----- | ----------- |\n| http | The health check will be performed via HTTP. |\n| https | The health check will be performed via HTTPS. |\n| both | The health check will be performed via both HTTP and HTTPS. Failing a health check on one protocol will remove the server from the pool of servers only for that protocol. |\n\n"
|
||||
},
|
||||
"path": {
|
||||
"pattern": "/[A-Za-z0-9/.?=&+%_-]*",
|
||||
"minLength": 1,
|
||||
"type": "string",
|
||||
"description": "Leave null to accept the default '/' path.",
|
||||
"nullable": true
|
||||
"description": "The path to the health check endpoint."
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -8489,6 +8607,26 @@
|
||||
"The health check will be performed via both HTTP and HTTPS. Failing a health check on one protocol will remove the server from the pool of servers only for that protocol."
|
||||
]
|
||||
},
|
||||
"HealthCheckRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"protocol": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/HealthCheckProtocol"
|
||||
}
|
||||
],
|
||||
"description": "Leave null to accept the default HTTP protocol.\n\n| Value | Description |\n| ----- | ----------- |\n| http | The health check will be performed via HTTP. |\n| https | The health check will be performed via HTTPS. |\n| both | The health check will be performed via both HTTP and HTTPS. Failing a health check on one protocol will remove the server from the pool of servers only for that protocol. |\n\n",
|
||||
"nullable": true
|
||||
},
|
||||
"path": {
|
||||
"pattern": "/[A-Za-z0-9/.?=&+%_-]*",
|
||||
"type": "string",
|
||||
"description": "Leave null to accept the default '/' path.",
|
||||
"nullable": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"Host": {
|
||||
"required": [
|
||||
"display_name"
|
||||
@@ -8840,7 +8978,7 @@
|
||||
},
|
||||
"locked": {
|
||||
"type": "boolean",
|
||||
"description": "Optional: you may choose to lock an individual backup in which case we will not update that backup until you unlock it. Do not provide to leave the locked status unchanged.",
|
||||
"description": "Optional: you may choose to lock an individual backup in which case we will not update that backup until you unlock it. Do not provide to leave the locked status unchanged. You may not lock or unlock a temporary backup or a backup that is attached to a server.",
|
||||
"nullable": true
|
||||
}
|
||||
}
|
||||
@@ -9198,6 +9336,7 @@
|
||||
},
|
||||
"LicensedSoftware": {
|
||||
"required": [
|
||||
"incompatible",
|
||||
"licence_count",
|
||||
"software"
|
||||
],
|
||||
@@ -9215,6 +9354,10 @@
|
||||
"type": "integer",
|
||||
"description": "The current licence count for the software.",
|
||||
"format": "int32"
|
||||
},
|
||||
"incompatible": {
|
||||
"type": "boolean",
|
||||
"description": "Software that is incompatible with the server will be automatically removed at the next plan change.\nServers may have incompatible software due to changes made by support. Software is not incompatible merely because it is disabled;\ndisabled software may be retained by servers that already have it, incompatible software will be removed."
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -9283,21 +9426,18 @@
|
||||
"type": "integer",
|
||||
"description": "The ID of the load balancer.",
|
||||
"format": "int64",
|
||||
"readOnly": true,
|
||||
"x-cli-format": 1
|
||||
},
|
||||
"name": {
|
||||
"minLength": 1,
|
||||
"type": "string",
|
||||
"description": "The hostname of the load balancer.",
|
||||
"readOnly": true,
|
||||
"x-cli-format": 2
|
||||
},
|
||||
"ip": {
|
||||
"minLength": 1,
|
||||
"type": "string",
|
||||
"description": "The IPv4 address of the load balancer.",
|
||||
"readOnly": true,
|
||||
"x-cli-format": 4
|
||||
},
|
||||
"status": {
|
||||
@@ -9306,21 +9446,19 @@
|
||||
"$ref": "#/components/schemas/LoadBalancerStatus"
|
||||
}
|
||||
],
|
||||
"readOnly": true
|
||||
"description": "The current status of the load balancer.\n\n| Value | Description |\n| ----- | ----------- |\n| new | The load balancer is currently being built and is not ready to accept connections. |\n| active | The load balancer is available. |\n| errored | The load balancer is in an errored state. |\n\n"
|
||||
},
|
||||
"created_at": {
|
||||
"type": "string",
|
||||
"description": "The date and time in ISO8601 format of the creation of the load balancer.",
|
||||
"format": "date-time",
|
||||
"readOnly": true
|
||||
"format": "date-time"
|
||||
},
|
||||
"forwarding_rules": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/ForwardingRule"
|
||||
},
|
||||
"description": "The rules that control which traffic the load balancer will forward to servers in the pool.",
|
||||
"readOnly": true
|
||||
"description": "The rules that control which traffic the load balancer will forward to servers in the pool."
|
||||
},
|
||||
"health_check": {
|
||||
"allOf": [
|
||||
@@ -9329,7 +9467,6 @@
|
||||
}
|
||||
],
|
||||
"description": "The rules that determine which servers are considered 'healthy' and in the server pool for the load balancer.",
|
||||
"readOnly": true,
|
||||
"x-oapi-codegen-extra-tags": {
|
||||
"tfsdk": "health_check"
|
||||
}
|
||||
@@ -9342,7 +9479,6 @@
|
||||
],
|
||||
"description": "The region the load balancer is located in. If this value is null the load balancer is an 'AnyCast' load balancer.",
|
||||
"nullable": true,
|
||||
"readOnly": true,
|
||||
"x-cli-format": 3
|
||||
},
|
||||
"server_ids": {
|
||||
@@ -9351,8 +9487,7 @@
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"description": "The server IDs of the servers that are currently in the load balancer pool (regardless of their current 'health').",
|
||||
"readOnly": true
|
||||
"description": "The server IDs of the servers that are currently in the load balancer pool (regardless of their current 'health')."
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -9370,8 +9505,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"description": "The slugs of regions where this load balancer option is available. If this is an Anycast load balancer option this will be null.",
|
||||
"nullable": true,
|
||||
"readOnly": true
|
||||
"nullable": true
|
||||
},
|
||||
"anycast": {
|
||||
"type": "boolean",
|
||||
@@ -9381,8 +9515,7 @@
|
||||
"price_monthly": {
|
||||
"type": "number",
|
||||
"description": "Monthly Price in AU$.",
|
||||
"format": "double",
|
||||
"readOnly": true
|
||||
"format": "double"
|
||||
},
|
||||
"price_hourly": {
|
||||
"type": "number",
|
||||
@@ -10140,7 +10273,7 @@
|
||||
"$ref": "#/components/schemas/ChangeLicenses"
|
||||
}
|
||||
],
|
||||
"description": "This may be left null to keep the current licenses for the server. If this is provided any licenses that are not included will be removed.",
|
||||
"description": "This may be left null to keep the current licenses for the server. If this is provided any licenses that are not included will be removed. Any licences that are invalid will be removed regardless, see the documentation for `servers/{server_id}/software` for more information.",
|
||||
"nullable": true
|
||||
},
|
||||
"pre_action_backup": {
|
||||
@@ -11896,7 +12029,7 @@
|
||||
"$ref": "#/components/schemas/BackupSlot"
|
||||
}
|
||||
],
|
||||
"description": "If replacement_strategy is anything other than 'specified', this must be provided.",
|
||||
"description": "If replacement_strategy is anything other than 'specified', this must be provided.\n\n| Value | Description |\n| ----- | ----------- |\n| daily | A backup which is scheduled to be taken each day. |\n| weekly | A backup which is scheduled to be taken each week. |\n| monthly | A backup which is scheduled to be taken each month. |\n| temporary | A backup which is created on demand and only retained for a maximum of seven days. |\n\n",
|
||||
"nullable": true
|
||||
},
|
||||
"replacement_strategy": {
|
||||
@@ -11905,7 +12038,7 @@
|
||||
"$ref": "#/components/schemas/BackupReplacementStrategy"
|
||||
}
|
||||
],
|
||||
"description": "The strategy for selecting which backup to replace (if any)."
|
||||
"description": "The strategy for selecting which backup to replace (if any).\n\n| Value | Description |\n| ----- | ----------- |\n| none | Do not replace any existing backup: use a free slot of the provided backup type. If there are no free slots an error will occur. |\n| specified | Replace the specific backup id provided. |\n| oldest | Use any free slots of the provided backup type, and if there are no free slots replace the oldest unlocked and un-attached backup of the provided backup type. |\n| newest | Use any free slots of the provided backup type, and if there are no free slots replace the newest unlocked and un-attached backup of the provided backup type. |\n\n"
|
||||
},
|
||||
"backup_id_to_replace": {
|
||||
"type": "integer",
|
||||
@@ -12108,6 +12241,77 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"UpdateDomainRecordRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/DomainRecordType"
|
||||
}
|
||||
],
|
||||
"description": "The type of the DNS record.\n\n| Value | Description |\n| ----- | ----------- |\n| A | Map an IPv4 address to a hostname. |\n| AAAA | Map an IPv6 address to a hostname. |\n| CAA | Restrict which certificate authorities are permitted to issue certificates for a domain. |\n| CNAME | Define an alias for your canonical hostname. |\n| MX | Define the mail exchanges that handle mail for the domain. |\n| NS | Define the nameservers that manage the domain. |\n| SOA | The Start of Authority record for the zone. |\n| SRV | Specify a server by hostname and port to handle a service or services. |\n| TXT | Define a string of text that is associated with a hostname. |\n\n",
|
||||
"nullable": true
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "The subdomain for this record. Use @ for records on the domain itself, and * to create a wildcard record.",
|
||||
"nullable": true
|
||||
},
|
||||
"data": {
|
||||
"type": "string",
|
||||
"description": "A general data field that has different functions depending on the record type.",
|
||||
"nullable": true
|
||||
},
|
||||
"priority": {
|
||||
"maximum": 65535,
|
||||
"minimum": 0,
|
||||
"type": "integer",
|
||||
"description": "A priority value that is only relevant for SRV and MX records.",
|
||||
"format": "int32",
|
||||
"nullable": true
|
||||
},
|
||||
"port": {
|
||||
"maximum": 65535,
|
||||
"minimum": 0,
|
||||
"type": "integer",
|
||||
"description": "A port value that is only relevant for SRV records.",
|
||||
"format": "int32",
|
||||
"nullable": true
|
||||
},
|
||||
"ttl": {
|
||||
"type": "integer",
|
||||
"description": "This value is the time to live for the record, in seconds.",
|
||||
"format": "int32",
|
||||
"nullable": true
|
||||
},
|
||||
"weight": {
|
||||
"maximum": 65535,
|
||||
"minimum": 0,
|
||||
"type": "integer",
|
||||
"description": "The weight value that is only relevant for SRV records.",
|
||||
"format": "int32",
|
||||
"nullable": true
|
||||
},
|
||||
"flags": {
|
||||
"maximum": 255,
|
||||
"minimum": 0,
|
||||
"type": "integer",
|
||||
"description": "An unsigned integer between 0-255 that is only relevant for CAA records.",
|
||||
"format": "int32",
|
||||
"nullable": true
|
||||
},
|
||||
"tag": {
|
||||
"maxLength": 15,
|
||||
"minLength": 1,
|
||||
"pattern": "[a-z0-9]+",
|
||||
"type": "string",
|
||||
"description": "A parameter tag that is only relevant for CAA records.",
|
||||
"nullable": true
|
||||
}
|
||||
},
|
||||
"description": "Any values not provided will be retained. Provide empty strings to clear existing string values, nulls to retain the existing values."
|
||||
},
|
||||
"UpdateLoadBalancerRequest": {
|
||||
"required": [
|
||||
"name"
|
||||
@@ -12122,7 +12326,7 @@
|
||||
"forwarding_rules": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/ForwardingRule"
|
||||
"$ref": "#/components/schemas/ForwardingRuleRequest"
|
||||
},
|
||||
"description": "The rules that control which traffic the load balancer will forward to servers in the pool. Leave null to accept a default \"HTTP\" only forwarding rule.",
|
||||
"nullable": true
|
||||
@@ -12130,7 +12334,7 @@
|
||||
"health_check": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/HealthCheck"
|
||||
"$ref": "#/components/schemas/HealthCheckRequest"
|
||||
}
|
||||
],
|
||||
"description": "The rules that determine which servers are considered 'healthy' and in the server pool for the load balancer. Leave this null to accept appropriate defaults based on the forwarding_rules.",
|
||||
@@ -12226,7 +12430,7 @@
|
||||
"$ref": "#/components/schemas/BackupSlot"
|
||||
}
|
||||
],
|
||||
"description": "If replacement_strategy is anything other than 'specified', this must be provided.",
|
||||
"description": "If replacement_strategy is anything other than 'specified', this must be provided.\n\n| Value | Description |\n| ----- | ----------- |\n| daily | A backup which is scheduled to be taken each day. |\n| weekly | A backup which is scheduled to be taken each week. |\n| monthly | A backup which is scheduled to be taken each month. |\n| temporary | A backup which is created on demand and only retained for a maximum of seven days. |\n\n",
|
||||
"nullable": true
|
||||
},
|
||||
"replacement_strategy": {
|
||||
@@ -12235,7 +12439,7 @@
|
||||
"$ref": "#/components/schemas/BackupReplacementStrategy"
|
||||
}
|
||||
],
|
||||
"description": "The strategy for selecting which backup to replace (if any)."
|
||||
"description": "The strategy for selecting which backup to replace (if any).\n\n| Value | Description |\n| ----- | ----------- |\n| none | Do not replace any existing backup: use a free slot of the provided backup type. If there are no free slots an error will occur. |\n| specified | Replace the specific backup id provided. |\n| oldest | Use any free slots of the provided backup type, and if there are no free slots replace the oldest unlocked and un-attached backup of the provided backup type. |\n| newest | Use any free slots of the provided backup type, and if there are no free slots replace the newest unlocked and un-attached backup of the provided backup type. |\n\n"
|
||||
},
|
||||
"backup_id_to_replace": {
|
||||
"type": "integer",
|
||||
@@ -12336,18 +12540,20 @@
|
||||
"pc_i440fx_4point2",
|
||||
"pc_i440fx_5point0",
|
||||
"pc_i440fx_5point1",
|
||||
"pc_i440fx_7point2"
|
||||
"pc_i440fx_7point2",
|
||||
"pc_i440fx_8point2"
|
||||
],
|
||||
"type": "string",
|
||||
"description": "\n| Value | Description |\n| ----- | ----------- |\n| pc_i440fx_1point5 | PC I440 FX 1.5 |\n| pc_i440fx_2point11 | PC I440 FX 2.11 |\n| pc_i440fx_4point1 | PC I440 FX 4.1 |\n| pc_i440fx_4point2 | PC I440 FX 4.2 |\n| pc_i440fx_5point0 | PC I440 FX 5.0 |\n| pc_i440fx_5point1 | PC I440 FX 5.1 |\n| pc_i440fx_7point2 | PC I440 FX 7.2 |\n\n",
|
||||
"description": "\n| Value | Description |\n| ----- | ----------- |\n| pc_i440fx_1point5 | PC i440FX 1.5 |\n| pc_i440fx_2point11 | PC i440FX 2.11 |\n| pc_i440fx_4point1 | PC i440FX 4.1 |\n| pc_i440fx_4point2 | PC i440FX 4.2 |\n| pc_i440fx_5point0 | PC i440FX 5.0 |\n| pc_i440fx_5point1 | PC i440FX 5.1 |\n| pc_i440fx_7point2 | PC i440FX 7.2 |\n| pc_i440fx_8point2 | PC i440FX 8.2 |\n\n",
|
||||
"x-enum-descriptions": [
|
||||
"PC I440 FX 1.5",
|
||||
"PC I440 FX 2.11",
|
||||
"PC I440 FX 4.1",
|
||||
"PC I440 FX 4.2",
|
||||
"PC I440 FX 5.0",
|
||||
"PC I440 FX 5.1",
|
||||
"PC I440 FX 7.2"
|
||||
"PC i440FX 1.5",
|
||||
"PC i440FX 2.11",
|
||||
"PC i440FX 4.1",
|
||||
"PC i440FX 4.2",
|
||||
"PC i440FX 5.0",
|
||||
"PC i440FX 5.1",
|
||||
"PC i440FX 7.2",
|
||||
"PC i440FX 8.2"
|
||||
]
|
||||
},
|
||||
"Vpc": {
|
||||
+91
-25
@@ -712,7 +712,7 @@
|
||||
"name": "entry_protocol",
|
||||
"string": {
|
||||
"computed_optional_required": "required",
|
||||
"description": "The protocol that traffic must match for the load balancer to forward it. Valid values are \"http\" and \"https\".",
|
||||
"description": "The protocol that traffic must match for this load balancer to forward traffic according to this rule.\n\n| Value | Description |\n| ----- | ----------- |\n| http | The load balancer will forward HTTP traffic that matches this rule. |\n| https | The load balancer will forward HTTPS traffic that matches this rule. |\n\n",
|
||||
"validators": [
|
||||
{
|
||||
"custom": {
|
||||
@@ -753,7 +753,7 @@
|
||||
"path": "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
|
||||
}
|
||||
],
|
||||
"schema_definition": "stringvalidator.RegexMatches(regexp.MustCompile(\"/[A-Za-z0-9/.?=\u0026+%_-]*\"), \"\")"
|
||||
"schema_definition": "stringvalidator.RegexMatches(regexp.MustCompile(\"/[A-Za-z0-9/.?=&+%_-]*\"), \"\")"
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -763,7 +763,7 @@
|
||||
"name": "protocol",
|
||||
"string": {
|
||||
"computed_optional_required": "computed_optional",
|
||||
"description": "Leave null to accept the default HTTP protocol."
|
||||
"description": "Leave null to accept the default HTTP protocol.\n\n| Value | Description |\n| ----- | ----------- |\n| http | The health check will be performed via HTTP. |\n| https | The health check will be performed via HTTPS. |\n| both | The health check will be performed via both HTTP and HTTPS. Failing a health check on one protocol will remove the server from the pool of servers only for that protocol. |\n\n"
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -834,6 +834,13 @@
|
||||
"description": "The slug of the selected operating system."
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "ipv6",
|
||||
"bool": {
|
||||
"computed_optional_required": "computed_optional",
|
||||
"description": "If true this will enable IPv6 for this server."
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "name",
|
||||
"string": {
|
||||
@@ -928,6 +935,84 @@
|
||||
"computed_optional_required": "computed_optional",
|
||||
"description": "The ID of the server to fetch."
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "advanced_features",
|
||||
"single_nested": {
|
||||
"computed_optional_required": "computed_optional",
|
||||
"attributes": [
|
||||
{
|
||||
"name": "emulated_hyperv",
|
||||
"bool": {
|
||||
"computed_optional_required": "computed_optional",
|
||||
"description": "Enable HyperV (a hypervisor produced by Microsoft) support. Enabled by default on Windows servers, generally of no value for non-Windows servers."
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "emulated_devices",
|
||||
"bool": {
|
||||
"computed_optional_required": "computed_optional",
|
||||
"description": "When emulated devices is enabled, the KVM specific \"VirtIO\" disk drive and network devices are removed, and replaced with emulated versions of physical hardware: an old IDE HDD and an Intel E1000 network card. Emulated devices are much slower than the VirtIO devices, and so this option should not be enabled unless absolutely necessary."
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "nested_virt",
|
||||
"bool": {
|
||||
"computed_optional_required": "computed_optional",
|
||||
"description": "When this option is enabled the functionality necessary to run your own KVM servers within your server is enabled. Note that all the networking limits - one MAC address per VPS, restricted to specific IPs - still apply to public cloud so this feature is generally only useful in combination with Virtual Private Cloud."
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "driver_disk",
|
||||
"bool": {
|
||||
"computed_optional_required": "computed_optional",
|
||||
"description": "When this option is enabled a copy of the KVM driver disc for Windows (\"virtio-win.iso\") will be attached to your server as a virtual CD. This option can also be used in combination with your own attached backup when installing Windows."
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "unset_uuid",
|
||||
"bool": {
|
||||
"computed_optional_required": "computed_optional",
|
||||
"description": "When this option is NOT enabled a 128-bit unique identifier is exposed to your server through the virtual BIOS. Each server receives a different UUID. Some proprietary licensed software utilize this identifier to \"tie\" the license to a specific server."
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "local_rtc",
|
||||
"bool": {
|
||||
"computed_optional_required": "computed_optional",
|
||||
"description": "When a server is booted the virtual BIOS receives the current date and time from the host node. The BIOS does not have an explicit timezone, so the timezone used is implicit and must be understood by the operating system. Most operating systems other than Windows expect the time to be UTC since it allows the operating system to control the timezone used when displaying the time. Our Windows installations have also been customized to use UTC, but when using your own installation of Windows this should be set to the host node's local timezone."
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "emulated_tpm",
|
||||
"bool": {
|
||||
"computed_optional_required": "computed_optional",
|
||||
"description": "When enabled this provides an emulated TPM v1.2 device to your Cloud Server. Warning: the TPM state is not backed up."
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "cloud_init",
|
||||
"bool": {
|
||||
"computed_optional_required": "computed",
|
||||
"description": "When this option is enabled the Cloud Server will be provided a datasource for the cloud-init service."
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "qemu_guest_agent",
|
||||
"bool": {
|
||||
"computed_optional_required": "computed",
|
||||
"description": "When this option is enabled the server will allow QEMU Guest Agent to perform password reset without rebooting."
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "uefi_boot",
|
||||
"bool": {
|
||||
"computed_optional_required": "computed",
|
||||
"description": "When this option is enabled the Cloud Server will use UEFI instead of legacy PC BIOS."
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -946,7 +1031,7 @@
|
||||
"name": "action",
|
||||
"string": {
|
||||
"computed_optional_required": "required",
|
||||
"description": "The action to take when there is a match on this rule.",
|
||||
"description": "The action to take when there is a match on this rule.\n\n| Value | Description |\n| ----- | ----------- |\n| drop | Traffic matching this rule will be dropped. |\n| accept | Traffic matching this rule will be accepted. |\n\n",
|
||||
"validators": [
|
||||
{
|
||||
"custom": {
|
||||
@@ -1016,7 +1101,7 @@
|
||||
"name": "protocol",
|
||||
"string": {
|
||||
"computed_optional_required": "required",
|
||||
"description": "The protocol to match for this rule.",
|
||||
"description": "The protocol to match for this rule.\n\n| Value | Description |\n| ----- | ----------- |\n| all | This rule will match any protocol. |\n| icmp | This rule will match ICMP traffic only. |\n| tcp | This rule will match TCP traffic only. |\n| udp | This rule will match UDP traffic only. |\n\n",
|
||||
"validators": [
|
||||
{
|
||||
"custom": {
|
||||
@@ -1098,25 +1183,6 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "public_key",
|
||||
"string": {
|
||||
"computed_optional_required": "required",
|
||||
"description": "The public key in OpenSSH \"authorized_keys\" format.",
|
||||
"validators": [
|
||||
{
|
||||
"custom": {
|
||||
"imports": [
|
||||
{
|
||||
"path": "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
|
||||
}
|
||||
],
|
||||
"schema_definition": "stringvalidator.LengthAtLeast(1)"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "id",
|
||||
"int64": {
|
||||
@@ -1251,4 +1317,4 @@
|
||||
}
|
||||
],
|
||||
"version": "0.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,6 @@ resources:
|
||||
default will be deployed (assuming the operating system supports SSH Keys). Submit an empty list to
|
||||
disable deployment of default keys.
|
||||
ignores:
|
||||
- ipv6
|
||||
- licenses
|
||||
- links
|
||||
- server
|
||||
@@ -99,6 +98,7 @@ resources:
|
||||
key_id: id
|
||||
ignores:
|
||||
- ssh_key
|
||||
- public_key
|
||||
vpc:
|
||||
create:
|
||||
path: /vpcs
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
{
|
||||
"name": "advanced_features",
|
||||
"single_nested": {
|
||||
"computed_optional_required": "computed_optional",
|
||||
"attributes": [
|
||||
{
|
||||
"name": "emulated_hyperv",
|
||||
"bool": {
|
||||
"computed_optional_required": "computed_optional",
|
||||
"description": "Enable HyperV (a hypervisor produced by Microsoft) support. Enabled by default on Windows servers, generally of no value for non-Windows servers."
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "emulated_devices",
|
||||
"bool": {
|
||||
"computed_optional_required": "computed_optional",
|
||||
"description": "When emulated devices is enabled, the KVM specific \"VirtIO\" disk drive and network devices are removed, and replaced with emulated versions of physical hardware: an old IDE HDD and an Intel E1000 network card. Emulated devices are much slower than the VirtIO devices, and so this option should not be enabled unless absolutely necessary."
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "nested_virt",
|
||||
"bool": {
|
||||
"computed_optional_required": "computed_optional",
|
||||
"description": "When this option is enabled the functionality necessary to run your own KVM servers within your server is enabled. Note that all the networking limits - one MAC address per VPS, restricted to specific IPs - still apply to public cloud so this feature is generally only useful in combination with Virtual Private Cloud."
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "driver_disk",
|
||||
"bool": {
|
||||
"computed_optional_required": "computed_optional",
|
||||
"description": "When this option is enabled a copy of the KVM driver disc for Windows (\"virtio-win.iso\") will be attached to your server as a virtual CD. This option can also be used in combination with your own attached backup when installing Windows."
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "unset_uuid",
|
||||
"bool": {
|
||||
"computed_optional_required": "computed_optional",
|
||||
"description": "When this option is NOT enabled a 128-bit unique identifier is exposed to your server through the virtual BIOS. Each server receives a different UUID. Some proprietary licensed software utilize this identifier to \"tie\" the license to a specific server."
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "local_rtc",
|
||||
"bool": {
|
||||
"computed_optional_required": "computed_optional",
|
||||
"description": "When a server is booted the virtual BIOS receives the current date and time from the host node. The BIOS does not have an explicit timezone, so the timezone used is implicit and must be understood by the operating system. Most operating systems other than Windows expect the time to be UTC since it allows the operating system to control the timezone used when displaying the time. Our Windows installations have also been customized to use UTC, but when using your own installation of Windows this should be set to the host node's local timezone."
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "emulated_tpm",
|
||||
"bool": {
|
||||
"computed_optional_required": "computed_optional",
|
||||
"description": "When enabled this provides an emulated TPM v1.2 device to your Cloud Server. Warning: the TPM state is not backed up."
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "cloud_init",
|
||||
"bool": {
|
||||
"computed_optional_required": "computed",
|
||||
"description": "When this option is enabled the Cloud Server will be provided a datasource for the cloud-init service."
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "qemu_guest_agent",
|
||||
"bool": {
|
||||
"computed_optional_required": "computed",
|
||||
"description": "When this option is enabled the server will allow QEMU Guest Agent to perform password reset without rebooting."
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "uefi_boot",
|
||||
"bool": {
|
||||
"computed_optional_required": "computed",
|
||||
"description": "When this option is enabled the Cloud Server will use UEFI instead of legacy PC BIOS."
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
Executable
+7
@@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
GENERATOR_CONFIG=$(dirname "$0")/../provider_code_spec.json
|
||||
|
||||
# Server configuration
|
||||
ADVANCED_FEATURES_CONFIG=$(dirname "$0")/data/server_advanced_features.json
|
||||
cat <<<$(jq --tab --slurpfile adv_feat_cfg $ADVANCED_FEATURES_CONFIG '.resources[1].schema.attributes |= . + $adv_feat_cfg' $GENERATOR_CONFIG) >$GENERATOR_CONFIG
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
OPENAPI_FILE=$(dirname "$0")/openapi.json
|
||||
OPENAPI_FILE=$(dirname "$0")/../openapi.json
|
||||
|
||||
# Fetch the latest OpenAPI spec
|
||||
curl https://api.binarylane.com.au/reference/openapi.json --output $OPENAPI_FILE
|
||||
@@ -27,6 +27,10 @@ cat <<<$(jq '.paths["/account/keys/{key_id}"].delete.parameters[0].schema |= del
|
||||
cat <<<$(jq '.paths["/account/keys/{key_id}"].delete.parameters[0].schema |= del(.oneOf) + {type:"integer"}' $OPENAPI_FILE) >$OPENAPI_FILE
|
||||
cat <<<$(jq '.paths["/images"].get.parameters[0].schema |= del(.allOf) + {type:"string"}' $OPENAPI_FILE) >$OPENAPI_FILE
|
||||
cat <<<$(jq '.paths["/sizes"].get.parameters[1].schema |= del(.oneOf) + {type:"string"}' $OPENAPI_FILE) >$OPENAPI_FILE
|
||||
cat <<<$(jq '.components.schemas.AdvancedFeature |= del(.enum)' $OPENAPI_FILE) >$OPENAPI_FILE
|
||||
cat <<<$(jq '.components.schemas.AdvancedServerFeatures.properties.enabled_advanced_features.items |= del(.["$ref"]) + {type:"string"}' $OPENAPI_FILE) >$OPENAPI_FILE
|
||||
cat <<<$(jq '.components.schemas.ChangeAdvancedFeatures.properties.enabled_advanced_features.items |= del(.["$ref"]) + {type:"string"}' $OPENAPI_FILE) >$OPENAPI_FILE
|
||||
cat <<<$(jq '.components.schemas.AvailableAdvancedServerFeatures.properties.advanced_features.items |= del(.["$ref"]) + {type:"string"}' $OPENAPI_FILE) >$OPENAPI_FILE
|
||||
|
||||
# Remove the "/paths/{image_id}" path because its duplicated by "/images/{image_id_or_slug}"
|
||||
cat <<<$(jq 'del(.paths."/images/{image_id}")' $OPENAPI_FILE) >$OPENAPI_FILE
|
||||
@@ -45,10 +49,17 @@ cat <<<$(jq '.components.schemas.AdvancedFirewallRule.properties.action += {"x-o
|
||||
cat <<<$(jq '.components.schemas.AdvancedFirewallRule.properties.destination_addresses += {"x-oapi-codegen-extra-tags": {"tfsdk": "destination_addresses"}}' $OPENAPI_FILE) >$OPENAPI_FILE
|
||||
cat <<<$(jq '.components.schemas.AdvancedFirewallRule.properties.destination_ports += {"x-oapi-codegen-extra-tags": {"tfsdk": "destination_ports"}}' $OPENAPI_FILE) >$OPENAPI_FILE
|
||||
cat <<<$(jq '.components.schemas.AdvancedFirewallRule.properties.source_addresses += {"x-oapi-codegen-extra-tags": {"tfsdk": "source_addresses"}}' $OPENAPI_FILE) >$OPENAPI_FILE
|
||||
cat <<<$(jq '.components.schemas.AdvancedFirewallRuleRequest.properties.description += {"x-oapi-codegen-extra-tags": {"tfsdk": "description"}}' $OPENAPI_FILE) >$OPENAPI_FILE
|
||||
cat <<<$(jq '.components.schemas.AdvancedFirewallRuleRequest.properties.protocol += {"x-oapi-codegen-extra-tags": {"tfsdk": "protocol"}}' $OPENAPI_FILE) >$OPENAPI_FILE
|
||||
cat <<<$(jq '.components.schemas.AdvancedFirewallRuleRequest.properties.action += {"x-oapi-codegen-extra-tags": {"tfsdk": "action"}}' $OPENAPI_FILE) >$OPENAPI_FILE
|
||||
cat <<<$(jq '.components.schemas.AdvancedFirewallRuleRequest.properties.destination_addresses += {"x-oapi-codegen-extra-tags": {"tfsdk": "destination_addresses"}}' $OPENAPI_FILE) >$OPENAPI_FILE
|
||||
cat <<<$(jq '.components.schemas.AdvancedFirewallRuleRequest.properties.destination_ports += {"x-oapi-codegen-extra-tags": {"tfsdk": "destination_ports"}}' $OPENAPI_FILE) >$OPENAPI_FILE
|
||||
cat <<<$(jq '.components.schemas.AdvancedFirewallRuleRequest.properties.source_addresses += {"x-oapi-codegen-extra-tags": {"tfsdk": "source_addresses"}}' $OPENAPI_FILE) >$OPENAPI_FILE
|
||||
|
||||
## Load Balancer
|
||||
cat <<<$(jq '.components.schemas.CreateLoadBalancerRequest.properties.forwarding_rules += {"x-oapi-codegen-extra-tags": {"tfsdk": "forwarding_rules"}}' $OPENAPI_FILE) >$OPENAPI_FILE
|
||||
cat <<<$(jq '.components.schemas.ForwardingRule.properties.entry_protocol += {"x-oapi-codegen-extra-tags": {"tfsdk": "entry_protocol"}}' $OPENAPI_FILE) >$OPENAPI_FILE
|
||||
cat <<<$(jq '.components.schemas.ForwardingRuleRequest.properties.entry_protocol += {"x-oapi-codegen-extra-tags": {"tfsdk": "entry_protocol"}}' $OPENAPI_FILE) >$OPENAPI_FILE
|
||||
cat <<<$(jq '.components.schemas.LoadBalancer.properties.health_check += {"x-oapi-codegen-extra-tags": {"tfsdk": "health_check"}}' $OPENAPI_FILE) >$OPENAPI_FILE
|
||||
cat <<<$(jq '.components.schemas.HealthCheckProtocol |= del(.enum)' $OPENAPI_FILE) >$OPENAPI_FILE
|
||||
|
||||
Reference in New Issue
Block a user