forked from mirrors/terraform-provider-binarylane
Compare commits
4 Commits
v0.10.3
...
feat-disks
| Author | SHA1 | Date | |
|---|---|---|---|
| 32e9056957 | |||
| 325b2e96ea | |||
| a50daac8e9 | |||
| 424828123d |
@@ -45,3 +45,8 @@ jobs:
|
||||
# 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 }}
|
||||
|
||||
+2
-1
@@ -24,7 +24,8 @@ provider_installation {
|
||||
4. Build and test the provider
|
||||
|
||||
```sh
|
||||
go build -o bin/terraform-provider-binarylane
|
||||
# Build with line numbers
|
||||
go build -ldflags="-s -w" -o bin/terraform-provider-binarylane
|
||||
go install
|
||||
cd examples/basic
|
||||
terraform plan
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -33,6 +33,7 @@ data "binarylane_server" "example" {
|
||||
- must be a multiple of 5
|
||||
- \> 60 GB must be a multiple of 10
|
||||
- \> 200 GB must be a multiple of 100
|
||||
- `disks` (Attributes List) A list of the disks that are currently attached to the server. (see [below for nested schema](#nestedatt--disks))
|
||||
- `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.
|
||||
- `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
|
||||
@@ -66,3 +67,14 @@ Read-Only:
|
||||
- `qemu_guest_agent` (Boolean)
|
||||
- `uefi_boot` (Boolean)
|
||||
- `unset_uuid` (Boolean)
|
||||
|
||||
|
||||
<a id="nestedatt--disks"></a>
|
||||
### Nested Schema for `disks`
|
||||
|
||||
Read-Only:
|
||||
|
||||
- `description` (String) A description of this disk.
|
||||
- `id` (Number) The ID of this disk.
|
||||
- `primary` (Boolean) A primary disk is treated differently from other disks.
|
||||
- `size_gigabytes` (Number) The size of the disk in GB.
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -44,6 +44,7 @@ resource "binarylane_server" "example" {
|
||||
- must be a multiple of 5
|
||||
- \> 60 GB must be a multiple of 10
|
||||
- \> 200 GB must be a multiple of 100
|
||||
- `disks` (Attributes List) A list of the disks that are currently attached to the server. (see [below for nested schema](#nestedatt--disks))
|
||||
- `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
|
||||
@@ -86,6 +87,23 @@ Read-Only:
|
||||
- `uefi_boot` (Boolean) When this option is enabled the Cloud Server will use UEFI instead of legacy PC BIOS.
|
||||
|
||||
|
||||
<a id="nestedatt--disks"></a>
|
||||
### Nested Schema for `disks`
|
||||
|
||||
Required:
|
||||
|
||||
- `size_gigabytes` (Number) The size of the disk in GB.
|
||||
|
||||
Optional:
|
||||
|
||||
- `description` (String) A description of this disk.
|
||||
|
||||
Read-Only:
|
||||
|
||||
- `id` (Number) The ID of this disk.
|
||||
- `primary` (Boolean) A primary disk is treated differently from other disks.
|
||||
|
||||
|
||||
<a id="nestedatt--timeouts"></a>
|
||||
### Nested Schema for `timeouts`
|
||||
|
||||
|
||||
@@ -17,4 +17,11 @@ resource "binarylane_server" "example" {
|
||||
size = "std-min" # 1 VPCU, 1 GB Memory, 20 GB NVME Storage, 1000 GB Data Transfer
|
||||
public_ipv4_count = 1
|
||||
# Password will be generated automatically and mailed to the account holder
|
||||
disks = [{
|
||||
description = "Primary Disk"
|
||||
size_gigabytes = 10
|
||||
}, {
|
||||
description = "Secondary Disk"
|
||||
size_gigabytes = 10
|
||||
}]
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -9,7 +9,7 @@ require (
|
||||
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.22.0
|
||||
github.com/hashicorp/terraform-plugin-framework v1.15.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.18.0
|
||||
github.com/hashicorp/terraform-plugin-go v0.28.0
|
||||
@@ -112,8 +112,8 @@ require (
|
||||
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-20250715232539-7130f93afb79 // indirect
|
||||
google.golang.org/grpc v1.73.0 // 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
|
||||
|
||||
@@ -71,8 +71,8 @@ github.com/go-git/go-billy/v5 v5.6.2 h1:6Q86EsPXMa7c3YZ3aLAQsMA0VlWmy43r6FHqa/UN
|
||||
github.com/go-git/go-billy/v5 v5.6.2/go.mod h1:rcFC2rAsp/erv7CMz9GczHcuD0D32fWzH+MJAU+jaUU=
|
||||
github.com/go-git/go-git/v5 v5.14.0 h1:/MD3lCrGjCen5WfEAzKg00MJJffKhC8gzS80ycmCi60=
|
||||
github.com/go-git/go-git/v5 v5.14.0/go.mod h1:Z5Xhoia5PcWA3NF8vRLURn9E5FRhSl7dGj9ItW3Wk5k=
|
||||
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
||||
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
|
||||
@@ -151,8 +151,8 @@ github.com/hashicorp/terraform-plugin-codegen-spec v0.2.0 h1:91dQG1A/DxP6vRz9Giy
|
||||
github.com/hashicorp/terraform-plugin-codegen-spec v0.2.0/go.mod h1:fywrEKpordQypmAjz/HIfm2LuNVmyJ6KDe8XT9GdJxQ=
|
||||
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.0 h1:LQ2rsOfmDLxcn5EeIwdXFtr03FVsNktbbBci8cOKdb4=
|
||||
github.com/hashicorp/terraform-plugin-framework v1.15.0/go.mod h1:hxrNI/GY32KPISpWqlCoTLM9JZsGH3CyYlir09bD/fI=
|
||||
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.18.0 h1:OQnlOt98ua//rCw+QhBbSqfW3QbwtVrcdWeQN5gI3Hw=
|
||||
@@ -323,16 +323,16 @@ go.abhg.dev/goldmark/frontmatter v0.2.0 h1:P8kPG0YkL12+aYk2yU3xHv4tcXzeVnN+gU0tJ
|
||||
go.abhg.dev/goldmark/frontmatter v0.2.0/go.mod h1:XqrEkZuM57djk7zrlRUB02x8I5J0px76YjkOzhB4YlU=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
||||
go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ=
|
||||
go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y=
|
||||
go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M=
|
||||
go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE=
|
||||
go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY=
|
||||
go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.35.0 h1:1RriWBmCKgkeHEhM7a2uMjMUfP7MsOF5JpUCaEqEI9o=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w=
|
||||
go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs=
|
||||
go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc=
|
||||
go.opentelemetry.io/otel v1.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=
|
||||
@@ -414,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-20250715232539-7130f93afb79 h1:1ZwqphdOdWYXsUHgMpU/101nCtf/kSp9hOrcvFsnl10=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250715232539-7130f93afb79/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
|
||||
google.golang.org/grpc v1.73.0 h1:VIWSmpI2MegBtTuFt5/JWy2oXxtjJ/e89Z70ImfD2ok=
|
||||
google.golang.org/grpc v1.73.0/go.mod h1:50sbHOUqWoCQGI8V2HQLJM0B+LMlIUjNSZmow7EVBQc=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250728155136-f173205681a0 h1:MAKi5q709QWfnkkpNQ0M12hYJ1+e8qYVDyowc4U1XZM=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250728155136-f173205681a0/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
|
||||
google.golang.org/grpc v1.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=
|
||||
|
||||
@@ -1189,10 +1189,10 @@ type ConsoleResponse struct {
|
||||
// CreateLoadBalancerRequest defines model for CreateLoadBalancerRequest.
|
||||
type CreateLoadBalancerRequest struct {
|
||||
// ForwardingRules The rules that control which traffic the load balancer will forward to servers in the pool. Leave null to accept a default "HTTP" only forwarding rule.
|
||||
ForwardingRules *[]ForwardingRule `json:"forwarding_rules" tfsdk:"forwarding_rules"`
|
||||
ForwardingRules *[]ForwardingRuleRequest `json:"forwarding_rules" tfsdk:"forwarding_rules"`
|
||||
|
||||
// HealthCheck The rules that determine which servers are considered 'healthy' and in the server pool for the load balancer. Leave this null to accept appropriate defaults based on the forwarding_rules.
|
||||
HealthCheck *HealthCheck `json:"health_check"`
|
||||
HealthCheck *HealthCheckRequest `json:"health_check"`
|
||||
|
||||
// Name The hostname of the load balancer.
|
||||
Name string `json:"name"`
|
||||
@@ -1356,16 +1356,16 @@ type DisableSelinuxType string
|
||||
// Disk defines model for Disk.
|
||||
type Disk struct {
|
||||
// Description A description of this disk.
|
||||
Description *string `json:"description"`
|
||||
Description *string `json:"description" tfsdk:"description"`
|
||||
|
||||
// Id The ID of this disk.
|
||||
Id *int64 `json:"id,omitempty"`
|
||||
Id *int64 `json:"id,omitempty" tfsdk:"id"`
|
||||
|
||||
// Primary A primary disk is treated differently from other disks.
|
||||
Primary *bool `json:"primary,omitempty"`
|
||||
Primary *bool `json:"primary,omitempty" tfsdk:"primary"`
|
||||
|
||||
// SizeGigabytes The size of the disk in GB.
|
||||
SizeGigabytes *float64 `json:"size_gigabytes,omitempty"`
|
||||
SizeGigabytes *float64 `json:"size_gigabytes,omitempty" tfsdk:"size_gigabytes"`
|
||||
}
|
||||
|
||||
// DistributionFeature
|
||||
@@ -1603,14 +1603,50 @@ type ForwardingRule struct {
|
||||
EntryProtocol LoadBalancerRuleProtocol `json:"entry_protocol" tfsdk:"entry_protocol"`
|
||||
}
|
||||
|
||||
// ForwardingRuleRequest defines model for ForwardingRuleRequest.
|
||||
type ForwardingRuleRequest struct {
|
||||
// EntryProtocol The protocol that traffic must match for this load balancer to forward traffic according to this rule.
|
||||
//
|
||||
// | Value | Description |
|
||||
// | ----- | ----------- |
|
||||
// | http | The load balancer will forward HTTP traffic that matches this rule. |
|
||||
// | https | The load balancer will forward HTTPS traffic that matches this rule. |
|
||||
//
|
||||
EntryProtocol LoadBalancerRuleProtocol `json:"entry_protocol" tfsdk:"entry_protocol"`
|
||||
}
|
||||
|
||||
// ForwardingRulesRequest defines model for ForwardingRulesRequest.
|
||||
type ForwardingRulesRequest struct {
|
||||
// ForwardingRules The rules that control which traffic the load balancer will forward to servers in the pool.
|
||||
ForwardingRules []ForwardingRule `json:"forwarding_rules"`
|
||||
ForwardingRules []ForwardingRuleRequest `json:"forwarding_rules"`
|
||||
}
|
||||
|
||||
// HealthCheck defines model for HealthCheck.
|
||||
type HealthCheck struct {
|
||||
// Path The path to the health check endpoint.
|
||||
Path string `json:"path"`
|
||||
|
||||
// Protocol The protocol used for the health check.
|
||||
//
|
||||
// | Value | Description |
|
||||
// | ----- | ----------- |
|
||||
// | http | The health check will be performed via HTTP. |
|
||||
// | https | The health check will be performed via HTTPS. |
|
||||
// | both | The health check will be performed via both HTTP and HTTPS. Failing a health check on one protocol will remove the server from the pool of servers only for that protocol. |
|
||||
//
|
||||
Protocol HealthCheckProtocol `json:"protocol"`
|
||||
}
|
||||
|
||||
// HealthCheckProtocol
|
||||
// | Value | Description |
|
||||
// | ----- | ----------- |
|
||||
// | http | The health check will be performed via HTTP. |
|
||||
// | https | The health check will be performed via HTTPS. |
|
||||
// | both | The health check will be performed via both HTTP and HTTPS. Failing a health check on one protocol will remove the server from the pool of servers only for that protocol. |
|
||||
type HealthCheckProtocol = string
|
||||
|
||||
// HealthCheckRequest defines model for HealthCheckRequest.
|
||||
type HealthCheckRequest struct {
|
||||
// Path Leave null to accept the default '/' path.
|
||||
Path *string `json:"path"`
|
||||
|
||||
@@ -1625,14 +1661,6 @@ type HealthCheck struct {
|
||||
Protocol *HealthCheckProtocol `json:"protocol"`
|
||||
}
|
||||
|
||||
// HealthCheckProtocol
|
||||
// | Value | Description |
|
||||
// | ----- | ----------- |
|
||||
// | http | The health check will be performed via HTTP. |
|
||||
// | https | The health check will be performed via HTTPS. |
|
||||
// | both | The health check will be performed via both HTTP and HTTPS. Failing a health check on one protocol will remove the server from the pool of servers only for that protocol. |
|
||||
type HealthCheckProtocol = string
|
||||
|
||||
// Host defines model for Host.
|
||||
type Host struct {
|
||||
// DisplayName The name for this host. If this is a dedicated host this property will be empty.
|
||||
@@ -1912,29 +1940,38 @@ type Links struct {
|
||||
// LoadBalancer defines model for LoadBalancer.
|
||||
type LoadBalancer struct {
|
||||
// CreatedAt The date and time in ISO8601 format of the creation of the load balancer.
|
||||
CreatedAt *time.Time `json:"created_at,omitempty"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
|
||||
// ForwardingRules The rules that control which traffic the load balancer will forward to servers in the pool.
|
||||
ForwardingRules *[]ForwardingRule `json:"forwarding_rules,omitempty"`
|
||||
ForwardingRules []ForwardingRule `json:"forwarding_rules"`
|
||||
|
||||
// HealthCheck The rules that determine which servers are considered 'healthy' and in the server pool for the load balancer.
|
||||
HealthCheck *HealthCheck `json:"health_check,omitempty" tfsdk:"health_check"`
|
||||
HealthCheck HealthCheck `json:"health_check" tfsdk:"health_check"`
|
||||
|
||||
// Id The ID of the load balancer.
|
||||
Id *int64 `json:"id,omitempty"`
|
||||
Id int64 `json:"id"`
|
||||
|
||||
// Ip The IPv4 address of the load balancer.
|
||||
Ip *string `json:"ip,omitempty"`
|
||||
Ip string `json:"ip"`
|
||||
|
||||
// Name The hostname of the load balancer.
|
||||
Name *string `json:"name,omitempty"`
|
||||
Name string `json:"name"`
|
||||
|
||||
// Region The region the load balancer is located in. If this value is null the load balancer is an 'AnyCast' load balancer.
|
||||
Region *Region `json:"region"`
|
||||
|
||||
// ServerIds The server IDs of the servers that are currently in the load balancer pool (regardless of their current 'health').
|
||||
ServerIds *[]int64 `json:"server_ids,omitempty"`
|
||||
Status *LoadBalancerStatus `json:"status,omitempty"`
|
||||
ServerIds []int64 `json:"server_ids"`
|
||||
|
||||
// Status The current status of the load balancer.
|
||||
//
|
||||
// | Value | Description |
|
||||
// | ----- | ----------- |
|
||||
// | new | The load balancer is currently being built and is not ready to accept connections. |
|
||||
// | active | The load balancer is available. |
|
||||
// | errored | The load balancer is in an errored state. |
|
||||
//
|
||||
Status LoadBalancerStatus `json:"status"`
|
||||
}
|
||||
|
||||
// LoadBalancerAvailabilityOption defines model for LoadBalancerAvailabilityOption.
|
||||
@@ -1946,7 +1983,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"`
|
||||
@@ -3048,10 +3085,10 @@ type UpdateDomainRecordRequest struct {
|
||||
// UpdateLoadBalancerRequest defines model for UpdateLoadBalancerRequest.
|
||||
type UpdateLoadBalancerRequest struct {
|
||||
// ForwardingRules The rules that control which traffic the load balancer will forward to servers in the pool. Leave null to accept a default "HTTP" only forwarding rule.
|
||||
ForwardingRules *[]ForwardingRule `json:"forwarding_rules"`
|
||||
ForwardingRules *[]ForwardingRuleRequest `json:"forwarding_rules"`
|
||||
|
||||
// HealthCheck The rules that determine which servers are considered 'healthy' and in the server pool for the load balancer. Leave this null to accept appropriate defaults based on the forwarding_rules.
|
||||
HealthCheck *HealthCheck `json:"health_check"`
|
||||
HealthCheck *HealthCheckRequest `json:"health_check"`
|
||||
|
||||
// Name The hostname of the load balancer.
|
||||
Name string `json:"name"`
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"terraform-provider-binarylane/internal/resources"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-framework/datasource"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -22,8 +23,9 @@ type loadBalancerDataSource struct {
|
||||
bc *BinarylaneClient
|
||||
}
|
||||
|
||||
type loadBalancerDataSourceModel struct {
|
||||
type loadBalancerDataModel struct {
|
||||
resources.LoadBalancerModel
|
||||
Ip types.String `tfsdk:"ip"`
|
||||
}
|
||||
|
||||
func (d *loadBalancerDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
|
||||
@@ -52,7 +54,7 @@ func (d *loadBalancerDataSource) Configure(
|
||||
|
||||
func (d *loadBalancerDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) {
|
||||
ds, err := convertResourceSchemaToDataSourceSchema(
|
||||
resources.LoadBalancerResourceSchema(ctx),
|
||||
loadBalancerSchema(ctx),
|
||||
AttributeConfig{
|
||||
RequiredAttributes: &[]string{"id"},
|
||||
},
|
||||
@@ -63,10 +65,11 @@ func (d *loadBalancerDataSource) Schema(ctx context.Context, req datasource.Sche
|
||||
}
|
||||
resp.Schema = *ds
|
||||
resp.Schema.Description = "Retrieve details about a BinaryLane Load Balancer."
|
||||
resp.Schema.MarkdownDescription = resp.Schema.Description
|
||||
}
|
||||
|
||||
func (d *loadBalancerDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
|
||||
var data loadBalancerDataSourceModel
|
||||
var data loadBalancerDataModel
|
||||
|
||||
// Read Terraform prior state data into the model
|
||||
resp.Diagnostics.Append(req.Config.Get(ctx, &data)...)
|
||||
@@ -93,7 +96,7 @@ func (d *loadBalancerDataSource) Read(ctx context.Context, req datasource.ReadRe
|
||||
return
|
||||
}
|
||||
|
||||
diags := setLoadBalancerModelState(ctx, &data.LoadBalancerModel, lbResp.JSON200.LoadBalancer)
|
||||
diags := setLoadBalancerModelState(ctx, &data, lbResp.JSON200.LoadBalancer)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
|
||||
@@ -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)},
|
||||
|
||||
@@ -35,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" {
|
||||
@@ -54,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"),
|
||||
@@ -64,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
|
||||
@@ -79,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"),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -117,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 {
|
||||
|
||||
@@ -162,6 +162,14 @@ func (d *serverDataSource) Read(ctx context.Context, req datasource.ReadRequest,
|
||||
data.PrivateIPv4Addresses = tfPrivateIpv4Addresses
|
||||
}
|
||||
|
||||
disks, diag := types.ListValueFrom(ctx, data.Disks.ElementType(ctx), serverResp.JSON200.Server.Disks)
|
||||
diags.Append(diag...)
|
||||
if diag.HasError() {
|
||||
data.Disks = types.ListUnknown(data.Disks.ElementType(ctx))
|
||||
} else {
|
||||
data.Disks = disks
|
||||
}
|
||||
|
||||
// Get user data script
|
||||
userDataResp, err := d.bc.client.GetServersServerIdUserDataWithResponse(ctx, data.Id.ValueInt64())
|
||||
if err != nil {
|
||||
|
||||
@@ -63,7 +63,7 @@ func (r *serverFirewallRulesResource) Schema(ctx context.Context, req resource.S
|
||||
|
||||
// Overrides
|
||||
serverId := resp.Schema.Attributes["server_id"]
|
||||
resp.Schema.Attributes["server_id"] = &schema.Int64Attribute{
|
||||
resp.Schema.Attributes["server_id"] = schema.Int64Attribute{
|
||||
Description: serverId.GetDescription(),
|
||||
MarkdownDescription: serverId.GetMarkdownDescription(),
|
||||
Required: true, // Server ID is required to define the firewall rules
|
||||
@@ -251,7 +251,7 @@ func GetFirewallRulesState(ctx context.Context, firewallRules *[]binarylane.Adva
|
||||
firewallRulesValue := resources.FirewallRulesValue{}
|
||||
var firewallRulesValues []resources.FirewallRulesValue
|
||||
|
||||
if *firewallRules == nil || len(*firewallRules) == 0 {
|
||||
if len(*firewallRules) == 0 {
|
||||
firewallRulesValues = []resources.FirewallRulesValue{}
|
||||
} else {
|
||||
for _, rule := range *firewallRules {
|
||||
|
||||
@@ -87,7 +87,7 @@ func serverSchema(ctx context.Context) schema.Schema {
|
||||
|
||||
// Overrides
|
||||
id := s.Attributes["id"]
|
||||
s.Attributes["id"] = &schema.Int64Attribute{
|
||||
s.Attributes["id"] = schema.Int64Attribute{
|
||||
Description: id.GetDescription(),
|
||||
MarkdownDescription: id.GetMarkdownDescription(),
|
||||
// read only
|
||||
@@ -101,7 +101,7 @@ func serverSchema(ctx context.Context) schema.Schema {
|
||||
|
||||
imageDescription := "The slug of the selected operating system, such as `debian-12`. You can fetch a full list of images from the BinaryLane API."
|
||||
image := s.Attributes["image"]
|
||||
s.Attributes["image"] = &schema.StringAttribute{
|
||||
s.Attributes["image"] = schema.StringAttribute{
|
||||
Description: imageDescription,
|
||||
MarkdownDescription: imageDescription,
|
||||
Required: image.IsRequired(),
|
||||
@@ -113,7 +113,7 @@ func serverSchema(ctx context.Context) schema.Schema {
|
||||
}
|
||||
|
||||
backupsDescription := "If `true` this will enable two daily backups for the server. By default, backups are disabled."
|
||||
s.Attributes["backups"] = &schema.BoolAttribute{
|
||||
s.Attributes["backups"] = schema.BoolAttribute{
|
||||
Description: backupsDescription,
|
||||
MarkdownDescription: backupsDescription,
|
||||
Optional: true,
|
||||
@@ -122,7 +122,7 @@ func serverSchema(ctx context.Context) schema.Schema {
|
||||
}
|
||||
|
||||
user_data := s.Attributes["user_data"]
|
||||
s.Attributes["user_data"] = &schema.StringAttribute{
|
||||
s.Attributes["user_data"] = schema.StringAttribute{
|
||||
Description: user_data.GetDescription(),
|
||||
MarkdownDescription: user_data.GetMarkdownDescription(),
|
||||
Optional: true, // Optional as not all servers have an initialization script
|
||||
@@ -130,7 +130,7 @@ func serverSchema(ctx context.Context) schema.Schema {
|
||||
}
|
||||
|
||||
vpcId := s.Attributes["vpc_id"]
|
||||
s.Attributes["vpc_id"] = &schema.Int64Attribute{
|
||||
s.Attributes["vpc_id"] = schema.Int64Attribute{
|
||||
Description: vpcId.GetDescription(),
|
||||
MarkdownDescription: vpcId.GetMarkdownDescription(),
|
||||
Optional: vpcId.IsOptional(),
|
||||
@@ -138,7 +138,7 @@ func serverSchema(ctx context.Context) schema.Schema {
|
||||
}
|
||||
|
||||
portBlocking := s.Attributes["port_blocking"]
|
||||
s.Attributes["port_blocking"] = &schema.BoolAttribute{
|
||||
s.Attributes["port_blocking"] = schema.BoolAttribute{
|
||||
Description: portBlocking.GetDescription(),
|
||||
MarkdownDescription: portBlocking.GetMarkdownDescription(),
|
||||
Optional: portBlocking.IsOptional(),
|
||||
@@ -147,7 +147,7 @@ func serverSchema(ctx context.Context) schema.Schema {
|
||||
}
|
||||
|
||||
region := s.Attributes["region"].(schema.StringAttribute)
|
||||
s.Attributes["region"] = &schema.StringAttribute{
|
||||
s.Attributes["region"] = schema.StringAttribute{
|
||||
Description: region.GetDescription(),
|
||||
MarkdownDescription: region.GetMarkdownDescription(),
|
||||
Optional: region.IsOptional(),
|
||||
@@ -160,7 +160,7 @@ func serverSchema(ctx context.Context) schema.Schema {
|
||||
}
|
||||
|
||||
sshKeys := s.Attributes["ssh_keys"]
|
||||
s.Attributes["ssh_keys"] = &schema.ListAttribute{
|
||||
s.Attributes["ssh_keys"] = schema.ListAttribute{
|
||||
ElementType: types.Int64Type,
|
||||
Description: sshKeys.GetMarkdownDescription(),
|
||||
MarkdownDescription: sshKeys.GetDescription(),
|
||||
@@ -174,7 +174,7 @@ func serverSchema(ctx context.Context) schema.Schema {
|
||||
userDataDescription := "A script or cloud-config YAML file to configure the server. Can only be specified if the OS image supports UserData (i.e. not Windows)." +
|
||||
" See more: https://cloudinit.readthedocs.io/en/latest/explanation/format.html#user-data-script"
|
||||
userData := s.Attributes["user_data"]
|
||||
s.Attributes["user_data"] = &schema.StringAttribute{
|
||||
s.Attributes["user_data"] = schema.StringAttribute{
|
||||
Description: userDataDescription,
|
||||
MarkdownDescription: userDataDescription,
|
||||
Required: userData.IsRequired(),
|
||||
@@ -190,7 +190,7 @@ func serverSchema(ctx context.Context) schema.Schema {
|
||||
"If this is provided the specified or default remote user's account password will be set to this value. " +
|
||||
"Only valid if the server supports password change actions. If omitted and the server supports password " +
|
||||
"change actions a random password will be generated and emailed to the account email address."
|
||||
s.Attributes["password"] = &schema.StringAttribute{
|
||||
s.Attributes["password"] = schema.StringAttribute{
|
||||
Description: pwDescription,
|
||||
MarkdownDescription: pwDescription,
|
||||
Optional: true, // Password optional, if not set will be emailed to user
|
||||
@@ -199,7 +199,7 @@ func serverSchema(ctx context.Context) schema.Schema {
|
||||
}
|
||||
|
||||
publicIpv4CountDescription := "The number of public IPv4 addresses to assign to the server."
|
||||
s.Attributes["public_ipv4_count"] = &schema.Int32Attribute{
|
||||
s.Attributes["public_ipv4_count"] = schema.Int32Attribute{
|
||||
Description: publicIpv4CountDescription,
|
||||
MarkdownDescription: publicIpv4CountDescription,
|
||||
Required: true,
|
||||
@@ -212,7 +212,7 @@ func serverSchema(ctx context.Context) schema.Schema {
|
||||
}
|
||||
|
||||
publicIpv4AddressesDescription := "The public IPv4 addresses assigned to the server."
|
||||
s.Attributes["public_ipv4_addresses"] = &schema.ListAttribute{
|
||||
s.Attributes["public_ipv4_addresses"] = schema.ListAttribute{
|
||||
Description: publicIpv4AddressesDescription,
|
||||
MarkdownDescription: publicIpv4AddressesDescription,
|
||||
ElementType: types.StringType,
|
||||
@@ -229,7 +229,7 @@ func serverSchema(ctx context.Context) schema.Schema {
|
||||
"to incorrect network configuration. When `source_and_destination_check` is `false`, your Cloud Server will be able " +
|
||||
"to send and receive packets addressed to any server. This is typically used when you want to use " +
|
||||
"your Cloud Server as a VPN endpoint, a NAT server to provide internet access, or IP forwarding."
|
||||
s.Attributes["source_and_destination_check"] = &schema.BoolAttribute{
|
||||
s.Attributes["source_and_destination_check"] = schema.BoolAttribute{
|
||||
Description: sourceDestCheckDescription,
|
||||
MarkdownDescription: sourceDestCheckDescription,
|
||||
Optional: true,
|
||||
@@ -243,7 +243,7 @@ func serverSchema(ctx context.Context) schema.Schema {
|
||||
}
|
||||
|
||||
privateIpv4AddressesDescription := "The private IPv4 addresses assigned to the server."
|
||||
s.Attributes["private_ipv4_addresses"] = &schema.ListAttribute{
|
||||
s.Attributes["private_ipv4_addresses"] = schema.ListAttribute{
|
||||
Description: privateIpv4AddressesDescription,
|
||||
MarkdownDescription: privateIpv4AddressesDescription,
|
||||
ElementType: types.StringType,
|
||||
@@ -256,7 +256,7 @@ func serverSchema(ctx context.Context) schema.Schema {
|
||||
},
|
||||
}
|
||||
|
||||
s.Attributes["permalink"] = &schema.StringAttribute{
|
||||
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 +271,7 @@ func serverSchema(ctx context.Context) schema.Schema {
|
||||
pwChangeDescription := "If this is true then the `password` attribute can be changed with Terraform. " +
|
||||
"If this is false then the `password` attribute can only be replaced with a null/empty value, which will clear " +
|
||||
"the root/administrator password allowing the password to be changed via the web console."
|
||||
s.Attributes["password_change_supported"] = &schema.BoolAttribute{
|
||||
s.Attributes["password_change_supported"] = schema.BoolAttribute{
|
||||
Description: pwChangeDescription,
|
||||
MarkdownDescription: pwChangeDescription,
|
||||
// read only
|
||||
@@ -293,7 +293,7 @@ func serverSchema(ctx context.Context) schema.Schema {
|
||||
- \> 16384 MB must be a multiple of 2048
|
||||
- \> 24576 MB must be a multiple of 4096`
|
||||
|
||||
s.Attributes["memory"] = &schema.Int32Attribute{
|
||||
s.Attributes["memory"] = schema.Int32Attribute{
|
||||
Description: memoryDescription + memoryValidValues,
|
||||
MarkdownDescription: memoryDescription + memoryValidValuesMarkdown,
|
||||
Optional: true,
|
||||
@@ -316,7 +316,7 @@ func serverSchema(ctx context.Context) schema.Schema {
|
||||
- \> 60 GB must be a multiple of 10
|
||||
- \> 200 GB must be a multiple of 100`
|
||||
|
||||
s.Attributes["disk"] = &schema.Int32Attribute{
|
||||
s.Attributes["disk"] = schema.Int32Attribute{
|
||||
Description: diskDescription + diskValidValues,
|
||||
MarkdownDescription: diskDescription + diskValidValuesMarkdown,
|
||||
Optional: true,
|
||||
@@ -421,8 +421,13 @@ func (r *serverResource) ModifyPlan(ctx context.Context, req resource.ModifyPlan
|
||||
if (plan.Disk.IsNull() || plan.Disk.IsUnknown()) && plan.Size.Equal(state.Size) {
|
||||
plan.Disk = state.Disk
|
||||
}
|
||||
if (plan.Disks.IsNull() || plan.Disks.IsUnknown()) && plan.Size.Equal(state.Size) {
|
||||
plan.Disks = state.Disks
|
||||
}
|
||||
|
||||
if isAdvFeatChanged(&config.AdvancedFeatures, &state.AdvancedFeatures) {
|
||||
if !isAdvFeatChanged(&config.AdvancedFeatures, &state.AdvancedFeatures) {
|
||||
plan.AdvancedFeatures = state.AdvancedFeatures
|
||||
} else {
|
||||
advFeatResp, err := r.bc.client.GetServersServerIdAvailableAdvancedFeaturesWithResponse(ctx, state.Id.ValueInt64())
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError(
|
||||
@@ -628,6 +633,14 @@ func (r *serverResource) Create(ctx context.Context, req resource.CreateRequest,
|
||||
data.PrivateIPv4Addresses, diags = types.ListValueFrom(ctx, types.StringType, privateIpv4Addresses)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
|
||||
disks, diags := types.ListValueFrom(ctx, data.Disks.ElementType(ctx), serverResp.JSON200.Server.Disks)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
if diags.HasError() {
|
||||
data.Disks = types.ListUnknown(data.Disks.ElementType(ctx))
|
||||
} else {
|
||||
data.Disks = disks
|
||||
}
|
||||
|
||||
// Save data into Terraform state
|
||||
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
@@ -658,8 +671,14 @@ func (r *serverResource) Create(ctx context.Context, req resource.CreateRequest,
|
||||
|
||||
// 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...)
|
||||
diags = r.fetchServerResourceState(ctx, &data)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
|
||||
// Update disks
|
||||
if !config.Disks.IsNull() && !config.Disks.Equal(data.Disks) {
|
||||
diags = r.updateDisks(ctx, &data, config.Disks)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
}
|
||||
|
||||
// Save data into Terraform state
|
||||
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
|
||||
@@ -999,6 +1018,18 @@ func (r *serverResource) Update(ctx context.Context, req resource.UpdateRequest,
|
||||
}
|
||||
}
|
||||
|
||||
// Update disks
|
||||
if !config.Disks.IsNull() && !config.Disks.Equal(plan.Disks) {
|
||||
diags := r.updateDisks(ctx, &state, config.Disks)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
|
||||
// Save updated data into Terraform state
|
||||
resp.Diagnostics.Append(resp.State.Set(ctx, &state)...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Enable or disable backups
|
||||
if !plan.Backups.Equal(state.Backups) {
|
||||
if plan.Backups.ValueBool() {
|
||||
@@ -1223,6 +1254,181 @@ func (r *serverResource) updateSourceDestCheck(
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *serverResource) updateDisks(ctx context.Context, state *serverResourceModel, disks types.List) diag.Diagnostics {
|
||||
var diags diag.Diagnostics
|
||||
|
||||
if state.Disk.IsUnknown() || state.Disk.IsNull() {
|
||||
diags.AddError("Error updating disks", "Unable to update disks because the `disk` attribute is unknown or null.")
|
||||
return diags
|
||||
}
|
||||
if state.Disks.IsUnknown() || state.Disks.IsNull() {
|
||||
diags.AddError("Error updating disks", "Unable to update disks because the `disks` attribute is unknown or null.")
|
||||
return diags
|
||||
}
|
||||
if state.Disks.Equal(disks) {
|
||||
tflog.Debug(ctx, "No changes to disks, skipping update")
|
||||
return diags
|
||||
}
|
||||
|
||||
var current []resources.DisksValue
|
||||
diags.Append(state.Disks.ElementsAs(ctx, ¤t, false)...)
|
||||
if diags.HasError() {
|
||||
return diags
|
||||
}
|
||||
|
||||
var desired []resources.DisksValue
|
||||
diags.Append(disks.ElementsAs(ctx, &desired, false)...)
|
||||
if diags.HasError() {
|
||||
return diags
|
||||
}
|
||||
|
||||
// 1. Check that desired disks fit within max VM disk size
|
||||
var totalDesired float64
|
||||
for _, d := range desired {
|
||||
totalDesired += d.SizeGigabytes.ValueFloat64()
|
||||
}
|
||||
if int32(totalDesired) > state.Disk.ValueInt32() {
|
||||
diags.AddError("Error updating disks",
|
||||
fmt.Sprintf("Total desired disk size %d GB exceeds maximum allowed %d GB",
|
||||
int32(totalDesired), state.Disk.ValueInt32()))
|
||||
return diags
|
||||
}
|
||||
|
||||
// Build maps for diffing
|
||||
currentMap := make(map[int64]resources.DisksValue)
|
||||
for _, d := range current {
|
||||
currentMap[d.Id.ValueInt64()] = d
|
||||
}
|
||||
|
||||
desiredMap := make(map[int64]resources.DisksValue)
|
||||
for _, d := range desired {
|
||||
// Only disks with IDs are "existing". New ones will have Id.IsNull()
|
||||
if !d.Id.IsNull() && !d.Id.IsUnknown() {
|
||||
desiredMap[d.Id.ValueInt64()] = d
|
||||
}
|
||||
}
|
||||
|
||||
// Remove unused disks
|
||||
for id := range currentMap {
|
||||
if _, ok := desiredMap[id]; !ok {
|
||||
tflog.Debug(ctx, "Deleting disk", map[string]any{"disk_id": id})
|
||||
resp, err := r.bc.client.PostServersServerIdActionsDeleteDiskWithResponse(ctx, state.Id.ValueInt64(), binarylane.DeleteDisk{
|
||||
DiskId: id,
|
||||
Type: "delete_disk",
|
||||
})
|
||||
if err != nil {
|
||||
diags.AddError("Error deleting disk", err.Error())
|
||||
return diags
|
||||
}
|
||||
// WIP
|
||||
|
||||
// binarylane_server.example: Modifying... [name=tf-example-basic]
|
||||
// ╷
|
||||
// │ Error: Unexpected HTTP status code deleting disk
|
||||
// │
|
||||
// │ with binarylane_server.example,
|
||||
// │ on main.tf line 13, in resource "binarylane_server" "example":
|
||||
// │ 13: resource "binarylane_server" "example" {
|
||||
// │
|
||||
// │ Received 400 Bad Request deleting disk: server_id=523165, disk_id=1. Details:
|
||||
// │ {"type":"https://tools.ietf.org/html/rfc7231#section-6.5.1","title":"One or more validation errors
|
||||
// │ occurred","status":400,"errors":{"disk_id":["May not delete primary disk."]},"message":"May not delete
|
||||
// │ primary disk."}
|
||||
if resp.StatusCode() != http.StatusOK {
|
||||
diags.AddError("Unexpected HTTP status code deleting disk",
|
||||
fmt.Sprintf("Received %s deleting disk: server_id=%s, disk_id=%d. Details: %s",
|
||||
resp.Status(), state.Id.String(), id, resp.Body))
|
||||
return diags
|
||||
}
|
||||
err = r.waitForServerAction(ctx, state.Id.ValueInt64(), *resp.JSON200.Action.Id)
|
||||
if err != nil {
|
||||
diags.AddError("Error waiting for disks to be deleted", err.Error())
|
||||
return diags
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Downsize disks
|
||||
for id, desiredDisk := range desiredMap {
|
||||
if currentDisk, ok := currentMap[id]; ok {
|
||||
curSize := int32(currentDisk.SizeGigabytes.ValueFloat64())
|
||||
newSize := int32(desiredDisk.SizeGigabytes.ValueFloat64())
|
||||
if newSize < curSize {
|
||||
tflog.Debug(ctx, "Downsizing disk", map[string]any{"disk_id": id, "from": curSize, "to": newSize})
|
||||
resp, err := r.bc.client.PostServersServerIdActionsResizeDiskWithResponse(ctx, state.Id.ValueInt64(), binarylane.ResizeDisk{
|
||||
DiskId: id,
|
||||
SizeGigabytes: newSize,
|
||||
Type: "resize_disk",
|
||||
})
|
||||
if err != nil {
|
||||
diags.AddError("Error downsizing disk", err.Error())
|
||||
return diags
|
||||
}
|
||||
if resp.StatusCode() != http.StatusOK {
|
||||
diags.AddError("Unexpected HTTP status code downsizing disks",
|
||||
fmt.Sprintf("Received %s downsizing disks: server_id=%s, disk_id=%d. Details: %s",
|
||||
resp.Status(), state.Id.String(), id, resp.Body))
|
||||
return diags
|
||||
}
|
||||
err = r.waitForServerAction(ctx, state.Id.ValueInt64(), *resp.JSON200.Action.Id)
|
||||
if err != nil {
|
||||
diags.AddError("Error waiting for disks to downsize", err.Error())
|
||||
return diags
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Upsize disks
|
||||
for id, desiredDisk := range desiredMap {
|
||||
if currentDisk, ok := currentMap[id]; ok {
|
||||
curSize := int32(currentDisk.SizeGigabytes.ValueFloat64())
|
||||
newSize := int32(desiredDisk.SizeGigabytes.ValueFloat64())
|
||||
if newSize > curSize {
|
||||
tflog.Debug(ctx, "Upsizing disk", map[string]any{"disk_id": id, "from": curSize, "to": newSize})
|
||||
resp, err := r.bc.client.PostServersServerIdActionsResizeDiskWithResponse(ctx, state.Id.ValueInt64(), binarylane.ResizeDisk{
|
||||
DiskId: id,
|
||||
SizeGigabytes: newSize,
|
||||
Type: "resize_disk",
|
||||
})
|
||||
if err != nil {
|
||||
diags.AddError("Error upsizing disk", err.Error())
|
||||
return diags
|
||||
}
|
||||
err = r.waitForServerAction(ctx, state.Id.ValueInt64(), *resp.JSON200.Action.Id)
|
||||
if err != nil {
|
||||
diags.AddError("Error waiting for new disks to upsize", err.Error())
|
||||
return diags
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 5. Add new disks (those with no ID in desired)
|
||||
for _, desiredDisk := range desired {
|
||||
if desiredDisk.Id.IsNull() || desiredDisk.Id.IsUnknown() {
|
||||
desc := desiredDisk.Description.ValueStringPointer()
|
||||
tflog.Debug(ctx, "Creating new disk", map[string]any{"size": desiredDisk.SizeGigabytes.ValueFloat64()})
|
||||
resp, err := r.bc.client.PostServersServerIdActionsAddDiskWithResponse(ctx, state.Id.ValueInt64(), binarylane.AddDisk{
|
||||
Description: desc,
|
||||
SizeGigabytes: int32(desiredDisk.SizeGigabytes.ValueFloat64()),
|
||||
Type: "add_disk",
|
||||
})
|
||||
if err != nil {
|
||||
diags.AddError("Error creating disk", err.Error())
|
||||
return diags
|
||||
}
|
||||
err = r.waitForServerAction(ctx, state.Id.ValueInt64(), *resp.JSON200.Action.Id)
|
||||
if err != nil {
|
||||
diags.AddError("Error waiting for new disk to be added", err.Error())
|
||||
return diags
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return diags
|
||||
}
|
||||
|
||||
func (r *serverResource) fetchServerResourceState(ctx context.Context, state *serverResourceModel) diag.Diagnostics {
|
||||
var diags diag.Diagnostics
|
||||
|
||||
@@ -1282,10 +1488,16 @@ func (r *serverResource) fetchServerResourceState(ctx context.Context, state *se
|
||||
privateIpv4Addresses := []string{}
|
||||
|
||||
for _, v4address := range serverResp.JSON200.Server.Networks.V4 {
|
||||
if v4address.Type == "public" {
|
||||
switch v4address.Type {
|
||||
case "public":
|
||||
publicIpv4Addresses = append(publicIpv4Addresses, v4address.IpAddress)
|
||||
} else if v4address.Type == "private" {
|
||||
case "private":
|
||||
privateIpv4Addresses = append(privateIpv4Addresses, v4address.IpAddress)
|
||||
default:
|
||||
diags.AddError(
|
||||
"Unexpected IP address type",
|
||||
fmt.Sprintf("Received unexpected IP address type '%s' for server: id=%d, name=%s", v4address.Type, *serverResp.JSON200.Server.Id, *serverResp.JSON200.Server.Name),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1307,6 +1519,14 @@ func (r *serverResource) fetchServerResourceState(ctx context.Context, state *se
|
||||
state.PrivateIPv4Addresses = tfPrivateIpv4Addresses
|
||||
}
|
||||
|
||||
disks, diag := types.ListValueFrom(ctx, state.Disks.ElementType(ctx), serverResp.JSON200.Server.Disks)
|
||||
diags.Append(diag...)
|
||||
if diag.HasError() {
|
||||
state.Disks = types.ListUnknown(state.Disks.ElementType(ctx))
|
||||
} else {
|
||||
state.Disks = disks
|
||||
}
|
||||
|
||||
return diags
|
||||
}
|
||||
|
||||
|
||||
@@ -104,6 +104,11 @@ echo "Hello World" > /var/tmp/output.txt
|
||||
resource.TestCheckResourceAttr("binarylane_server.test", "advanced_features.cloud_init", "true"),
|
||||
resource.TestCheckResourceAttr("binarylane_server.test", "advanced_features.qemu_guest_agent", "false"),
|
||||
resource.TestCheckResourceAttr("binarylane_server.test", "advanced_features.uefi_boot", "false"),
|
||||
resource.TestCheckResourceAttr("binarylane_server.test", "disks.#", "1"),
|
||||
resource.TestCheckResourceAttrSet("binarylane_server.test", "disks.0.id"),
|
||||
resource.TestCheckResourceAttrSet("binarylane_server.test", "disks.0.description"),
|
||||
resource.TestCheckResourceAttr("binarylane_server.test", "disks.0.primary", "true"),
|
||||
resource.TestCheckResourceAttr("binarylane_server.test", "disks.0.size_gigabytes", "20"),
|
||||
|
||||
// Verify data source values
|
||||
resource.TestCheckResourceAttrPair("data.binarylane_server.test", "id", "binarylane_server.test", "id"),
|
||||
@@ -130,6 +135,11 @@ echo "Hello World" > /var/tmp/output.txt
|
||||
resource.TestCheckResourceAttr("data.binarylane_server.test", "advanced_features.cloud_init", "true"),
|
||||
resource.TestCheckResourceAttr("data.binarylane_server.test", "advanced_features.qemu_guest_agent", "false"),
|
||||
resource.TestCheckResourceAttr("data.binarylane_server.test", "advanced_features.uefi_boot", "false"),
|
||||
resource.TestCheckResourceAttr("data.binarylane_server.test", "disks.#", "1"),
|
||||
resource.TestCheckResourceAttrSet("data.binarylane_server.test", "disks.0.id"),
|
||||
resource.TestCheckResourceAttrSet("data.binarylane_server.test", "disks.0.description"),
|
||||
resource.TestCheckResourceAttr("data.binarylane_server.test", "disks.0.primary", "true"),
|
||||
resource.TestCheckResourceAttr("data.binarylane_server.test", "disks.0.size_gigabytes", "20"),
|
||||
),
|
||||
},
|
||||
// Test import by ID
|
||||
@@ -313,6 +323,85 @@ resource "binarylane_server" "test" {
|
||||
})
|
||||
}
|
||||
|
||||
func TestServerResourceDisks(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{
|
||||
// Create and Read testing
|
||||
{
|
||||
Config: providerConfig + `
|
||||
resource "binarylane_server" "test" {
|
||||
name = "tf-test-server-resource"
|
||||
region = "per"
|
||||
image = "debian-12"
|
||||
size = "std-min"
|
||||
password = "` + password + `"
|
||||
public_ipv4_count = 0
|
||||
disks = [
|
||||
{
|
||||
description = "Primary Disk"
|
||||
size_gigabytes = 9
|
||||
},
|
||||
{
|
||||
description = "Secondary Disk"
|
||||
size_gigabytes = 2
|
||||
},
|
||||
{
|
||||
description = "Tertiary Disk"
|
||||
size_gigabytes = 4
|
||||
}
|
||||
]
|
||||
}
|
||||
`,
|
||||
Check: resource.ComposeAggregateTestCheckFunc(
|
||||
resource.TestCheckResourceAttr("binarylane_server.test", "disks.#", "2"),
|
||||
resource.TestCheckResourceAttrSet("binarylane_server.test", "disks.0.id"),
|
||||
resource.TestCheckResourceAttr("binarylane_server.test", "disks.0.description", "Renamed Primary Disk"),
|
||||
resource.TestCheckResourceAttr("binarylane_server.test", "disks.0.primary", "true"),
|
||||
resource.TestCheckResourceAttr("binarylane_server.test", "disks.0.size_gigabytes", "10"),
|
||||
resource.TestCheckResourceAttrSet("binarylane_server.test", "disks.1.id"),
|
||||
resource.TestCheckResourceAttr("binarylane_server.test", "disks.1.description", "Secondary Disk"),
|
||||
resource.TestCheckResourceAttr("binarylane_server.test", "disks.1.primary", "false"),
|
||||
resource.TestCheckResourceAttr("binarylane_server.test", "disks.1.size_gigabytes", "5"),
|
||||
),
|
||||
},
|
||||
// Test import by ID
|
||||
{
|
||||
ResourceName: "binarylane_server.test",
|
||||
ImportState: true,
|
||||
ImportStateVerify: true,
|
||||
ImportStateVerifyIgnore: []string{"password", "ssh_keys", "timeouts"},
|
||||
},
|
||||
// Test import by ID
|
||||
{
|
||||
Config: providerConfig + `
|
||||
resource "binarylane_server" "test" {
|
||||
name = "tf-test-server-resource"
|
||||
region = "per"
|
||||
image = "debian-12"
|
||||
size = "std-min"
|
||||
password = "` + password + `"
|
||||
public_ipv4_count = 0
|
||||
disks = [
|
||||
{
|
||||
description = "Renamed Primary Disk"
|
||||
size_gigabytes = 10
|
||||
},
|
||||
{
|
||||
description = "Secondary Disk"
|
||||
size_gigabytes = 10
|
||||
}
|
||||
]
|
||||
}
|
||||
`,
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func GenerateTestPassword(t *testing.T) string {
|
||||
t.Helper()
|
||||
pwBytes := make([]byte, 12)
|
||||
|
||||
@@ -82,7 +82,7 @@ func (d *sshKeyDataSource) Schema(ctx context.Context, req datasource.SchemaRequ
|
||||
}
|
||||
|
||||
fingerprintDescription := "The fingerprint of the SSH key."
|
||||
resp.Schema.Attributes["fingerprint"] = &schema.StringAttribute{
|
||||
resp.Schema.Attributes["fingerprint"] = schema.StringAttribute{
|
||||
Description: fingerprintDescription,
|
||||
MarkdownDescription: fingerprintDescription,
|
||||
Optional: false,
|
||||
|
||||
@@ -105,7 +105,7 @@ func (r *sshKeyResource) Schema(ctx context.Context, req resource.SchemaRequest,
|
||||
}
|
||||
|
||||
fingerprintDescription := "The fingerprint of the SSH key."
|
||||
resp.Schema.Attributes["fingerprint"] = &schema.StringAttribute{
|
||||
resp.Schema.Attributes["fingerprint"] = schema.StringAttribute{
|
||||
Description: fingerprintDescription,
|
||||
MarkdownDescription: fingerprintDescription,
|
||||
Optional: false,
|
||||
|
||||
@@ -136,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,
|
||||
@@ -183,7 +183,6 @@ func convertResourceAttrToDataSourceAttr(name string, attribute r_schema.Attribu
|
||||
AttributeTypes: attributeTypes,
|
||||
}, nil
|
||||
}
|
||||
|
||||
if t, isObject := attribute.GetType().(types.ObjectType); isObject {
|
||||
return d_schema.ObjectAttribute{
|
||||
AttributeTypes: t.AttrTypes,
|
||||
|
||||
@@ -63,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
|
||||
@@ -73,7 +73,7 @@ func (r *vpcResource) Schema(ctx context.Context, req resource.SchemaRequest, re
|
||||
}
|
||||
|
||||
ipRange := resp.Schema.Attributes["ip_range"]
|
||||
resp.Schema.Attributes["ip_range"] = &schema.StringAttribute{
|
||||
resp.Schema.Attributes["ip_range"] = schema.StringAttribute{
|
||||
Description: ipRange.GetDescription(),
|
||||
MarkdownDescription: ipRange.GetMarkdownDescription(),
|
||||
Required: false,
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -94,6 +94,42 @@ func ServerResourceSchema(ctx context.Context) schema.Schema {
|
||||
Description: "If true this will enable two daily backups for the server. `options.daily_backups` will override this value if provided. Setting this to false has no effect.\n",
|
||||
MarkdownDescription: "If true this will enable two daily backups for the server. `options.daily_backups` will override this value if provided. Setting this to false has no effect.\n",
|
||||
},
|
||||
"disks": schema.ListNestedAttribute{
|
||||
NestedObject: schema.NestedAttributeObject{
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"description": schema.StringAttribute{
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
Description: "A description of this disk.",
|
||||
MarkdownDescription: "A description of this disk.",
|
||||
},
|
||||
"id": schema.Int64Attribute{
|
||||
Computed: true,
|
||||
Description: "The ID of this disk.",
|
||||
MarkdownDescription: "The ID of this disk.",
|
||||
},
|
||||
"primary": schema.BoolAttribute{
|
||||
Computed: true,
|
||||
Description: "A primary disk is treated differently from other disks.",
|
||||
MarkdownDescription: "A primary disk is treated differently from other disks.",
|
||||
},
|
||||
"size_gigabytes": schema.Float64Attribute{
|
||||
Required: true,
|
||||
Description: "The size of the disk in GB.",
|
||||
MarkdownDescription: "The size of the disk in GB.",
|
||||
},
|
||||
},
|
||||
CustomType: DisksType{
|
||||
ObjectType: types.ObjectType{
|
||||
AttrTypes: DisksValue{}.AttributeTypes(ctx),
|
||||
},
|
||||
},
|
||||
},
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
Description: "A list of the disks that are currently attached to the server.",
|
||||
MarkdownDescription: "A list of the disks that are currently attached to the server.",
|
||||
},
|
||||
"id": schema.Int64Attribute{
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
@@ -162,6 +198,7 @@ func ServerResourceSchema(ctx context.Context) schema.Schema {
|
||||
type ServerModel struct {
|
||||
AdvancedFeatures AdvancedFeaturesValue `tfsdk:"advanced_features"`
|
||||
Backups types.Bool `tfsdk:"backups"`
|
||||
Disks types.List `tfsdk:"disks"`
|
||||
Id types.Int64 `tfsdk:"id"`
|
||||
Image types.String `tfsdk:"image"`
|
||||
Name types.String `tfsdk:"name"`
|
||||
@@ -991,3 +1028,492 @@ func (v AdvancedFeaturesValue) AttributeTypes(ctx context.Context) map[string]at
|
||||
"unset_uuid": basetypes.BoolType{},
|
||||
}
|
||||
}
|
||||
|
||||
var _ basetypes.ObjectTypable = DisksType{}
|
||||
|
||||
type DisksType struct {
|
||||
basetypes.ObjectType
|
||||
}
|
||||
|
||||
func (t DisksType) Equal(o attr.Type) bool {
|
||||
other, ok := o.(DisksType)
|
||||
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
return t.ObjectType.Equal(other.ObjectType)
|
||||
}
|
||||
|
||||
func (t DisksType) String() string {
|
||||
return "DisksType"
|
||||
}
|
||||
|
||||
func (t DisksType) ValueFromObject(ctx context.Context, in basetypes.ObjectValue) (basetypes.ObjectValuable, diag.Diagnostics) {
|
||||
var diags diag.Diagnostics
|
||||
|
||||
attributes := in.Attributes()
|
||||
|
||||
descriptionAttribute, ok := attributes["description"]
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Missing",
|
||||
`description is missing from object`)
|
||||
|
||||
return nil, diags
|
||||
}
|
||||
|
||||
descriptionVal, ok := descriptionAttribute.(basetypes.StringValue)
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Wrong Type",
|
||||
fmt.Sprintf(`description expected to be basetypes.StringValue, was: %T`, descriptionAttribute))
|
||||
}
|
||||
|
||||
idAttribute, ok := attributes["id"]
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Missing",
|
||||
`id is missing from object`)
|
||||
|
||||
return nil, diags
|
||||
}
|
||||
|
||||
idVal, ok := idAttribute.(basetypes.Int64Value)
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Wrong Type",
|
||||
fmt.Sprintf(`id expected to be basetypes.Int64Value, was: %T`, idAttribute))
|
||||
}
|
||||
|
||||
primaryAttribute, ok := attributes["primary"]
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Missing",
|
||||
`primary is missing from object`)
|
||||
|
||||
return nil, diags
|
||||
}
|
||||
|
||||
primaryVal, ok := primaryAttribute.(basetypes.BoolValue)
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Wrong Type",
|
||||
fmt.Sprintf(`primary expected to be basetypes.BoolValue, was: %T`, primaryAttribute))
|
||||
}
|
||||
|
||||
sizeGigabytesAttribute, ok := attributes["size_gigabytes"]
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Missing",
|
||||
`size_gigabytes is missing from object`)
|
||||
|
||||
return nil, diags
|
||||
}
|
||||
|
||||
sizeGigabytesVal, ok := sizeGigabytesAttribute.(basetypes.Float64Value)
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Wrong Type",
|
||||
fmt.Sprintf(`size_gigabytes expected to be basetypes.Float64Value, was: %T`, sizeGigabytesAttribute))
|
||||
}
|
||||
|
||||
if diags.HasError() {
|
||||
return nil, diags
|
||||
}
|
||||
|
||||
return DisksValue{
|
||||
Description: descriptionVal,
|
||||
Id: idVal,
|
||||
Primary: primaryVal,
|
||||
SizeGigabytes: sizeGigabytesVal,
|
||||
state: attr.ValueStateKnown,
|
||||
}, diags
|
||||
}
|
||||
|
||||
func NewDisksValueNull() DisksValue {
|
||||
return DisksValue{
|
||||
state: attr.ValueStateNull,
|
||||
}
|
||||
}
|
||||
|
||||
func NewDisksValueUnknown() DisksValue {
|
||||
return DisksValue{
|
||||
state: attr.ValueStateUnknown,
|
||||
}
|
||||
}
|
||||
|
||||
func NewDisksValue(attributeTypes map[string]attr.Type, attributes map[string]attr.Value) (DisksValue, 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 DisksValue Attribute Value",
|
||||
"While creating a DisksValue value, a missing attribute value was detected. "+
|
||||
"A DisksValue 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("DisksValue Attribute Name (%s) Expected Type: %s", name, attributeType.String()),
|
||||
)
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
if !attributeType.Equal(attribute.Type(ctx)) {
|
||||
diags.AddError(
|
||||
"Invalid DisksValue Attribute Type",
|
||||
"While creating a DisksValue value, an invalid attribute value was detected. "+
|
||||
"A DisksValue 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("DisksValue Attribute Name (%s) Expected Type: %s\n", name, attributeType.String())+
|
||||
fmt.Sprintf("DisksValue Attribute Name (%s) Given Type: %s", name, attribute.Type(ctx)),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
for name := range attributes {
|
||||
_, ok := attributeTypes[name]
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Extra DisksValue Attribute Value",
|
||||
"While creating a DisksValue value, an extra attribute value was detected. "+
|
||||
"A DisksValue 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 DisksValue Attribute Name: %s", name),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if diags.HasError() {
|
||||
return NewDisksValueUnknown(), diags
|
||||
}
|
||||
|
||||
descriptionAttribute, ok := attributes["description"]
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Missing",
|
||||
`description is missing from object`)
|
||||
|
||||
return NewDisksValueUnknown(), diags
|
||||
}
|
||||
|
||||
descriptionVal, ok := descriptionAttribute.(basetypes.StringValue)
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Wrong Type",
|
||||
fmt.Sprintf(`description expected to be basetypes.StringValue, was: %T`, descriptionAttribute))
|
||||
}
|
||||
|
||||
idAttribute, ok := attributes["id"]
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Missing",
|
||||
`id is missing from object`)
|
||||
|
||||
return NewDisksValueUnknown(), diags
|
||||
}
|
||||
|
||||
idVal, ok := idAttribute.(basetypes.Int64Value)
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Wrong Type",
|
||||
fmt.Sprintf(`id expected to be basetypes.Int64Value, was: %T`, idAttribute))
|
||||
}
|
||||
|
||||
primaryAttribute, ok := attributes["primary"]
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Missing",
|
||||
`primary is missing from object`)
|
||||
|
||||
return NewDisksValueUnknown(), diags
|
||||
}
|
||||
|
||||
primaryVal, ok := primaryAttribute.(basetypes.BoolValue)
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Wrong Type",
|
||||
fmt.Sprintf(`primary expected to be basetypes.BoolValue, was: %T`, primaryAttribute))
|
||||
}
|
||||
|
||||
sizeGigabytesAttribute, ok := attributes["size_gigabytes"]
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Missing",
|
||||
`size_gigabytes is missing from object`)
|
||||
|
||||
return NewDisksValueUnknown(), diags
|
||||
}
|
||||
|
||||
sizeGigabytesVal, ok := sizeGigabytesAttribute.(basetypes.Float64Value)
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Wrong Type",
|
||||
fmt.Sprintf(`size_gigabytes expected to be basetypes.Float64Value, was: %T`, sizeGigabytesAttribute))
|
||||
}
|
||||
|
||||
if diags.HasError() {
|
||||
return NewDisksValueUnknown(), diags
|
||||
}
|
||||
|
||||
return DisksValue{
|
||||
Description: descriptionVal,
|
||||
Id: idVal,
|
||||
Primary: primaryVal,
|
||||
SizeGigabytes: sizeGigabytesVal,
|
||||
state: attr.ValueStateKnown,
|
||||
}, diags
|
||||
}
|
||||
|
||||
func NewDisksValueMust(attributeTypes map[string]attr.Type, attributes map[string]attr.Value) DisksValue {
|
||||
object, diags := NewDisksValue(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("NewDisksValueMust received error(s): " + strings.Join(diagsStrings, "\n"))
|
||||
}
|
||||
|
||||
return object
|
||||
}
|
||||
|
||||
func (t DisksType) ValueFromTerraform(ctx context.Context, in tftypes.Value) (attr.Value, error) {
|
||||
if in.Type() == nil {
|
||||
return NewDisksValueNull(), 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 NewDisksValueUnknown(), nil
|
||||
}
|
||||
|
||||
if in.IsNull() {
|
||||
return NewDisksValueNull(), 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 NewDisksValueMust(DisksValue{}.AttributeTypes(ctx), attributes), nil
|
||||
}
|
||||
|
||||
func (t DisksType) ValueType(ctx context.Context) attr.Value {
|
||||
return DisksValue{}
|
||||
}
|
||||
|
||||
var _ basetypes.ObjectValuable = DisksValue{}
|
||||
|
||||
type DisksValue struct {
|
||||
Description basetypes.StringValue `tfsdk:"description"`
|
||||
Id basetypes.Int64Value `tfsdk:"id"`
|
||||
Primary basetypes.BoolValue `tfsdk:"primary"`
|
||||
SizeGigabytes basetypes.Float64Value `tfsdk:"size_gigabytes"`
|
||||
state attr.ValueState
|
||||
}
|
||||
|
||||
func (v DisksValue) ToTerraformValue(ctx context.Context) (tftypes.Value, error) {
|
||||
attrTypes := make(map[string]tftypes.Type, 4)
|
||||
|
||||
var val tftypes.Value
|
||||
var err error
|
||||
|
||||
attrTypes["description"] = basetypes.StringType{}.TerraformType(ctx)
|
||||
attrTypes["id"] = basetypes.Int64Type{}.TerraformType(ctx)
|
||||
attrTypes["primary"] = basetypes.BoolType{}.TerraformType(ctx)
|
||||
attrTypes["size_gigabytes"] = basetypes.Float64Type{}.TerraformType(ctx)
|
||||
|
||||
objectType := tftypes.Object{AttributeTypes: attrTypes}
|
||||
|
||||
switch v.state {
|
||||
case attr.ValueStateKnown:
|
||||
vals := make(map[string]tftypes.Value, 4)
|
||||
|
||||
val, err = v.Description.ToTerraformValue(ctx)
|
||||
|
||||
if err != nil {
|
||||
return tftypes.NewValue(objectType, tftypes.UnknownValue), err
|
||||
}
|
||||
|
||||
vals["description"] = val
|
||||
|
||||
val, err = v.Id.ToTerraformValue(ctx)
|
||||
|
||||
if err != nil {
|
||||
return tftypes.NewValue(objectType, tftypes.UnknownValue), err
|
||||
}
|
||||
|
||||
vals["id"] = val
|
||||
|
||||
val, err = v.Primary.ToTerraformValue(ctx)
|
||||
|
||||
if err != nil {
|
||||
return tftypes.NewValue(objectType, tftypes.UnknownValue), err
|
||||
}
|
||||
|
||||
vals["primary"] = val
|
||||
|
||||
val, err = v.SizeGigabytes.ToTerraformValue(ctx)
|
||||
|
||||
if err != nil {
|
||||
return tftypes.NewValue(objectType, tftypes.UnknownValue), err
|
||||
}
|
||||
|
||||
vals["size_gigabytes"] = 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 DisksValue) IsNull() bool {
|
||||
return v.state == attr.ValueStateNull
|
||||
}
|
||||
|
||||
func (v DisksValue) IsUnknown() bool {
|
||||
return v.state == attr.ValueStateUnknown
|
||||
}
|
||||
|
||||
func (v DisksValue) String() string {
|
||||
return "DisksValue"
|
||||
}
|
||||
|
||||
func (v DisksValue) ToObjectValue(ctx context.Context) (basetypes.ObjectValue, diag.Diagnostics) {
|
||||
var diags diag.Diagnostics
|
||||
|
||||
attributeTypes := map[string]attr.Type{
|
||||
"description": basetypes.StringType{},
|
||||
"id": basetypes.Int64Type{},
|
||||
"primary": basetypes.BoolType{},
|
||||
"size_gigabytes": basetypes.Float64Type{},
|
||||
}
|
||||
|
||||
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{
|
||||
"description": v.Description,
|
||||
"id": v.Id,
|
||||
"primary": v.Primary,
|
||||
"size_gigabytes": v.SizeGigabytes,
|
||||
})
|
||||
|
||||
return objVal, diags
|
||||
}
|
||||
|
||||
func (v DisksValue) Equal(o attr.Value) bool {
|
||||
other, ok := o.(DisksValue)
|
||||
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
if v.state != other.state {
|
||||
return false
|
||||
}
|
||||
|
||||
if v.state != attr.ValueStateKnown {
|
||||
return true
|
||||
}
|
||||
|
||||
if !v.Description.Equal(other.Description) {
|
||||
return false
|
||||
}
|
||||
|
||||
if !v.Id.Equal(other.Id) {
|
||||
return false
|
||||
}
|
||||
|
||||
if !v.Primary.Equal(other.Primary) {
|
||||
return false
|
||||
}
|
||||
|
||||
if !v.SizeGigabytes.Equal(other.SizeGigabytes) {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (v DisksValue) Type(ctx context.Context) attr.Type {
|
||||
return DisksType{
|
||||
basetypes.ObjectType{
|
||||
AttrTypes: v.AttributeTypes(ctx),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (v DisksValue) AttributeTypes(ctx context.Context) map[string]attr.Type {
|
||||
return map[string]attr.Type{
|
||||
"description": basetypes.StringType{},
|
||||
"id": basetypes.Int64Type{},
|
||||
"primary": basetypes.BoolType{},
|
||||
"size_gigabytes": basetypes.Float64Type{},
|
||||
}
|
||||
}
|
||||
|
||||
+78
-35
@@ -8,7 +8,7 @@
|
||||
"url": "https://support.binarylane.com.au",
|
||||
"email": "support@binarylane.com.au"
|
||||
},
|
||||
"version": "0.32.0",
|
||||
"version": "0.32.1",
|
||||
"x-logo": {
|
||||
"url": "https://www.binarylane.com.au/res/images/binarylane/logo.png",
|
||||
"backgroundColor": "#000000",
|
||||
@@ -7590,7 +7590,7 @@
|
||||
"forwarding_rules": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/ForwardingRule"
|
||||
"$ref": "#/components/schemas/ForwardingRuleRequest"
|
||||
},
|
||||
"description": "The rules that control which traffic the load balancer will forward to servers in the pool. Leave null to accept a default \"HTTP\" only forwarding rule.",
|
||||
"nullable": true,
|
||||
@@ -7601,7 +7601,7 @@
|
||||
"health_check": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/HealthCheck"
|
||||
"$ref": "#/components/schemas/HealthCheckRequest"
|
||||
}
|
||||
],
|
||||
"description": "The rules that determine which servers are considered 'healthy' and in the server pool for the load balancer. Leave this null to accept appropriate defaults based on the forwarding_rules.",
|
||||
@@ -7995,24 +7995,36 @@
|
||||
"type": "integer",
|
||||
"description": "The ID of this disk.",
|
||||
"format": "int64",
|
||||
"readOnly": true
|
||||
"readOnly": true,
|
||||
"x-oapi-codegen-extra-tags": {
|
||||
"tfsdk": "id"
|
||||
}
|
||||
},
|
||||
"size_gigabytes": {
|
||||
"type": "number",
|
||||
"description": "The size of the disk in GB.",
|
||||
"format": "double",
|
||||
"readOnly": true
|
||||
"readOnly": true,
|
||||
"x-oapi-codegen-extra-tags": {
|
||||
"tfsdk": "size_gigabytes"
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"description": "A description of this disk.",
|
||||
"nullable": true,
|
||||
"readOnly": true
|
||||
"readOnly": true,
|
||||
"x-oapi-codegen-extra-tags": {
|
||||
"tfsdk": "description"
|
||||
}
|
||||
},
|
||||
"primary": {
|
||||
"type": "boolean",
|
||||
"description": "A primary disk is treated differently from other disks.",
|
||||
"readOnly": true
|
||||
"readOnly": true,
|
||||
"x-oapi-codegen-extra-tags": {
|
||||
"tfsdk": "primary"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -8542,6 +8554,25 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"ForwardingRuleRequest": {
|
||||
"required": [
|
||||
"entry_protocol"
|
||||
],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"entry_protocol": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/LoadBalancerRuleProtocol"
|
||||
}
|
||||
],
|
||||
"description": "The protocol that traffic must match for this load balancer to forward traffic according to this rule.\n\n| Value | Description |\n| ----- | ----------- |\n| http | The load balancer will forward HTTP traffic that matches this rule. |\n| https | The load balancer will forward HTTPS traffic that matches this rule. |\n\n",
|
||||
"x-oapi-codegen-extra-tags": {
|
||||
"tfsdk": "entry_protocol"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"ForwardingRulesRequest": {
|
||||
"required": [
|
||||
"forwarding_rules"
|
||||
@@ -8551,13 +8582,44 @@
|
||||
"forwarding_rules": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/ForwardingRule"
|
||||
"$ref": "#/components/schemas/ForwardingRuleRequest"
|
||||
},
|
||||
"description": "The rules that control which traffic the load balancer will forward to servers in the pool."
|
||||
}
|
||||
}
|
||||
},
|
||||
"HealthCheck": {
|
||||
"required": [
|
||||
"path",
|
||||
"protocol"
|
||||
],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"protocol": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/HealthCheckProtocol"
|
||||
}
|
||||
],
|
||||
"description": "The protocol used for the health check.\n\n| Value | Description |\n| ----- | ----------- |\n| http | The health check will be performed via HTTP. |\n| https | The health check will be performed via HTTPS. |\n| both | The health check will be performed via both HTTP and HTTPS. Failing a health check on one protocol will remove the server from the pool of servers only for that protocol. |\n\n"
|
||||
},
|
||||
"path": {
|
||||
"minLength": 1,
|
||||
"type": "string",
|
||||
"description": "The path to the health check endpoint."
|
||||
}
|
||||
}
|
||||
},
|
||||
"HealthCheckProtocol": {
|
||||
"type": "string",
|
||||
"description": "\n| Value | Description |\n| ----- | ----------- |\n| http | The health check will be performed via HTTP. |\n| https | The health check will be performed via HTTPS. |\n| both | The health check will be performed via both HTTP and HTTPS. Failing a health check on one protocol will remove the server from the pool of servers only for that protocol. |\n\n",
|
||||
"x-enum-descriptions": [
|
||||
"The health check will be performed via HTTP.",
|
||||
"The health check will be performed via HTTPS.",
|
||||
"The health check will be performed via both HTTP and HTTPS. Failing a health check on one protocol will remove the server from the pool of servers only for that protocol."
|
||||
]
|
||||
},
|
||||
"HealthCheckRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"protocol": {
|
||||
@@ -8577,15 +8639,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"HealthCheckProtocol": {
|
||||
"type": "string",
|
||||
"description": "\n| Value | Description |\n| ----- | ----------- |\n| http | The health check will be performed via HTTP. |\n| https | The health check will be performed via HTTPS. |\n| both | The health check will be performed via both HTTP and HTTPS. Failing a health check on one protocol will remove the server from the pool of servers only for that protocol. |\n\n",
|
||||
"x-enum-descriptions": [
|
||||
"The health check will be performed via HTTP.",
|
||||
"The health check will be performed via HTTPS.",
|
||||
"The health check will be performed via both HTTP and HTTPS. Failing a health check on one protocol will remove the server from the pool of servers only for that protocol."
|
||||
]
|
||||
},
|
||||
"Host": {
|
||||
"required": [
|
||||
"display_name"
|
||||
@@ -9380,21 +9433,18 @@
|
||||
"type": "integer",
|
||||
"description": "The ID of the load balancer.",
|
||||
"format": "int64",
|
||||
"readOnly": true,
|
||||
"x-cli-format": 1
|
||||
},
|
||||
"name": {
|
||||
"minLength": 1,
|
||||
"type": "string",
|
||||
"description": "The hostname of the load balancer.",
|
||||
"readOnly": true,
|
||||
"x-cli-format": 2
|
||||
},
|
||||
"ip": {
|
||||
"minLength": 1,
|
||||
"type": "string",
|
||||
"description": "The IPv4 address of the load balancer.",
|
||||
"readOnly": true,
|
||||
"x-cli-format": 4
|
||||
},
|
||||
"status": {
|
||||
@@ -9403,21 +9453,19 @@
|
||||
"$ref": "#/components/schemas/LoadBalancerStatus"
|
||||
}
|
||||
],
|
||||
"readOnly": true
|
||||
"description": "The current status of the load balancer.\n\n| Value | Description |\n| ----- | ----------- |\n| new | The load balancer is currently being built and is not ready to accept connections. |\n| active | The load balancer is available. |\n| errored | The load balancer is in an errored state. |\n\n"
|
||||
},
|
||||
"created_at": {
|
||||
"type": "string",
|
||||
"description": "The date and time in ISO8601 format of the creation of the load balancer.",
|
||||
"format": "date-time",
|
||||
"readOnly": true
|
||||
"format": "date-time"
|
||||
},
|
||||
"forwarding_rules": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/ForwardingRule"
|
||||
},
|
||||
"description": "The rules that control which traffic the load balancer will forward to servers in the pool.",
|
||||
"readOnly": true
|
||||
"description": "The rules that control which traffic the load balancer will forward to servers in the pool."
|
||||
},
|
||||
"health_check": {
|
||||
"allOf": [
|
||||
@@ -9426,7 +9474,6 @@
|
||||
}
|
||||
],
|
||||
"description": "The rules that determine which servers are considered 'healthy' and in the server pool for the load balancer.",
|
||||
"readOnly": true,
|
||||
"x-oapi-codegen-extra-tags": {
|
||||
"tfsdk": "health_check"
|
||||
}
|
||||
@@ -9439,7 +9486,6 @@
|
||||
],
|
||||
"description": "The region the load balancer is located in. If this value is null the load balancer is an 'AnyCast' load balancer.",
|
||||
"nullable": true,
|
||||
"readOnly": true,
|
||||
"x-cli-format": 3
|
||||
},
|
||||
"server_ids": {
|
||||
@@ -9448,8 +9494,7 @@
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"description": "The server IDs of the servers that are currently in the load balancer pool (regardless of their current 'health').",
|
||||
"readOnly": true
|
||||
"description": "The server IDs of the servers that are currently in the load balancer pool (regardless of their current 'health')."
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -9467,8 +9512,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"description": "The slugs of regions where this load balancer option is available. If this is an Anycast load balancer option this will be null.",
|
||||
"nullable": true,
|
||||
"readOnly": true
|
||||
"nullable": true
|
||||
},
|
||||
"anycast": {
|
||||
"type": "boolean",
|
||||
@@ -9478,8 +9522,7 @@
|
||||
"price_monthly": {
|
||||
"type": "number",
|
||||
"description": "Monthly Price in AU$.",
|
||||
"format": "double",
|
||||
"readOnly": true
|
||||
"format": "double"
|
||||
},
|
||||
"price_hourly": {
|
||||
"type": "number",
|
||||
@@ -12290,7 +12333,7 @@
|
||||
"forwarding_rules": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/ForwardingRule"
|
||||
"$ref": "#/components/schemas/ForwardingRuleRequest"
|
||||
},
|
||||
"description": "The rules that control which traffic the load balancer will forward to servers in the pool. Leave null to accept a default \"HTTP\" only forwarding rule.",
|
||||
"nullable": true
|
||||
@@ -12298,7 +12341,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.",
|
||||
|
||||
+40
-1
@@ -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": {
|
||||
@@ -1006,6 +1006,45 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "disks",
|
||||
"list_nested": {
|
||||
"computed_optional_required": "computed_optional",
|
||||
"nested_object": {
|
||||
"attributes": [
|
||||
{
|
||||
"name": "description",
|
||||
"string": {
|
||||
"computed_optional_required": "computed_optional",
|
||||
"description": "A description of this disk."
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "id",
|
||||
"int64": {
|
||||
"computed_optional_required": "computed",
|
||||
"description": "The ID of this disk."
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "primary",
|
||||
"bool": {
|
||||
"computed_optional_required": "computed",
|
||||
"description": "A primary disk is treated differently from other disks."
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "size_gigabytes",
|
||||
"float64": {
|
||||
"computed_optional_required": "required",
|
||||
"description": "The size of the disk in GB."
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"description": "A list of the disks that are currently attached to the server."
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"name": "disks",
|
||||
"list_nested": {
|
||||
"computed_optional_required": "computed_optional",
|
||||
"nested_object": {
|
||||
"attributes": [
|
||||
{
|
||||
"name": "description",
|
||||
"string": {
|
||||
"computed_optional_required": "computed_optional",
|
||||
"description": "A description of this disk."
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "id",
|
||||
"int64": {
|
||||
"computed_optional_required": "computed",
|
||||
"description": "The ID of this disk."
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "primary",
|
||||
"bool": {
|
||||
"computed_optional_required": "computed",
|
||||
"description": "A primary disk is treated differently from other disks."
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "size_gigabytes",
|
||||
"float64": {
|
||||
"computed_optional_required": "required",
|
||||
"description": "The size of the disk in GB."
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"description": "A list of the disks that are currently attached to the server."
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,9 @@
|
||||
|
||||
GENERATOR_CONFIG=$(dirname "$0")/../provider_code_spec.json
|
||||
|
||||
# Advanced features configuration
|
||||
ADVANCED_FEATURES_CONFIG=$(dirname "$0")/data/advanced_features.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
|
||||
|
||||
DISKS_CONFIG=$(dirname "$0")/data/server_disks.json
|
||||
cat <<<$(jq --tab --slurpfile disks_cfg $DISKS_CONFIG '.resources[1].schema.attributes |= . + $disks_cfg' $GENERATOR_CONFIG) >$GENERATOR_CONFIG
|
||||
|
||||
@@ -59,6 +59,7 @@ cat <<<$(jq '.components.schemas.AdvancedFirewallRuleRequest.properties.source_a
|
||||
## Load Balancer
|
||||
cat <<<$(jq '.components.schemas.CreateLoadBalancerRequest.properties.forwarding_rules += {"x-oapi-codegen-extra-tags": {"tfsdk": "forwarding_rules"}}' $OPENAPI_FILE) >$OPENAPI_FILE
|
||||
cat <<<$(jq '.components.schemas.ForwardingRule.properties.entry_protocol += {"x-oapi-codegen-extra-tags": {"tfsdk": "entry_protocol"}}' $OPENAPI_FILE) >$OPENAPI_FILE
|
||||
cat <<<$(jq '.components.schemas.ForwardingRuleRequest.properties.entry_protocol += {"x-oapi-codegen-extra-tags": {"tfsdk": "entry_protocol"}}' $OPENAPI_FILE) >$OPENAPI_FILE
|
||||
cat <<<$(jq '.components.schemas.LoadBalancer.properties.health_check += {"x-oapi-codegen-extra-tags": {"tfsdk": "health_check"}}' $OPENAPI_FILE) >$OPENAPI_FILE
|
||||
cat <<<$(jq '.components.schemas.HealthCheckProtocol |= del(.enum)' $OPENAPI_FILE) >$OPENAPI_FILE
|
||||
|
||||
@@ -141,5 +142,11 @@ cat <<<$(jq '.components.schemas.SizeType.properties.slug += {"x-oapi-codegen-ex
|
||||
cat <<<$(jq '.components.schemas.SizeType.properties.name += {"x-oapi-codegen-extra-tags": {"tfsdk": "name"}}' $OPENAPI_FILE) >$OPENAPI_FILE
|
||||
cat <<<$(jq '.components.schemas.SizeType.properties.description += {"x-oapi-codegen-extra-tags": {"tfsdk": "description"}}' $OPENAPI_FILE) >$OPENAPI_FILE
|
||||
|
||||
## Disks
|
||||
cat <<<$(jq '.components.schemas.Disk.properties.id += {"x-oapi-codegen-extra-tags": {"tfsdk": "id"}}' $OPENAPI_FILE) >$OPENAPI_FILE
|
||||
cat <<<$(jq '.components.schemas.Disk.properties.description += {"x-oapi-codegen-extra-tags": {"tfsdk": "description"}}' $OPENAPI_FILE) >$OPENAPI_FILE
|
||||
cat <<<$(jq '.components.schemas.Disk.properties.primary += {"x-oapi-codegen-extra-tags": {"tfsdk": "primary"}}' $OPENAPI_FILE) >$OPENAPI_FILE
|
||||
cat <<<$(jq '.components.schemas.Disk.properties.size_gigabytes += {"x-oapi-codegen-extra-tags": {"tfsdk": "size_gigabytes"}}' $OPENAPI_FILE) >$OPENAPI_FILE
|
||||
|
||||
# Edit description here because it's hard to override nested schema properties
|
||||
cat <<<$(jq '.components.schemas.ForwardingRule.properties.entry_protocol.description = "The protocol that traffic must match for the load balancer to forward it. Valid values are \"http\" and \"https\"."' $OPENAPI_FILE) >$OPENAPI_FILE
|
||||
|
||||
Reference in New Issue
Block a user