mirror of
https://github.com/oscarhermoso/terraform-provider-binarylane
synced 2026-10-19 21:49:15 +11:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 32e9056957 | |||
| 325b2e96ea |
@@ -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
|
||||
|
||||
@@ -39,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.
|
||||
|
||||
@@ -53,7 +53,12 @@ resource "binarylane_load_balancer" "example" {
|
||||
|
||||
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
|
||||
}]
|
||||
}
|
||||
|
||||
@@ -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"`
|
||||
|
||||
@@ -154,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() {
|
||||
@@ -175,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(),
|
||||
}
|
||||
@@ -320,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() {
|
||||
@@ -339,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(),
|
||||
},
|
||||
@@ -442,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
|
||||
@@ -456,24 +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 *loadBalancerDataModel, lb *binarylane.LoadBalancer) diag.Diagnostics {
|
||||
var diags, diag diag.Diagnostics
|
||||
|
||||
data.Id = types.Int64Value(*lb.Id)
|
||||
data.Name = types.StringValue(*lb.Name)
|
||||
data.Ip = types.StringValue(*lb.Ip)
|
||||
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()
|
||||
@@ -483,18 +475,14 @@ func setLoadBalancerModelState(ctx context.Context, data *loadBalancerDataModel,
|
||||
|
||||
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)},
|
||||
|
||||
@@ -180,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 {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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