Extend network resource fields (#576)
* deprecate nameservers filed * onboard routed field * onboard new ipv4 fields * onboard new ipv6 fields * update examples * update examples * update examples * remove nameserver(deprecated) mapping * make fields computed * Revert "remove nameserver(deprecated) mapping" This reverts commit e4bf1dc184289f3bddc10c5d3b2320966b529649. * remove routed from update payload (not yet supported) * Update docs/resources/network.md Co-authored-by: João Palet <joao.palet@outlook.com> * Update stackit/internal/services/iaas/network/resource.go Co-authored-by: João Palet <joao.palet@outlook.com> * fix the field descriptions * remove ipv6 from examples * use nameservers as rollback value to support deprecated field * extend acceptance tests * add condition that nameserver and ipv4_nameserver cannot be provided at the same time * extend acc test * improve conditions in create payload * adapt modify plan to support update and delete operations * fix acceptance test * deprecate prefixes and create ipv4_prefixes field * fix unit tests * fix update issues * fix linter issues * extend modifyPlan condition * add validateConfig function * Update stackit/internal/services/iaas/network/resource.go Co-authored-by: João Palet <joao.palet@outlook.com> * Update stackit/internal/services/iaas/network/resource.go Co-authored-by: João Palet <joao.palet@outlook.com> * update descriptions * Update stackit/internal/services/iaas/network/resource.go Co-authored-by: João Palet <joao.palet@outlook.com> * Update stackit/internal/services/iaas/network/resource.go Co-authored-by: João Palet <joao.palet@outlook.com> * implement no_gateway field and condition check * implement no_ipv6_gateway field and condition check * update examples * update examples and descriptions * fix linter issues * Update stackit/internal/services/iaas/network/resource.go Co-authored-by: João Palet <joao.palet@outlook.com> * adapt descriptions * apply acceptance comments * adapt conditions in create and update * add plan modifiers * add requiresReplace --------- Co-authored-by: João Palet <joao.palet@outlook.com>
This commit is contained in:
parent
3ac1d50253
commit
b1fb9ab9b6
7 changed files with 857 additions and 60 deletions
|
|
@ -30,9 +30,19 @@ data "stackit_network" "example" {
|
|||
### Read-Only
|
||||
|
||||
- `id` (String) Terraform's internal resource ID. It is structured as "`project_id`,`network_id`".
|
||||
- `ipv4_gateway` (String) The IPv4 gateway of a network. If not specified, the first IP of the network will be assigned as the gateway.
|
||||
- `ipv4_nameservers` (List of String) The IPv4 nameservers of the network.
|
||||
- `ipv4_prefix` (String) The IPv4 prefix of the network (CIDR).
|
||||
- `ipv4_prefix_length` (Number) The IPv4 prefix length of the network.
|
||||
- `ipv4_prefixes` (List of String) The IPv4 prefixes of the network.
|
||||
- `ipv6_gateway` (String) The IPv6 gateway of a network. If not specified, the first IP of the network will be assigned as the gateway.
|
||||
- `ipv6_nameservers` (List of String) The IPv6 nameservers of the network.
|
||||
- `ipv6_prefix` (String) The IPv6 prefix of the network (CIDR).
|
||||
- `ipv6_prefix_length` (Number) The IPv6 prefix length of the network.
|
||||
- `ipv6_prefixes` (List of String) The IPv6 prefixes of the network.
|
||||
- `labels` (Map of String) Labels are key-value string pairs which can be attached to a resource container
|
||||
- `name` (String) The name of the network.
|
||||
- `nameservers` (List of String) The nameservers of the network.
|
||||
- `prefixes` (List of String) The prefixes of the network.
|
||||
- `nameservers` (List of String, Deprecated) The nameservers of the network. This field is deprecated and will be removed soon, use `ipv4_nameservers` to configure the nameservers for IPv4.
|
||||
- `prefixes` (List of String, Deprecated) The prefixes of the network. This field is deprecated and will be removed soon, use `ipv4_prefixes` to read the prefixes of the IPv4 networks.
|
||||
- `public_ip` (String) The public IP of the network.
|
||||
- `routed` (Boolean) Shows if the network is routed and therefore accessible from other networks.
|
||||
|
|
|
|||
|
|
@ -13,14 +13,31 @@ Network resource schema. Must have a `region` specified in the provider configur
|
|||
## Example Usage
|
||||
|
||||
```terraform
|
||||
resource "stackit_network" "example" {
|
||||
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||
name = "example-network"
|
||||
nameservers = ["1.2.3.4", "5.6.7.8"]
|
||||
ipv4_prefix_length = 24
|
||||
resource "stackit_network" "example_with_name" {
|
||||
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||
name = "example-with-name"
|
||||
}
|
||||
|
||||
resource "stackit_network" "example_routed_network" {
|
||||
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||
name = "example-routed-network"
|
||||
labels = {
|
||||
"key" = "value"
|
||||
}
|
||||
routed = true
|
||||
}
|
||||
|
||||
resource "stackit_network" "example_non_routed_network" {
|
||||
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||
name = "example-non-routed-network"
|
||||
ipv4_nameservers = ["1.2.3.4", "5.6.7.8"]
|
||||
ipv4_prefix_length = 24
|
||||
ipv4_gateway = "10.1.2.3"
|
||||
ipv4_prefix = "10.1.2.0/24"
|
||||
labels = {
|
||||
"key" = "value"
|
||||
}
|
||||
routed = false
|
||||
}
|
||||
```
|
||||
|
||||
|
|
@ -34,13 +51,25 @@ resource "stackit_network" "example" {
|
|||
|
||||
### Optional
|
||||
|
||||
- `ipv4_gateway` (String) The IPv4 gateway of a network. If not specified, the first IP of the network will be assigned as the gateway.
|
||||
- `ipv4_nameservers` (List of String) The IPv4 nameservers of the network.
|
||||
- `ipv4_prefix` (String) The IPv4 prefix of the network (CIDR).
|
||||
- `ipv4_prefix_length` (Number) The IPv4 prefix length of the network.
|
||||
- `ipv6_gateway` (String) The IPv6 gateway of a network. If not specified, the first IP of the network will be assigned as the gateway.
|
||||
- `ipv6_nameservers` (List of String) The IPv6 nameservers of the network.
|
||||
- `ipv6_prefix` (String) The IPv6 prefix of the network (CIDR).
|
||||
- `ipv6_prefix_length` (Number) The IPv6 prefix length of the network.
|
||||
- `labels` (Map of String) Labels are key-value string pairs which can be attached to a resource container
|
||||
- `nameservers` (List of String) The nameservers of the network.
|
||||
- `nameservers` (List of String, Deprecated) The nameservers of the network. This field is deprecated and will be removed soon, use `ipv4_nameservers` to configure the nameservers for IPv4.
|
||||
- `no_ipv4_gateway` (Boolean) If set to `true`, the network doesn't have a gateway.
|
||||
- `no_ipv6_gateway` (Boolean) If set to `true`, the network doesn't have a gateway.
|
||||
- `routed` (Boolean) If set to `true`, the network is routed and therefore accessible from other networks.
|
||||
|
||||
### Read-Only
|
||||
|
||||
- `id` (String) Terraform's internal resource ID. It is structured as "`project_id`,`network_id`".
|
||||
- `ipv4_prefixes` (List of String) The IPv4 prefixes of the network.
|
||||
- `ipv6_prefixes` (List of String) The IPv6 prefixes of the network.
|
||||
- `network_id` (String) The network ID.
|
||||
- `prefixes` (List of String) The prefixes of the network.
|
||||
- `prefixes` (List of String, Deprecated) The prefixes of the network. This field is deprecated and will be removed soon, use `ipv4_prefixes` to read the prefixes of the IPv4 networks.
|
||||
- `public_ip` (String) The public IP of the network.
|
||||
|
|
|
|||
|
|
@ -1,9 +1,26 @@
|
|||
resource "stackit_network" "example" {
|
||||
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||
name = "example-network"
|
||||
nameservers = ["1.2.3.4", "5.6.7.8"]
|
||||
ipv4_prefix_length = 24
|
||||
resource "stackit_network" "example_with_name" {
|
||||
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||
name = "example-with-name"
|
||||
}
|
||||
|
||||
resource "stackit_network" "example_routed_network" {
|
||||
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||
name = "example-routed-network"
|
||||
labels = {
|
||||
"key" = "value"
|
||||
}
|
||||
routed = true
|
||||
}
|
||||
|
||||
resource "stackit_network" "example_non_routed_network" {
|
||||
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||
name = "example-non-routed-network"
|
||||
ipv4_nameservers = ["1.2.3.4", "5.6.7.8"]
|
||||
ipv4_prefix_length = 24
|
||||
ipv4_gateway = "10.1.2.3"
|
||||
ipv4_prefix = "10.1.2.0/24"
|
||||
labels = {
|
||||
"key" = "value"
|
||||
}
|
||||
routed = false
|
||||
}
|
||||
|
|
@ -29,6 +29,9 @@ var networkResource = map[string]string{
|
|||
"ipv4_prefix_length": "24",
|
||||
"nameserver0": "1.2.3.4",
|
||||
"nameserver1": "5.6.7.8",
|
||||
"ipv4_gateway": "10.1.2.1",
|
||||
"ipv4_prefix": "10.1.2.1/24",
|
||||
"routed": "false",
|
||||
}
|
||||
|
||||
var networkAreaResource = map[string]string{
|
||||
|
|
@ -113,13 +116,19 @@ func networkResourceConfig(name, nameservers string) string {
|
|||
project_id = "%s"
|
||||
name = "%s"
|
||||
ipv4_prefix_length = "%s"
|
||||
nameservers = %s
|
||||
ipv4_nameservers = %s
|
||||
ipv4_gateway = "%s"
|
||||
ipv4_prefix = "%s"
|
||||
routed = "%s"
|
||||
}
|
||||
`,
|
||||
networkResource["project_id"],
|
||||
name,
|
||||
networkResource["ipv4_prefix_length"],
|
||||
nameservers,
|
||||
networkResource["ipv4_gateway"],
|
||||
networkResource["ipv4_prefix"],
|
||||
networkResource["routed"],
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -616,6 +625,9 @@ func TestAccServer(t *testing.T) {
|
|||
resource.TestCheckResourceAttr("stackit_network.network", "name", networkResource["name"]),
|
||||
resource.TestCheckResourceAttr("stackit_network.network", "nameservers.#", "1"),
|
||||
resource.TestCheckResourceAttr("stackit_network.network", "nameservers.0", networkResource["nameserver0"]),
|
||||
resource.TestCheckResourceAttr("stackit_network.network", "ipv4_gateway", networkResource["ipv4_gateway"]),
|
||||
resource.TestCheckResourceAttr("stackit_network.network", "ipv4_prefix", networkResource["ipv4_prefix"]),
|
||||
resource.TestCheckResourceAttr("stackit_network.network", "routed", networkResource["routed"]),
|
||||
|
||||
// Server
|
||||
resource.TestCheckResourceAttr("stackit_server.server", "project_id", serverResource["project_id"]),
|
||||
|
|
@ -718,6 +730,9 @@ func TestAccServer(t *testing.T) {
|
|||
),
|
||||
resource.TestCheckResourceAttr("data.stackit_network.network", "name", networkResource["name"]),
|
||||
resource.TestCheckResourceAttr("data.stackit_network.network", "nameservers.0", networkResource["nameserver0"]),
|
||||
resource.TestCheckResourceAttr("data.stackit_network.network", "ipv4_gateway", networkResource["ipv4_gateway"]),
|
||||
resource.TestCheckResourceAttr("data.stackit_network.network", "ipv4_prefix", networkResource["ipv4_prefix"]),
|
||||
resource.TestCheckResourceAttr("data.stackit_network.network", "routed", networkResource["routed"]),
|
||||
|
||||
// Server
|
||||
resource.TestCheckResourceAttr("data.stackit_server.server", "project_id", serverResource["project_id"]),
|
||||
|
|
@ -879,6 +894,8 @@ func TestAccServer(t *testing.T) {
|
|||
resource.TestCheckResourceAttr("stackit_network.network", "nameservers.#", "2"),
|
||||
resource.TestCheckResourceAttr("stackit_network.network", "nameservers.0", networkResource["nameserver0"]),
|
||||
resource.TestCheckResourceAttr("stackit_network.network", "nameservers.1", networkResource["nameserver1"]),
|
||||
resource.TestCheckResourceAttr("stackit_network.network", "ipv4_gateway", networkResource["ipv4_gateway"]),
|
||||
resource.TestCheckResourceAttr("stackit_network.network", "ipv4_prefix", networkResource["ipv4_prefix"]),
|
||||
|
||||
// Server
|
||||
resource.TestCheckResourceAttr("stackit_server.server", "project_id", serverResource["project_id"]),
|
||||
|
|
|
|||
|
|
@ -107,16 +107,58 @@ func (d *networkDataSource) Schema(_ context.Context, _ datasource.SchemaRequest
|
|||
},
|
||||
},
|
||||
"nameservers": schema.ListAttribute{
|
||||
Description: "The nameservers of the network.",
|
||||
Description: "The nameservers of the network. This field is deprecated and will be removed soon, use `ipv4_nameservers` to configure the nameservers for IPv4.",
|
||||
DeprecationMessage: "Use `ipv4_nameservers` to configure the nameservers for IPv4.",
|
||||
Computed: true,
|
||||
ElementType: types.StringType,
|
||||
},
|
||||
"ipv4_gateway": schema.StringAttribute{
|
||||
Description: "The IPv4 gateway of a network. If not specified, the first IP of the network will be assigned as the gateway.",
|
||||
Computed: true,
|
||||
},
|
||||
"ipv4_nameservers": schema.ListAttribute{
|
||||
Description: "The IPv4 nameservers of the network.",
|
||||
Computed: true,
|
||||
ElementType: types.StringType,
|
||||
},
|
||||
"ipv4_prefix": schema.StringAttribute{
|
||||
Description: "The IPv4 prefix of the network (CIDR).",
|
||||
Computed: true,
|
||||
},
|
||||
"ipv4_prefix_length": schema.Int64Attribute{
|
||||
Description: "The IPv4 prefix length of the network.",
|
||||
Computed: true,
|
||||
},
|
||||
"prefixes": schema.ListAttribute{
|
||||
Description: "The prefixes of the network.",
|
||||
Description: "The prefixes of the network. This field is deprecated and will be removed soon, use `ipv4_prefixes` to read the prefixes of the IPv4 networks.",
|
||||
DeprecationMessage: "Use `ipv4_prefixes` to read the prefixes of the IPv4 networks.",
|
||||
Computed: true,
|
||||
ElementType: types.StringType,
|
||||
},
|
||||
"ipv4_prefixes": schema.ListAttribute{
|
||||
Description: "The IPv4 prefixes of the network.",
|
||||
Computed: true,
|
||||
ElementType: types.StringType,
|
||||
},
|
||||
"ipv6_gateway": schema.StringAttribute{
|
||||
Description: "The IPv6 gateway of a network. If not specified, the first IP of the network will be assigned as the gateway.",
|
||||
Computed: true,
|
||||
},
|
||||
"ipv6_nameservers": schema.ListAttribute{
|
||||
Description: "The IPv6 nameservers of the network.",
|
||||
Computed: true,
|
||||
ElementType: types.StringType,
|
||||
},
|
||||
"ipv6_prefix": schema.StringAttribute{
|
||||
Description: "The IPv6 prefix of the network (CIDR).",
|
||||
Computed: true,
|
||||
},
|
||||
"ipv6_prefix_length": schema.Int64Attribute{
|
||||
Description: "The IPv6 prefix length of the network.",
|
||||
Computed: true,
|
||||
},
|
||||
"ipv6_prefixes": schema.ListAttribute{
|
||||
Description: "The IPv6 prefixes of the network.",
|
||||
Computed: true,
|
||||
ElementType: types.StringType,
|
||||
},
|
||||
|
|
@ -129,6 +171,10 @@ func (d *networkDataSource) Schema(_ context.Context, _ datasource.SchemaRequest
|
|||
ElementType: types.StringType,
|
||||
Computed: true,
|
||||
},
|
||||
"routed": schema.BoolAttribute{
|
||||
Description: "Shows if the network is routed and therefore accessible from other networks.",
|
||||
Computed: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,11 +6,14 @@ import (
|
|||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-framework-validators/resourcevalidator"
|
||||
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
|
||||
"github.com/hashicorp/terraform-plugin-framework/attr"
|
||||
"github.com/hashicorp/terraform-plugin-framework/diag"
|
||||
"github.com/hashicorp/terraform-plugin-framework/path"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/boolplanmodifier"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/listplanmodifier"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
|
||||
|
|
@ -40,10 +43,22 @@ type Model struct {
|
|||
NetworkId types.String `tfsdk:"network_id"`
|
||||
Name types.String `tfsdk:"name"`
|
||||
Nameservers types.List `tfsdk:"nameservers"`
|
||||
IPv4Gateway types.String `tfsdk:"ipv4_gateway"`
|
||||
IPv4Nameservers types.List `tfsdk:"ipv4_nameservers"`
|
||||
IPv4Prefix types.String `tfsdk:"ipv4_prefix"`
|
||||
IPv4PrefixLength types.Int64 `tfsdk:"ipv4_prefix_length"`
|
||||
Prefixes types.List `tfsdk:"prefixes"`
|
||||
IPv4Prefixes types.List `tfsdk:"ipv4_prefixes"`
|
||||
IPv6Gateway types.String `tfsdk:"ipv6_gateway"`
|
||||
IPv6Nameservers types.List `tfsdk:"ipv6_nameservers"`
|
||||
IPv6Prefix types.String `tfsdk:"ipv6_prefix"`
|
||||
IPv6PrefixLength types.Int64 `tfsdk:"ipv6_prefix_length"`
|
||||
IPv6Prefixes types.List `tfsdk:"ipv6_prefixes"`
|
||||
PublicIP types.String `tfsdk:"public_ip"`
|
||||
Labels types.Map `tfsdk:"labels"`
|
||||
Routed types.Bool `tfsdk:"routed"`
|
||||
NoIPv4Gateway types.Bool `tfsdk:"no_ipv4_gateway"`
|
||||
NoIPv6Gateway types.Bool `tfsdk:"no_ipv6_gateway"`
|
||||
}
|
||||
|
||||
// NewNetworkResource is a helper function to simplify the provider implementation.
|
||||
|
|
@ -98,6 +113,32 @@ func (r *networkResource) Configure(ctx context.Context, req resource.ConfigureR
|
|||
tflog.Info(ctx, "IaaS client configured")
|
||||
}
|
||||
|
||||
func (r networkResource) ValidateConfig(ctx context.Context, req resource.ValidateConfigRequest, resp *resource.ValidateConfigResponse) {
|
||||
var model Model
|
||||
resp.Diagnostics.Append(req.Config.Get(ctx, &model)...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
if !model.Nameservers.IsUnknown() && !model.IPv4Nameservers.IsUnknown() && !model.Nameservers.IsNull() && !model.IPv4Nameservers.IsNull() {
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error configuring network", "You cannot provide both the `nameservers` and `ipv4_nameservers` fields simultaneously. Please remove the deprecated `nameservers` field, and use `ipv4_nameservers` to configure nameservers for IPv4.")
|
||||
}
|
||||
}
|
||||
|
||||
// ConfigValidators validates the resource configuration
|
||||
func (r *networkResource) ConfigValidators(_ context.Context) []resource.ConfigValidator {
|
||||
return []resource.ConfigValidator{
|
||||
resourcevalidator.Conflicting(
|
||||
path.MatchRoot("no_ipv4_gateway"),
|
||||
path.MatchRoot("ipv4_gateway"),
|
||||
),
|
||||
resourcevalidator.Conflicting(
|
||||
path.MatchRoot("no_ipv6_gateway"),
|
||||
path.MatchRoot("ipv6_gateway"),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
// Schema defines the schema for the resource.
|
||||
func (r *networkResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
|
||||
resp.Schema = schema.Schema{
|
||||
|
|
@ -141,32 +182,128 @@ func (r *networkResource) Schema(_ context.Context, _ resource.SchemaRequest, re
|
|||
},
|
||||
},
|
||||
"nameservers": schema.ListAttribute{
|
||||
Description: "The nameservers of the network.",
|
||||
Description: "The nameservers of the network. This field is deprecated and will be removed soon, use `ipv4_nameservers` to configure the nameservers for IPv4.",
|
||||
DeprecationMessage: "Use `ipv4_nameservers` to configure the nameservers for IPv4.",
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
ElementType: types.StringType,
|
||||
},
|
||||
"no_ipv4_gateway": schema.BoolAttribute{
|
||||
Description: "If set to `true`, the network doesn't have a gateway.",
|
||||
Optional: true,
|
||||
PlanModifiers: []planmodifier.Bool{
|
||||
boolplanmodifier.UseStateForUnknown(),
|
||||
},
|
||||
},
|
||||
"ipv4_gateway": schema.StringAttribute{
|
||||
Description: "The IPv4 gateway of a network. If not specified, the first IP of the network will be assigned as the gateway.",
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
PlanModifiers: []planmodifier.List{
|
||||
listplanmodifier.UseStateForUnknown(),
|
||||
Validators: []validator.String{
|
||||
validate.IP(),
|
||||
},
|
||||
},
|
||||
"ipv4_nameservers": schema.ListAttribute{
|
||||
Description: "The IPv4 nameservers of the network.",
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
ElementType: types.StringType,
|
||||
},
|
||||
"ipv4_prefix": schema.StringAttribute{
|
||||
Description: "The IPv4 prefix of the network (CIDR).",
|
||||
Optional: true,
|
||||
Validators: []validator.String{
|
||||
validate.CIDR(),
|
||||
},
|
||||
PlanModifiers: []planmodifier.String{
|
||||
stringplanmodifier.RequiresReplace(),
|
||||
},
|
||||
},
|
||||
"ipv4_prefix_length": schema.Int64Attribute{
|
||||
Description: "The IPv4 prefix length of the network.",
|
||||
Optional: true,
|
||||
},
|
||||
"prefixes": schema.ListAttribute{
|
||||
Description: "The prefixes of the network.",
|
||||
Description: "The prefixes of the network. This field is deprecated and will be removed soon, use `ipv4_prefixes` to read the prefixes of the IPv4 networks.",
|
||||
DeprecationMessage: "Use `ipv4_prefixes` to read the prefixes of the IPv4 networks.",
|
||||
Computed: true,
|
||||
ElementType: types.StringType,
|
||||
PlanModifiers: []planmodifier.List{
|
||||
listplanmodifier.UseStateForUnknown(),
|
||||
},
|
||||
},
|
||||
"ipv4_prefixes": schema.ListAttribute{
|
||||
Description: "The IPv4 prefixes of the network.",
|
||||
Computed: true,
|
||||
ElementType: types.StringType,
|
||||
PlanModifiers: []planmodifier.List{
|
||||
listplanmodifier.UseStateForUnknown(),
|
||||
},
|
||||
},
|
||||
"no_ipv6_gateway": schema.BoolAttribute{
|
||||
Description: "If set to `true`, the network doesn't have a gateway.",
|
||||
Optional: true,
|
||||
PlanModifiers: []planmodifier.Bool{
|
||||
boolplanmodifier.UseStateForUnknown(),
|
||||
},
|
||||
},
|
||||
"ipv6_gateway": schema.StringAttribute{
|
||||
Description: "The IPv6 gateway of a network. If not specified, the first IP of the network will be assigned as the gateway.",
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
Validators: []validator.String{
|
||||
validate.IP(),
|
||||
},
|
||||
},
|
||||
"ipv6_nameservers": schema.ListAttribute{
|
||||
Description: "The IPv6 nameservers of the network.",
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
ElementType: types.StringType,
|
||||
},
|
||||
"ipv6_prefix": schema.StringAttribute{
|
||||
Description: "The IPv6 prefix of the network (CIDR).",
|
||||
Optional: true,
|
||||
Validators: []validator.String{
|
||||
validate.CIDR(),
|
||||
},
|
||||
PlanModifiers: []planmodifier.String{
|
||||
stringplanmodifier.RequiresReplace(),
|
||||
},
|
||||
},
|
||||
"ipv6_prefix_length": schema.Int64Attribute{
|
||||
Description: "The IPv6 prefix length of the network.",
|
||||
Optional: true,
|
||||
},
|
||||
"ipv6_prefixes": schema.ListAttribute{
|
||||
Description: "The IPv6 prefixes of the network.",
|
||||
Computed: true,
|
||||
ElementType: types.StringType,
|
||||
PlanModifiers: []planmodifier.List{
|
||||
listplanmodifier.UseStateForUnknown(),
|
||||
},
|
||||
},
|
||||
"public_ip": schema.StringAttribute{
|
||||
Description: "The public IP of the network.",
|
||||
Computed: true,
|
||||
PlanModifiers: []planmodifier.String{
|
||||
stringplanmodifier.UseStateForUnknown(),
|
||||
},
|
||||
},
|
||||
"labels": schema.MapAttribute{
|
||||
Description: "Labels are key-value string pairs which can be attached to a resource container",
|
||||
ElementType: types.StringType,
|
||||
Optional: true,
|
||||
},
|
||||
"routed": schema.BoolAttribute{
|
||||
Description: "If set to `true`, the network is routed and therefore accessible from other networks.",
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
PlanModifiers: []planmodifier.Bool{
|
||||
boolplanmodifier.UseStateForUnknown(),
|
||||
boolplanmodifier.RequiresReplace(),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
@ -285,7 +422,7 @@ func (r *networkResource) Update(ctx context.Context, req resource.UpdateRequest
|
|||
}
|
||||
|
||||
// Generate API request body from model
|
||||
payload, err := toUpdatePayload(ctx, &model, stateModel.Labels)
|
||||
payload, err := toUpdatePayload(ctx, &model, &stateModel)
|
||||
if err != nil {
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error updating network", fmt.Sprintf("Creating API payload: %v", err))
|
||||
return
|
||||
|
|
@ -407,27 +544,41 @@ func mapFields(ctx context.Context, networkResp *iaas.Network, model *Model) err
|
|||
labels = types.MapNull(types.StringType)
|
||||
}
|
||||
|
||||
// IPv4
|
||||
|
||||
if networkResp.Nameservers == nil {
|
||||
model.Nameservers = types.ListNull(types.StringType)
|
||||
model.IPv4Nameservers = types.ListNull(types.StringType)
|
||||
} else {
|
||||
respNameservers := *networkResp.Nameservers
|
||||
modelNameservers, err := utils.ListValuetoStringSlice(model.Nameservers)
|
||||
modelIPv4Nameservers, errIpv4 := utils.ListValuetoStringSlice(model.IPv4Nameservers)
|
||||
if err != nil {
|
||||
return fmt.Errorf("get current network nameservers from model: %w", err)
|
||||
}
|
||||
if errIpv4 != nil {
|
||||
return fmt.Errorf("get current IPv4 network nameservers from model: %w", errIpv4)
|
||||
}
|
||||
|
||||
reconciledNameservers := utils.ReconcileStringSlices(modelNameservers, respNameservers)
|
||||
reconciledIPv4Nameservers := utils.ReconcileStringSlices(modelIPv4Nameservers, respNameservers)
|
||||
|
||||
nameserversTF, diags := types.ListValueFrom(ctx, types.StringType, reconciledNameservers)
|
||||
ipv4NameserversTF, ipv4Diags := types.ListValueFrom(ctx, types.StringType, reconciledIPv4Nameservers)
|
||||
if diags.HasError() {
|
||||
return fmt.Errorf("map network nameservers: %w", core.DiagsToError(diags))
|
||||
}
|
||||
if ipv4Diags.HasError() {
|
||||
return fmt.Errorf("map IPv4 network nameservers: %w", core.DiagsToError(ipv4Diags))
|
||||
}
|
||||
|
||||
model.Nameservers = nameserversTF
|
||||
model.IPv4Nameservers = ipv4NameserversTF
|
||||
}
|
||||
|
||||
if networkResp.Prefixes == nil {
|
||||
model.Prefixes = types.ListNull(types.StringType)
|
||||
model.IPv4Prefixes = types.ListNull(types.StringType)
|
||||
} else {
|
||||
respPrefixes := *networkResp.Prefixes
|
||||
prefixesTF, diags := types.ListValueFrom(ctx, types.StringType, respPrefixes)
|
||||
|
|
@ -436,12 +587,59 @@ func mapFields(ctx context.Context, networkResp *iaas.Network, model *Model) err
|
|||
}
|
||||
|
||||
model.Prefixes = prefixesTF
|
||||
model.IPv4Prefixes = prefixesTF
|
||||
}
|
||||
|
||||
if networkResp.Gateway != nil {
|
||||
model.IPv4Gateway = types.StringPointerValue(networkResp.GetGateway())
|
||||
} else {
|
||||
model.IPv4Gateway = types.StringNull()
|
||||
}
|
||||
|
||||
// IPv6
|
||||
|
||||
if networkResp.NameserversV6 == nil {
|
||||
model.IPv6Nameservers = types.ListNull(types.StringType)
|
||||
} else {
|
||||
respIPv6Nameservers := *networkResp.NameserversV6
|
||||
modelIPv6Nameservers, errIpv6 := utils.ListValuetoStringSlice(model.IPv6Nameservers)
|
||||
if errIpv6 != nil {
|
||||
return fmt.Errorf("get current IPv6 network nameservers from model: %w", errIpv6)
|
||||
}
|
||||
|
||||
reconciledIPv6Nameservers := utils.ReconcileStringSlices(modelIPv6Nameservers, respIPv6Nameservers)
|
||||
|
||||
ipv6NameserversTF, ipv6Diags := types.ListValueFrom(ctx, types.StringType, reconciledIPv6Nameservers)
|
||||
if ipv6Diags.HasError() {
|
||||
return fmt.Errorf("map IPv6 network nameservers: %w", core.DiagsToError(ipv6Diags))
|
||||
}
|
||||
|
||||
model.IPv6Nameservers = ipv6NameserversTF
|
||||
}
|
||||
|
||||
if networkResp.PrefixesV6 == nil {
|
||||
model.IPv6Prefixes = types.ListNull(types.StringType)
|
||||
} else {
|
||||
respPrefixesV6 := *networkResp.PrefixesV6
|
||||
prefixesV6TF, diags := types.ListValueFrom(ctx, types.StringType, respPrefixesV6)
|
||||
if diags.HasError() {
|
||||
return fmt.Errorf("map network IPv6 prefixes: %w", core.DiagsToError(diags))
|
||||
}
|
||||
|
||||
model.IPv6Prefixes = prefixesV6TF
|
||||
}
|
||||
|
||||
if networkResp.Gatewayv6 != nil {
|
||||
model.IPv6Gateway = types.StringPointerValue(networkResp.GetGatewayv6())
|
||||
} else {
|
||||
model.IPv6Gateway = types.StringNull()
|
||||
}
|
||||
|
||||
model.NetworkId = types.StringValue(networkId)
|
||||
model.Name = types.StringPointerValue(networkResp.Name)
|
||||
model.PublicIP = types.StringPointerValue(networkResp.PublicIp)
|
||||
model.Labels = labels
|
||||
model.Routed = types.BoolPointerValue(networkResp.Routed)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
@ -450,14 +648,60 @@ func toCreatePayload(ctx context.Context, model *Model) (*iaas.CreateNetworkPayl
|
|||
if model == nil {
|
||||
return nil, fmt.Errorf("nil model")
|
||||
}
|
||||
addressFamily := &iaas.CreateNetworkAddressFamily{}
|
||||
|
||||
modelNameservers := []string{}
|
||||
for _, ns := range model.Nameservers.Elements() {
|
||||
nameserverString, ok := ns.(types.String)
|
||||
modelIPv6Nameservers := []string{}
|
||||
for _, ipv6ns := range model.IPv6Nameservers.Elements() {
|
||||
ipv6NameserverString, ok := ipv6ns.(types.String)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("type assertion failed")
|
||||
}
|
||||
modelNameservers = append(modelNameservers, nameserverString.ValueString())
|
||||
modelIPv6Nameservers = append(modelIPv6Nameservers, ipv6NameserverString.ValueString())
|
||||
}
|
||||
|
||||
if !(model.IPv6Prefix.IsNull() || model.IPv6PrefixLength.IsNull() || model.IPv6Nameservers.IsNull()) {
|
||||
addressFamily.Ipv6 = &iaas.CreateNetworkIPv6Body{
|
||||
Nameservers: &modelIPv6Nameservers,
|
||||
Prefix: conversion.StringValueToPointer(model.IPv6Prefix),
|
||||
PrefixLength: conversion.Int64ValueToPointer(model.IPv6PrefixLength),
|
||||
}
|
||||
|
||||
if model.NoIPv6Gateway.ValueBool() {
|
||||
addressFamily.Ipv6.Gateway = iaas.NewNullableString(nil)
|
||||
} else if !(model.IPv6Gateway.IsUnknown() || model.IPv6Gateway.IsNull()) {
|
||||
addressFamily.Ipv6.Gateway = iaas.NewNullableString(conversion.StringValueToPointer(model.IPv6Gateway))
|
||||
}
|
||||
}
|
||||
|
||||
modelIPv4Nameservers := []string{}
|
||||
var modelIPv4List []attr.Value
|
||||
|
||||
if !(model.IPv4Nameservers.IsNull() || model.IPv4Nameservers.IsUnknown()) {
|
||||
modelIPv4List = model.IPv4Nameservers.Elements()
|
||||
} else {
|
||||
modelIPv4List = model.Nameservers.Elements()
|
||||
}
|
||||
|
||||
for _, ipv4ns := range modelIPv4List {
|
||||
ipv4NameserverString, ok := ipv4ns.(types.String)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("type assertion failed")
|
||||
}
|
||||
modelIPv4Nameservers = append(modelIPv4Nameservers, ipv4NameserverString.ValueString())
|
||||
}
|
||||
|
||||
if !model.IPv4Prefix.IsNull() || !model.IPv4PrefixLength.IsNull() || !model.IPv4Nameservers.IsNull() || !model.Nameservers.IsNull() {
|
||||
addressFamily.Ipv4 = &iaas.CreateNetworkIPv4Body{
|
||||
Nameservers: &modelIPv4Nameservers,
|
||||
Prefix: conversion.StringValueToPointer(model.IPv4Prefix),
|
||||
PrefixLength: conversion.Int64ValueToPointer(model.IPv4PrefixLength),
|
||||
}
|
||||
|
||||
if model.NoIPv4Gateway.ValueBool() {
|
||||
addressFamily.Ipv4.Gateway = iaas.NewNullableString(nil)
|
||||
} else if !(model.IPv4Gateway.IsUnknown() || model.IPv4Gateway.IsNull()) {
|
||||
addressFamily.Ipv4.Gateway = iaas.NewNullableString(conversion.StringValueToPointer(model.IPv4Gateway))
|
||||
}
|
||||
}
|
||||
|
||||
labels, err := conversion.ToStringInterfaceMap(ctx, model.Labels)
|
||||
|
|
@ -465,44 +709,88 @@ func toCreatePayload(ctx context.Context, model *Model) (*iaas.CreateNetworkPayl
|
|||
return nil, fmt.Errorf("converting to Go map: %w", err)
|
||||
}
|
||||
|
||||
return &iaas.CreateNetworkPayload{
|
||||
Name: conversion.StringValueToPointer(model.Name),
|
||||
AddressFamily: &iaas.CreateNetworkAddressFamily{
|
||||
Ipv4: &iaas.CreateNetworkIPv4Body{
|
||||
PrefixLength: conversion.Int64ValueToPointer(model.IPv4PrefixLength),
|
||||
Nameservers: &modelNameservers,
|
||||
},
|
||||
},
|
||||
payload := iaas.CreateNetworkPayload{
|
||||
Name: conversion.StringValueToPointer(model.Name),
|
||||
Labels: &labels,
|
||||
}, nil
|
||||
Routed: conversion.BoolValueToPointer(model.Routed),
|
||||
}
|
||||
|
||||
if addressFamily.Ipv6 != nil || addressFamily.Ipv4 != nil {
|
||||
payload.AddressFamily = addressFamily
|
||||
}
|
||||
|
||||
return &payload, nil
|
||||
}
|
||||
|
||||
func toUpdatePayload(ctx context.Context, model *Model, currentLabels types.Map) (*iaas.PartialUpdateNetworkPayload, error) {
|
||||
func toUpdatePayload(ctx context.Context, model, stateModel *Model) (*iaas.PartialUpdateNetworkPayload, error) {
|
||||
if model == nil {
|
||||
return nil, fmt.Errorf("nil model")
|
||||
}
|
||||
addressFamily := &iaas.UpdateNetworkAddressFamily{}
|
||||
|
||||
modelNameservers := []string{}
|
||||
for _, ns := range model.Nameservers.Elements() {
|
||||
nameserverString, ok := ns.(types.String)
|
||||
modelIPv6Nameservers := []string{}
|
||||
for _, ipv6ns := range model.IPv6Nameservers.Elements() {
|
||||
ipv6NameserverString, ok := ipv6ns.(types.String)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("type assertion failed")
|
||||
}
|
||||
modelNameservers = append(modelNameservers, nameserverString.ValueString())
|
||||
modelIPv6Nameservers = append(modelIPv6Nameservers, ipv6NameserverString.ValueString())
|
||||
}
|
||||
|
||||
if !(model.IPv6Nameservers.IsNull() || model.IPv6Nameservers.IsUnknown()) {
|
||||
addressFamily.Ipv6 = &iaas.UpdateNetworkIPv6Body{
|
||||
Nameservers: &modelIPv6Nameservers,
|
||||
}
|
||||
|
||||
if model.NoIPv6Gateway.ValueBool() {
|
||||
addressFamily.Ipv6.Gateway = iaas.NewNullableString(nil)
|
||||
} else if !(model.IPv6Gateway.IsUnknown() || model.IPv6Gateway.IsNull()) {
|
||||
addressFamily.Ipv6.Gateway = iaas.NewNullableString(conversion.StringValueToPointer(model.IPv6Gateway))
|
||||
}
|
||||
}
|
||||
|
||||
modelIPv4Nameservers := []string{}
|
||||
var modelIPv4List []attr.Value
|
||||
|
||||
if !(model.IPv4Nameservers.IsNull() || model.IPv4Nameservers.IsUnknown()) {
|
||||
modelIPv4List = model.IPv4Nameservers.Elements()
|
||||
} else {
|
||||
modelIPv4List = model.Nameservers.Elements()
|
||||
}
|
||||
for _, ipv4ns := range modelIPv4List {
|
||||
ipv4NameserverString, ok := ipv4ns.(types.String)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("type assertion failed")
|
||||
}
|
||||
modelIPv4Nameservers = append(modelIPv4Nameservers, ipv4NameserverString.ValueString())
|
||||
}
|
||||
|
||||
if !model.IPv4Nameservers.IsNull() || !model.Nameservers.IsNull() {
|
||||
addressFamily.Ipv4 = &iaas.UpdateNetworkIPv4Body{
|
||||
Nameservers: &modelIPv4Nameservers,
|
||||
}
|
||||
|
||||
if model.NoIPv4Gateway.ValueBool() {
|
||||
addressFamily.Ipv4.Gateway = iaas.NewNullableString(nil)
|
||||
} else if !(model.IPv4Gateway.IsUnknown() || model.IPv4Gateway.IsNull()) {
|
||||
addressFamily.Ipv4.Gateway = iaas.NewNullableString(conversion.StringValueToPointer(model.IPv4Gateway))
|
||||
}
|
||||
}
|
||||
|
||||
currentLabels := stateModel.Labels
|
||||
labels, err := conversion.ToJSONMapPartialUpdatePayload(ctx, currentLabels, model.Labels)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("converting to Go map: %w", err)
|
||||
}
|
||||
|
||||
return &iaas.PartialUpdateNetworkPayload{
|
||||
Name: conversion.StringValueToPointer(model.Name),
|
||||
AddressFamily: &iaas.UpdateNetworkAddressFamily{
|
||||
Ipv4: &iaas.UpdateNetworkIPv4Body{
|
||||
Nameservers: &modelNameservers,
|
||||
},
|
||||
},
|
||||
payload := iaas.PartialUpdateNetworkPayload{
|
||||
Name: conversion.StringValueToPointer(model.Name),
|
||||
Labels: &labels,
|
||||
}, nil
|
||||
}
|
||||
|
||||
if addressFamily.Ipv6 != nil || addressFamily.Ipv4 != nil {
|
||||
payload.AddressFamily = addressFamily
|
||||
}
|
||||
|
||||
return &payload, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ func TestMapFields(t *testing.T) {
|
|||
},
|
||||
&iaas.Network{
|
||||
NetworkId: utils.Ptr("nid"),
|
||||
Gateway: iaas.NewNullableString(nil),
|
||||
},
|
||||
Model{
|
||||
Id: types.StringValue("pid,nid"),
|
||||
|
|
@ -34,10 +35,20 @@ func TestMapFields(t *testing.T) {
|
|||
NetworkId: types.StringValue("nid"),
|
||||
Name: types.StringNull(),
|
||||
Nameservers: types.ListNull(types.StringType),
|
||||
IPv4Nameservers: types.ListNull(types.StringType),
|
||||
IPv4PrefixLength: types.Int64Null(),
|
||||
IPv4Gateway: types.StringNull(),
|
||||
IPv4Prefix: types.StringNull(),
|
||||
Prefixes: types.ListNull(types.StringType),
|
||||
IPv4Prefixes: types.ListNull(types.StringType),
|
||||
IPv6Nameservers: types.ListNull(types.StringType),
|
||||
IPv6PrefixLength: types.Int64Null(),
|
||||
IPv6Gateway: types.StringNull(),
|
||||
IPv6Prefix: types.StringNull(),
|
||||
IPv6Prefixes: types.ListNull(types.StringType),
|
||||
PublicIP: types.StringNull(),
|
||||
Labels: types.MapNull(types.StringType),
|
||||
Routed: types.BoolNull(),
|
||||
},
|
||||
true,
|
||||
},
|
||||
|
|
@ -58,10 +69,21 @@ func TestMapFields(t *testing.T) {
|
|||
"prefix1",
|
||||
"prefix2",
|
||||
},
|
||||
NameserversV6: &[]string{
|
||||
"ns1",
|
||||
"ns2",
|
||||
},
|
||||
PrefixesV6: &[]string{
|
||||
"prefix1",
|
||||
"prefix2",
|
||||
},
|
||||
PublicIp: utils.Ptr("publicIp"),
|
||||
Labels: &map[string]interface{}{
|
||||
"key": "value",
|
||||
},
|
||||
Routed: utils.Ptr(true),
|
||||
Gateway: iaas.NewNullableString(utils.Ptr("gateway")),
|
||||
Gatewayv6: iaas.NewNullableString(utils.Ptr("gateway")),
|
||||
},
|
||||
Model{
|
||||
Id: types.StringValue("pid,nid"),
|
||||
|
|
@ -72,20 +94,40 @@ func TestMapFields(t *testing.T) {
|
|||
types.StringValue("ns1"),
|
||||
types.StringValue("ns2"),
|
||||
}),
|
||||
IPv4Nameservers: types.ListValueMust(types.StringType, []attr.Value{
|
||||
types.StringValue("ns1"),
|
||||
types.StringValue("ns2"),
|
||||
}),
|
||||
IPv4PrefixLength: types.Int64Null(),
|
||||
Prefixes: types.ListValueMust(types.StringType, []attr.Value{
|
||||
types.StringValue("prefix1"),
|
||||
types.StringValue("prefix2"),
|
||||
}),
|
||||
IPv4Prefixes: types.ListValueMust(types.StringType, []attr.Value{
|
||||
types.StringValue("prefix1"),
|
||||
types.StringValue("prefix2"),
|
||||
}),
|
||||
IPv6Nameservers: types.ListValueMust(types.StringType, []attr.Value{
|
||||
types.StringValue("ns1"),
|
||||
types.StringValue("ns2"),
|
||||
}),
|
||||
IPv6PrefixLength: types.Int64Null(),
|
||||
IPv6Prefixes: types.ListValueMust(types.StringType, []attr.Value{
|
||||
types.StringValue("prefix1"),
|
||||
types.StringValue("prefix2"),
|
||||
}),
|
||||
PublicIP: types.StringValue("publicIp"),
|
||||
Labels: types.MapValueMust(types.StringType, map[string]attr.Value{
|
||||
"key": types.StringValue("value"),
|
||||
}),
|
||||
Routed: types.BoolValue(true),
|
||||
IPv4Gateway: types.StringValue("gateway"),
|
||||
IPv6Gateway: types.StringValue("gateway"),
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"nameservers_changed_outside_tf",
|
||||
"ipv4_nameservers_changed_outside_tf",
|
||||
Model{
|
||||
ProjectId: types.StringValue("pid"),
|
||||
NetworkId: types.StringValue("nid"),
|
||||
|
|
@ -93,6 +135,10 @@ func TestMapFields(t *testing.T) {
|
|||
types.StringValue("ns1"),
|
||||
types.StringValue("ns2"),
|
||||
}),
|
||||
IPv4Nameservers: types.ListValueMust(types.StringType, []attr.Value{
|
||||
types.StringValue("ns1"),
|
||||
types.StringValue("ns2"),
|
||||
}),
|
||||
},
|
||||
&iaas.Network{
|
||||
NetworkId: utils.Ptr("nid"),
|
||||
|
|
@ -102,21 +148,63 @@ func TestMapFields(t *testing.T) {
|
|||
},
|
||||
},
|
||||
Model{
|
||||
Id: types.StringValue("pid,nid"),
|
||||
ProjectId: types.StringValue("pid"),
|
||||
NetworkId: types.StringValue("nid"),
|
||||
Name: types.StringNull(),
|
||||
Prefixes: types.ListNull(types.StringType),
|
||||
Id: types.StringValue("pid,nid"),
|
||||
ProjectId: types.StringValue("pid"),
|
||||
NetworkId: types.StringValue("nid"),
|
||||
Name: types.StringNull(),
|
||||
IPv6Prefixes: types.ListNull(types.StringType),
|
||||
IPv6Nameservers: types.ListNull(types.StringType),
|
||||
Prefixes: types.ListNull(types.StringType),
|
||||
IPv4Prefixes: types.ListNull(types.StringType),
|
||||
Nameservers: types.ListValueMust(types.StringType, []attr.Value{
|
||||
types.StringValue("ns2"),
|
||||
types.StringValue("ns3"),
|
||||
}),
|
||||
IPv4Nameservers: types.ListValueMust(types.StringType, []attr.Value{
|
||||
types.StringValue("ns2"),
|
||||
types.StringValue("ns3"),
|
||||
}),
|
||||
Labels: types.MapNull(types.StringType),
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"prefixes_changed_outisde_tf",
|
||||
"ipv6_nameservers_changed_outside_tf",
|
||||
Model{
|
||||
ProjectId: types.StringValue("pid"),
|
||||
NetworkId: types.StringValue("nid"),
|
||||
IPv6Nameservers: types.ListValueMust(types.StringType, []attr.Value{
|
||||
types.StringValue("ns1"),
|
||||
types.StringValue("ns2"),
|
||||
}),
|
||||
},
|
||||
&iaas.Network{
|
||||
NetworkId: utils.Ptr("nid"),
|
||||
NameserversV6: &[]string{
|
||||
"ns2",
|
||||
"ns3",
|
||||
},
|
||||
},
|
||||
Model{
|
||||
Id: types.StringValue("pid,nid"),
|
||||
ProjectId: types.StringValue("pid"),
|
||||
NetworkId: types.StringValue("nid"),
|
||||
Name: types.StringNull(),
|
||||
IPv6Prefixes: types.ListNull(types.StringType),
|
||||
IPv4Nameservers: types.ListNull(types.StringType),
|
||||
Prefixes: types.ListNull(types.StringType),
|
||||
IPv4Prefixes: types.ListNull(types.StringType),
|
||||
Nameservers: types.ListNull(types.StringType),
|
||||
IPv6Nameservers: types.ListValueMust(types.StringType, []attr.Value{
|
||||
types.StringValue("ns2"),
|
||||
types.StringValue("ns3"),
|
||||
}),
|
||||
Labels: types.MapNull(types.StringType),
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"ipv4_prefixes_changed_outside_tf",
|
||||
Model{
|
||||
ProjectId: types.StringValue("pid"),
|
||||
NetworkId: types.StringValue("nid"),
|
||||
|
|
@ -137,13 +225,88 @@ func TestMapFields(t *testing.T) {
|
|||
ProjectId: types.StringValue("pid"),
|
||||
NetworkId: types.StringValue("nid"),
|
||||
Name: types.StringNull(),
|
||||
IPv6Nameservers: types.ListNull(types.StringType),
|
||||
IPv6PrefixLength: types.Int64Null(),
|
||||
IPv6Prefixes: types.ListNull(types.StringType),
|
||||
Labels: types.MapNull(types.StringType),
|
||||
Nameservers: types.ListNull(types.StringType),
|
||||
IPv4Nameservers: types.ListNull(types.StringType),
|
||||
IPv4PrefixLength: types.Int64Null(),
|
||||
Prefixes: types.ListValueMust(types.StringType, []attr.Value{
|
||||
types.StringValue("prefix2"),
|
||||
types.StringValue("prefix3"),
|
||||
}),
|
||||
Labels: types.MapNull(types.StringType),
|
||||
IPv4Prefixes: types.ListValueMust(types.StringType, []attr.Value{
|
||||
types.StringValue("prefix2"),
|
||||
types.StringValue("prefix3"),
|
||||
}),
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"ipv6_prefixes_changed_outside_tf",
|
||||
Model{
|
||||
ProjectId: types.StringValue("pid"),
|
||||
NetworkId: types.StringValue("nid"),
|
||||
IPv6Prefixes: types.ListValueMust(types.StringType, []attr.Value{
|
||||
types.StringValue("prefix1"),
|
||||
types.StringValue("prefix2"),
|
||||
}),
|
||||
},
|
||||
&iaas.Network{
|
||||
NetworkId: utils.Ptr("nid"),
|
||||
PrefixesV6: &[]string{
|
||||
"prefix2",
|
||||
"prefix3",
|
||||
},
|
||||
},
|
||||
Model{
|
||||
Id: types.StringValue("pid,nid"),
|
||||
ProjectId: types.StringValue("pid"),
|
||||
NetworkId: types.StringValue("nid"),
|
||||
Name: types.StringNull(),
|
||||
IPv4Nameservers: types.ListNull(types.StringType),
|
||||
IPv4PrefixLength: types.Int64Null(),
|
||||
Prefixes: types.ListNull(types.StringType),
|
||||
IPv4Prefixes: types.ListNull(types.StringType),
|
||||
Labels: types.MapNull(types.StringType),
|
||||
Nameservers: types.ListNull(types.StringType),
|
||||
IPv6Nameservers: types.ListNull(types.StringType),
|
||||
IPv6PrefixLength: types.Int64Null(),
|
||||
IPv6Prefixes: types.ListValueMust(types.StringType, []attr.Value{
|
||||
types.StringValue("prefix2"),
|
||||
types.StringValue("prefix3"),
|
||||
}),
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"ipv4_ipv6_gateway_nil",
|
||||
Model{
|
||||
ProjectId: types.StringValue("pid"),
|
||||
NetworkId: types.StringValue("nid"),
|
||||
},
|
||||
&iaas.Network{
|
||||
NetworkId: utils.Ptr("nid"),
|
||||
},
|
||||
Model{
|
||||
Id: types.StringValue("pid,nid"),
|
||||
ProjectId: types.StringValue("pid"),
|
||||
NetworkId: types.StringValue("nid"),
|
||||
Name: types.StringNull(),
|
||||
Nameservers: types.ListNull(types.StringType),
|
||||
IPv4Nameservers: types.ListNull(types.StringType),
|
||||
IPv4PrefixLength: types.Int64Null(),
|
||||
IPv4Gateway: types.StringNull(),
|
||||
Prefixes: types.ListNull(types.StringType),
|
||||
IPv4Prefixes: types.ListNull(types.StringType),
|
||||
IPv6Nameservers: types.ListNull(types.StringType),
|
||||
IPv6PrefixLength: types.Int64Null(),
|
||||
IPv6Gateway: types.StringNull(),
|
||||
IPv6Prefixes: types.ListNull(types.StringType),
|
||||
PublicIP: types.StringNull(),
|
||||
Labels: types.MapNull(types.StringType),
|
||||
Routed: types.BoolNull(),
|
||||
},
|
||||
true,
|
||||
},
|
||||
|
|
@ -194,7 +357,7 @@ func TestToCreatePayload(t *testing.T) {
|
|||
"default_ok",
|
||||
&Model{
|
||||
Name: types.StringValue("name"),
|
||||
Nameservers: types.ListValueMust(types.StringType, []attr.Value{
|
||||
IPv4Nameservers: types.ListValueMust(types.StringType, []attr.Value{
|
||||
types.StringValue("ns1"),
|
||||
types.StringValue("ns2"),
|
||||
}),
|
||||
|
|
@ -202,6 +365,9 @@ func TestToCreatePayload(t *testing.T) {
|
|||
Labels: types.MapValueMust(types.StringType, map[string]attr.Value{
|
||||
"key": types.StringValue("value"),
|
||||
}),
|
||||
Routed: types.BoolValue(false),
|
||||
IPv4Gateway: types.StringValue("gateway"),
|
||||
IPv4Prefix: types.StringValue("prefix"),
|
||||
},
|
||||
&iaas.CreateNetworkPayload{
|
||||
Name: utils.Ptr("name"),
|
||||
|
|
@ -212,11 +378,86 @@ func TestToCreatePayload(t *testing.T) {
|
|||
"ns2",
|
||||
},
|
||||
PrefixLength: utils.Ptr(int64(24)),
|
||||
Gateway: iaas.NewNullableString(utils.Ptr("gateway")),
|
||||
Prefix: utils.Ptr("prefix"),
|
||||
},
|
||||
},
|
||||
Labels: &map[string]interface{}{
|
||||
"key": "value",
|
||||
},
|
||||
Routed: utils.Ptr(false),
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"ipv4_nameservers_okay",
|
||||
&Model{
|
||||
Name: types.StringValue("name"),
|
||||
Nameservers: types.ListValueMust(types.StringType, []attr.Value{
|
||||
types.StringValue("ns1"),
|
||||
types.StringValue("ns2"),
|
||||
}),
|
||||
IPv4PrefixLength: types.Int64Value(24),
|
||||
Labels: types.MapValueMust(types.StringType, map[string]attr.Value{
|
||||
"key": types.StringValue("value"),
|
||||
}),
|
||||
Routed: types.BoolValue(false),
|
||||
IPv4Gateway: types.StringValue("gateway"),
|
||||
IPv4Prefix: types.StringValue("prefix"),
|
||||
},
|
||||
&iaas.CreateNetworkPayload{
|
||||
Name: utils.Ptr("name"),
|
||||
AddressFamily: &iaas.CreateNetworkAddressFamily{
|
||||
Ipv4: &iaas.CreateNetworkIPv4Body{
|
||||
Nameservers: &[]string{
|
||||
"ns1",
|
||||
"ns2",
|
||||
},
|
||||
PrefixLength: utils.Ptr(int64(24)),
|
||||
Gateway: iaas.NewNullableString(utils.Ptr("gateway")),
|
||||
Prefix: utils.Ptr("prefix"),
|
||||
},
|
||||
},
|
||||
Labels: &map[string]interface{}{
|
||||
"key": "value",
|
||||
},
|
||||
Routed: utils.Ptr(false),
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"ipv6_default_ok",
|
||||
&Model{
|
||||
Name: types.StringValue("name"),
|
||||
IPv6Nameservers: types.ListValueMust(types.StringType, []attr.Value{
|
||||
types.StringValue("ns1"),
|
||||
types.StringValue("ns2"),
|
||||
}),
|
||||
IPv6PrefixLength: types.Int64Value(24),
|
||||
Labels: types.MapValueMust(types.StringType, map[string]attr.Value{
|
||||
"key": types.StringValue("value"),
|
||||
}),
|
||||
Routed: types.BoolValue(false),
|
||||
IPv6Gateway: types.StringValue("gateway"),
|
||||
IPv6Prefix: types.StringValue("prefix"),
|
||||
},
|
||||
&iaas.CreateNetworkPayload{
|
||||
Name: utils.Ptr("name"),
|
||||
AddressFamily: &iaas.CreateNetworkAddressFamily{
|
||||
Ipv6: &iaas.CreateNetworkIPv6Body{
|
||||
Nameservers: &[]string{
|
||||
"ns1",
|
||||
"ns2",
|
||||
},
|
||||
PrefixLength: utils.Ptr(int64(24)),
|
||||
Gateway: iaas.NewNullableString(utils.Ptr("gateway")),
|
||||
Prefix: utils.Ptr("prefix"),
|
||||
},
|
||||
},
|
||||
Labels: &map[string]interface{}{
|
||||
"key": "value",
|
||||
},
|
||||
Routed: utils.Ptr(false),
|
||||
},
|
||||
true,
|
||||
},
|
||||
|
|
@ -231,7 +472,7 @@ func TestToCreatePayload(t *testing.T) {
|
|||
t.Fatalf("Should not have failed: %v", err)
|
||||
}
|
||||
if tt.isValid {
|
||||
diff := cmp.Diff(output, tt.expected)
|
||||
diff := cmp.Diff(output, tt.expected, cmp.AllowUnexported(iaas.NullableString{}))
|
||||
if diff != "" {
|
||||
t.Fatalf("Data does not match: %s", diff)
|
||||
}
|
||||
|
|
@ -244,11 +485,48 @@ func TestToUpdatePayload(t *testing.T) {
|
|||
tests := []struct {
|
||||
description string
|
||||
input *Model
|
||||
state Model
|
||||
expected *iaas.PartialUpdateNetworkPayload
|
||||
isValid bool
|
||||
}{
|
||||
{
|
||||
"default_ok",
|
||||
&Model{
|
||||
Name: types.StringValue("name"),
|
||||
IPv4Nameservers: types.ListValueMust(types.StringType, []attr.Value{
|
||||
types.StringValue("ns1"),
|
||||
types.StringValue("ns2"),
|
||||
}),
|
||||
Labels: types.MapValueMust(types.StringType, map[string]attr.Value{
|
||||
"key": types.StringValue("value"),
|
||||
}),
|
||||
Routed: types.BoolValue(true),
|
||||
IPv4Gateway: types.StringValue("gateway"),
|
||||
},
|
||||
Model{
|
||||
ProjectId: types.StringValue("pid"),
|
||||
NetworkId: types.StringValue("nid"),
|
||||
Labels: types.MapNull(types.StringType),
|
||||
},
|
||||
&iaas.PartialUpdateNetworkPayload{
|
||||
Name: utils.Ptr("name"),
|
||||
AddressFamily: &iaas.UpdateNetworkAddressFamily{
|
||||
Ipv4: &iaas.UpdateNetworkIPv4Body{
|
||||
Nameservers: &[]string{
|
||||
"ns1",
|
||||
"ns2",
|
||||
},
|
||||
Gateway: iaas.NewNullableString(utils.Ptr("gateway")),
|
||||
},
|
||||
},
|
||||
Labels: &map[string]interface{}{
|
||||
"key": "value",
|
||||
},
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"ipv4_nameservers_okay",
|
||||
&Model{
|
||||
Name: types.StringValue("name"),
|
||||
Nameservers: types.ListValueMust(types.StringType, []attr.Value{
|
||||
|
|
@ -258,6 +536,48 @@ func TestToUpdatePayload(t *testing.T) {
|
|||
Labels: types.MapValueMust(types.StringType, map[string]attr.Value{
|
||||
"key": types.StringValue("value"),
|
||||
}),
|
||||
Routed: types.BoolValue(true),
|
||||
IPv4Gateway: types.StringValue("gateway"),
|
||||
},
|
||||
Model{
|
||||
ProjectId: types.StringValue("pid"),
|
||||
NetworkId: types.StringValue("nid"),
|
||||
Labels: types.MapNull(types.StringType),
|
||||
},
|
||||
&iaas.PartialUpdateNetworkPayload{
|
||||
Name: utils.Ptr("name"),
|
||||
AddressFamily: &iaas.UpdateNetworkAddressFamily{
|
||||
Ipv4: &iaas.UpdateNetworkIPv4Body{
|
||||
Nameservers: &[]string{
|
||||
"ns1",
|
||||
"ns2",
|
||||
},
|
||||
Gateway: iaas.NewNullableString(utils.Ptr("gateway")),
|
||||
},
|
||||
},
|
||||
Labels: &map[string]interface{}{
|
||||
"key": "value",
|
||||
},
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"ipv4_gateway_nil",
|
||||
&Model{
|
||||
Name: types.StringValue("name"),
|
||||
IPv4Nameservers: types.ListValueMust(types.StringType, []attr.Value{
|
||||
types.StringValue("ns1"),
|
||||
types.StringValue("ns2"),
|
||||
}),
|
||||
Labels: types.MapValueMust(types.StringType, map[string]attr.Value{
|
||||
"key": types.StringValue("value"),
|
||||
}),
|
||||
Routed: types.BoolValue(true),
|
||||
},
|
||||
Model{
|
||||
ProjectId: types.StringValue("pid"),
|
||||
NetworkId: types.StringValue("nid"),
|
||||
Labels: types.MapNull(types.StringType),
|
||||
},
|
||||
&iaas.PartialUpdateNetworkPayload{
|
||||
Name: utils.Ptr("name"),
|
||||
|
|
@ -275,10 +595,80 @@ func TestToUpdatePayload(t *testing.T) {
|
|||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"ipv6_default_ok",
|
||||
&Model{
|
||||
Name: types.StringValue("name"),
|
||||
IPv6Nameservers: types.ListValueMust(types.StringType, []attr.Value{
|
||||
types.StringValue("ns1"),
|
||||
types.StringValue("ns2"),
|
||||
}),
|
||||
Labels: types.MapValueMust(types.StringType, map[string]attr.Value{
|
||||
"key": types.StringValue("value"),
|
||||
}),
|
||||
Routed: types.BoolValue(true),
|
||||
IPv6Gateway: types.StringValue("gateway"),
|
||||
},
|
||||
Model{
|
||||
ProjectId: types.StringValue("pid"),
|
||||
NetworkId: types.StringValue("nid"),
|
||||
Labels: types.MapNull(types.StringType),
|
||||
},
|
||||
&iaas.PartialUpdateNetworkPayload{
|
||||
Name: utils.Ptr("name"),
|
||||
AddressFamily: &iaas.UpdateNetworkAddressFamily{
|
||||
Ipv6: &iaas.UpdateNetworkIPv6Body{
|
||||
Nameservers: &[]string{
|
||||
"ns1",
|
||||
"ns2",
|
||||
},
|
||||
Gateway: iaas.NewNullableString(utils.Ptr("gateway")),
|
||||
},
|
||||
},
|
||||
Labels: &map[string]interface{}{
|
||||
"key": "value",
|
||||
},
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"ipv6_gateway_nil",
|
||||
&Model{
|
||||
Name: types.StringValue("name"),
|
||||
IPv6Nameservers: types.ListValueMust(types.StringType, []attr.Value{
|
||||
types.StringValue("ns1"),
|
||||
types.StringValue("ns2"),
|
||||
}),
|
||||
Labels: types.MapValueMust(types.StringType, map[string]attr.Value{
|
||||
"key": types.StringValue("value"),
|
||||
}),
|
||||
Routed: types.BoolValue(true),
|
||||
},
|
||||
Model{
|
||||
ProjectId: types.StringValue("pid"),
|
||||
NetworkId: types.StringValue("nid"),
|
||||
Labels: types.MapNull(types.StringType),
|
||||
},
|
||||
&iaas.PartialUpdateNetworkPayload{
|
||||
Name: utils.Ptr("name"),
|
||||
AddressFamily: &iaas.UpdateNetworkAddressFamily{
|
||||
Ipv6: &iaas.UpdateNetworkIPv6Body{
|
||||
Nameservers: &[]string{
|
||||
"ns1",
|
||||
"ns2",
|
||||
},
|
||||
},
|
||||
},
|
||||
Labels: &map[string]interface{}{
|
||||
"key": "value",
|
||||
},
|
||||
},
|
||||
true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.description, func(t *testing.T) {
|
||||
output, err := toUpdatePayload(context.Background(), tt.input, types.MapNull(types.StringType))
|
||||
output, err := toUpdatePayload(context.Background(), tt.input, &tt.state)
|
||||
if !tt.isValid && err == nil {
|
||||
t.Fatalf("Should have failed")
|
||||
}
|
||||
|
|
@ -286,7 +676,7 @@ func TestToUpdatePayload(t *testing.T) {
|
|||
t.Fatalf("Should not have failed: %v", err)
|
||||
}
|
||||
if tt.isValid {
|
||||
diff := cmp.Diff(output, tt.expected)
|
||||
diff := cmp.Diff(output, tt.expected, cmp.AllowUnexported(iaas.NullableString{}))
|
||||
if diff != "" {
|
||||
t.Fatalf("Data does not match: %s", diff)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue