diff --git a/.changelog/879.txt b/.changelog/879.txt
new file mode 100644
index 00000000..1d604b51
--- /dev/null
+++ b/.changelog/879.txt
@@ -0,0 +1,7 @@
+```release-note:new-resource
+`resource/cloudavenue_vdc_network_isolated` - Added a new resource to manage isolated networks in a VDC. This resource replace the deprecated `cloudavenue_network_isolated` resource.
+```
+
+```release-note:new-data-source
+`datasource/cloudavenue_vdc_network_isolated` - Added a new data source to fetch information about an isolated network in a VDC. This data source replace the deprecated `cloudavenue_network_isolated` data source.
+```
\ No newline at end of file
diff --git a/docs/data-sources/vdc_network_isolated.md b/docs/data-sources/vdc_network_isolated.md
new file mode 100644
index 00000000..07af3957
--- /dev/null
+++ b/docs/data-sources/vdc_network_isolated.md
@@ -0,0 +1,48 @@
+---
+page_title: "cloudavenue_vdc_network_isolated Data Source - cloudavenue"
+subcategory: "vDC (Virtual Datacenter)"
+description: |-
+ The cloudavenue_vdc_network_isolated data source allows you to retrieve information about an isolated network in a VDC.
+---
+
+# cloudavenue_vdc_network_isolated (Data Source)
+
+The `cloudavenue_vdc_network_isolated` data source allows you to retrieve information about an isolated network in a `VDC`.
+
+## Example Usage
+
+```terraform
+data "cloudavenue_vdc_network_isolated" "example" {
+ vdc = cloudavenue_vdc.example.name
+ name = "my-isolated-network"
+}
+```
+
+
+## Schema
+
+### Required
+
+- `name` (String) The name of the network. This value must be unique within the `VDC` that owns the network.
+- `vdc` (String) The name of vDC to use.
+
+### Read-Only
+
+- `description` (String) A description of the network.
+- `dns1` (String) The primary DNS server IP address for the network.
+- `dns2` (String) The secondary DNS server IP address for the network.
+- `dns_suffix` (String) The DNS suffix for the network.
+- `gateway` (String) The gateway IP address for the network. This value define also the network IP range with the prefix length.
+- `guest_vlan_allowed` (Boolean) Indicates if the network allows guest VLANs.
+- `id` (String) The ID of the isolated network.
+- `prefix_length` (Number) The prefix length for the network. This value must be a valid prefix length for the network IP range. (e.g. /24 for netmask 255.255.255.0).
+- `static_ip_pool` (Attributes Set) A set of static IP pools to be used for this network. (see [below for nested schema](#nestedatt--static_ip_pool))
+
+
+### Nested Schema for `static_ip_pool`
+
+Read-Only:
+
+- `end_address` (String) The end address of the IP pool. This value must be a valid IP address in the network IP range.
+- `start_address` (String) The start address of the IP pool. This value must be a valid IP address in the network IP range.
+
diff --git a/docs/resources/vdc_network_isolated.md b/docs/resources/vdc_network_isolated.md
new file mode 100644
index 00000000..22e57885
--- /dev/null
+++ b/docs/resources/vdc_network_isolated.md
@@ -0,0 +1,95 @@
+---
+page_title: "cloudavenue_vdc_network_isolated Resource - cloudavenue"
+subcategory: "vDC (Virtual Datacenter)"
+description: |-
+ The cloudavenue_vdc_network_isolated resource allows you to manage an isolated network in a VDC.
+---
+
+# cloudavenue_vdc_network_isolated (Resource)
+
+The `cloudavenue_vdc_network_isolated` resource allows you to manage an isolated network in a `VDC`.
+
+## Example Usage
+
+```terraform
+resource "cloudavenue_vdc_network_isolated" "example" {
+ name = "my-isolated-network"
+ vdc = cloudavenue_vdc.example.name
+
+ gateway = "192.168.0.1"
+ prefix_length = 24
+
+ dns1 = "192.168.0.2"
+ dns2 = "192.168.0.3"
+ dns_suffix = "example.local"
+}
+```
+
+
+## Schema
+
+### Required
+
+- `gateway` (String) (ForceNew) The gateway IP address for the network. This value define also the network IP range with the prefix length. Must be a valid IP with net.ParseIP.
+- `name` (String) The name of the network. This value must be unique within the `VDC` that owns the network.
+- `prefix_length` (Number) (ForceNew) The prefix length for the network. This value must be a valid prefix length for the network IP range. (e.g. /24 for netmask 255.255.255.0). Value must be between 1 and 32.
+- `vdc` (String) (ForceNew) The name of vDC to use.
+
+### Optional
+
+- `description` (String) A description of the network.
+- `dns1` (String) The primary DNS server IP address for the network. Must be a valid IP with net.ParseIP.
+- `dns2` (String) The secondary DNS server IP address for the network. Must be a valid IP with net.ParseIP.
+- `dns_suffix` (String) The DNS suffix for the network.
+- `guest_vlan_allowed` (Boolean) Indicates if the network allows guest VLANs. Value defaults to `false`.
+- `static_ip_pool` (Attributes Set) A set of static IP pools to be used for this network. (see [below for nested schema](#nestedatt--static_ip_pool))
+
+### Read-Only
+
+- `id` (String) The ID of the isolated network.
+
+
+### Nested Schema for `static_ip_pool`
+
+Required:
+
+- `end_address` (String) The end address of the IP pool. This value must be a valid IP address in the network IP range. Must be a valid IP with net.ParseIP.
+- `start_address` (String) The start address of the IP pool. This value must be a valid IP address in the network IP range. Must be a valid IP with net.ParseIP.
+
+## Advanced Usage
+
+Define `static_ip_pool` as a list of objects to create multiple IP pools.
+
+```hcl
+resource "cloudavenue_vdc_network_isolated" "example" {
+ name = "my-isolated-network"
+ vdc = cloudavenue_vdc.example.name
+
+ gateway = "192.168.0.1"
+ prefix_length = 24
+
+ dns1 = "192.168.0.2"
+ dns2 = "192.168.0.3"
+ dns_suffix = "example.local"
+
+ static_ip_pool = [
+ {
+ start_address = "192.168.0.10"
+ end_address = "192.168.0.20"
+ },
+ {
+ start_address = "192.168.0.100"
+ end_address = "192.168.0.130"
+ }
+ ]
+}
+
+```
+
+## Import
+
+Import is supported using the following syntax:
+```shell
+# VDC Network isolated can be imported using the VDC name and the network name or ID.
+terraform import cloudavenue_vdc_network_isolated.example vdc.networkNameOrId
+```
diff --git a/examples/data-sources/cloudavenue_vdc_network_isolated/data-source.tf b/examples/data-sources/cloudavenue_vdc_network_isolated/data-source.tf
new file mode 100644
index 00000000..496afe92
--- /dev/null
+++ b/examples/data-sources/cloudavenue_vdc_network_isolated/data-source.tf
@@ -0,0 +1,4 @@
+data "cloudavenue_vdc_network_isolated" "example" {
+ vdc = cloudavenue_vdc.example.name
+ name = "my-isolated-network"
+}
diff --git a/examples/resources/cloudavenue_vdc_network_isolated/import.sh b/examples/resources/cloudavenue_vdc_network_isolated/import.sh
new file mode 100644
index 00000000..2e480afb
--- /dev/null
+++ b/examples/resources/cloudavenue_vdc_network_isolated/import.sh
@@ -0,0 +1,2 @@
+# VDC Network isolated can be imported using the VDC name and the network name or ID.
+terraform import cloudavenue_vdc_network_isolated.example vdc.networkNameOrId
\ No newline at end of file
diff --git a/examples/resources/cloudavenue_vdc_network_isolated/resource.tf b/examples/resources/cloudavenue_vdc_network_isolated/resource.tf
new file mode 100644
index 00000000..ec35f77f
--- /dev/null
+++ b/examples/resources/cloudavenue_vdc_network_isolated/resource.tf
@@ -0,0 +1,11 @@
+resource "cloudavenue_vdc_network_isolated" "example" {
+ name = "my-isolated-network"
+ vdc = cloudavenue_vdc.example.name
+
+ gateway = "192.168.0.1"
+ prefix_length = 24
+
+ dns1 = "192.168.0.2"
+ dns2 = "192.168.0.3"
+ dns_suffix = "example.local"
+}
diff --git a/go.mod b/go.mod
index 4f5d136b..c7e6754a 100644
--- a/go.mod
+++ b/go.mod
@@ -23,7 +23,7 @@ require (
github.com/hashicorp/terraform-plugin-log v0.9.0
github.com/hashicorp/terraform-plugin-sdk/v2 v2.35.0
github.com/iancoleman/strcase v0.3.0
- github.com/orange-cloudavenue/cloudavenue-sdk-go v0.14.0
+ github.com/orange-cloudavenue/cloudavenue-sdk-go v0.14.1-0.20241212084109-0015a69a610a
github.com/orange-cloudavenue/common-go/utils v0.0.0-20240119163616-66b473d92339
github.com/rs/zerolog v1.33.0
github.com/thanhpk/randstr v1.0.6
@@ -45,6 +45,7 @@ require (
github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect
github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de // indirect
github.com/armon/go-radix v1.0.0 // indirect
+ github.com/avast/retry-go/v4 v4.6.0 // indirect
github.com/bgentry/speakeasy v0.1.0 // indirect
github.com/bmatcuk/doublestar/v4 v4.7.1 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
@@ -56,7 +57,7 @@ require (
github.com/go-chi/chi v4.1.2+incompatible // indirect
github.com/go-chi/render v1.0.3 // indirect
github.com/go-redis/redis/v8 v8.11.5 // indirect
- github.com/go-resty/resty/v2 v2.16.0 // indirect
+ github.com/go-resty/resty/v2 v2.16.2 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/hashicorp/cli v1.1.6 // indirect
diff --git a/go.sum b/go.sum
index 16cc678f..db351940 100644
--- a/go.sum
+++ b/go.sum
@@ -35,6 +35,8 @@ github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de h1:FxWPpzIjnTlhP
github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de/go.mod h1:DCaWoUhZrYW9p1lxo/cm8EmUOOzAPSEZNGF2DK1dJgw=
github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI=
github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
+github.com/avast/retry-go/v4 v4.6.0 h1:K9xNA+KeB8HHc2aWFuLb25Offp+0iVRXEvFx8IinRJA=
+github.com/avast/retry-go/v4 v4.6.0/go.mod h1:gvWlPhBVsvBbLkVGDg/KwvBv0bEkCOLRRSHKIr2PyOE=
github.com/aws/aws-sdk-go v1.31.9/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
github.com/aws/aws-sdk-go v1.55.5 h1:KKUZBfBoyqy5d3swXyiC7Q76ic40rYcbqH7qjh59kzU=
github.com/aws/aws-sdk-go v1.55.5/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU=
@@ -93,8 +95,8 @@ github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
-github.com/go-resty/resty/v2 v2.16.0 h1:qpKalHWI2bpp9BIKlyT8TYWEJXOk1NuKbfiT3RRnzWc=
-github.com/go-resty/resty/v2 v2.16.0/go.mod h1:0fHAoK7JoBy/Ch36N8VFeMsK7xQOHhvWaC3iOktwmIU=
+github.com/go-resty/resty/v2 v2.16.2 h1:CpRqTjIzq/rweXUt9+GxzzQdlkqMdt8Lm/fuK/CAbAg=
+github.com/go-resty/resty/v2 v2.16.2/go.mod h1:0fHAoK7JoBy/Ch36N8VFeMsK7xQOHhvWaC3iOktwmIU=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68=
github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
@@ -250,8 +252,8 @@ github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs=
-github.com/orange-cloudavenue/cloudavenue-sdk-go v0.14.0 h1:IHqwdPRAEfw/xP6I0COzE9hsju7Hk+TLjd3xzJ6AOqM=
-github.com/orange-cloudavenue/cloudavenue-sdk-go v0.14.0/go.mod h1:CTQO1VIVFvImvmKoR4ntL3HxBi5REm6ssLzUj3kv1sc=
+github.com/orange-cloudavenue/cloudavenue-sdk-go v0.14.1-0.20241212084109-0015a69a610a h1:z2os66FLZiYX+SogPZUwlRALepmnx4HE3Nf9JM7is6Q=
+github.com/orange-cloudavenue/cloudavenue-sdk-go v0.14.1-0.20241212084109-0015a69a610a/go.mod h1:c/V9npNz22QjlTXEsx0GWoxhzMFYiLynlCUPQOImd2w=
github.com/orange-cloudavenue/common-go/utils v0.0.0-20240119163616-66b473d92339 h1:DEKcWLGbEhu/I6kn9NAXhVCFrbPhR+Ef7oLmpLVnnPM=
github.com/orange-cloudavenue/common-go/utils v0.0.0-20240119163616-66b473d92339/go.mod h1:11JAFfGWVmhoT4AAORKsIC5M6nI+uDGSEOScMzavgPA=
github.com/peterhellberg/link v1.2.0 h1:UA5pg3Gp/E0F2WdX7GERiNrPQrM1K6CVJUUWfHa4t6c=
diff --git a/internal/provider/provider_datasources.go b/internal/provider/provider_datasources.go
index 6ce9df5d..99f98eb5 100644
--- a/internal/provider/provider_datasources.go
+++ b/internal/provider/provider_datasources.go
@@ -51,6 +51,7 @@ func (p *cloudavenueProvider) DataSources(_ context.Context) []func() datasource
vdc.NewVDCsDataSource,
vdc.NewVDCDataSource,
vdc.NewGroupDataSource,
+ vdc.NewNetworkIsolatedDataSource,
// * VDC GROUP
vdcg.NewVDCGDataSource,
diff --git a/internal/provider/provider_resources.go b/internal/provider/provider_resources.go
index 28def074..6b248a56 100644
--- a/internal/provider/provider_resources.go
+++ b/internal/provider/provider_resources.go
@@ -41,6 +41,7 @@ func (p *cloudavenueProvider) Resources(_ context.Context) []func() resource.Res
vdc.NewVDCResource,
vdc.NewACLResource,
vdc.NewGroupResource,
+ vdc.NewNetworkIsolatedResource,
// * VDC Group
vdcg.NewVDCGResource,
diff --git a/internal/provider/vdc/network_isolated_datasource.go b/internal/provider/vdc/network_isolated_datasource.go
new file mode 100644
index 00000000..97b5fb4a
--- /dev/null
+++ b/internal/provider/vdc/network_isolated_datasource.go
@@ -0,0 +1,102 @@
+package vdc
+
+import (
+ "context"
+ "fmt"
+
+ "github.com/hashicorp/terraform-plugin-framework/diag"
+
+ "github.com/hashicorp/terraform-plugin-framework/datasource"
+
+ "github.com/orange-cloudavenue/terraform-provider-cloudavenue/internal/client"
+ "github.com/orange-cloudavenue/terraform-provider-cloudavenue/internal/metrics"
+ "github.com/orange-cloudavenue/terraform-provider-cloudavenue/internal/provider/common/vdc"
+)
+
+var (
+ _ datasource.DataSource = &NetworkIsolatedDataSource{}
+ _ datasource.DataSourceWithConfigure = &NetworkIsolatedDataSource{}
+)
+
+func NewNetworkIsolatedDataSource() datasource.DataSource {
+ return &NetworkIsolatedDataSource{}
+}
+
+type NetworkIsolatedDataSource struct {
+ client *client.CloudAvenue
+ vdc vdc.VDC
+}
+
+func (d *NetworkIsolatedDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
+ resp.TypeName = req.ProviderTypeName + "_" + categoryName + "_network_isolated"
+}
+
+// Init Initializes the resource.
+func (d *NetworkIsolatedDataSource) Init(ctx context.Context, rm *networkIsolatedModel) (diags diag.Diagnostics) {
+ d.vdc, diags = vdc.Init(d.client, rm.VDC.StringValue)
+ return
+}
+
+func (d *NetworkIsolatedDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) {
+ resp.Schema = networkIsolatedSchema(ctx).GetDataSource(ctx)
+}
+
+func (d *NetworkIsolatedDataSource) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
+ // Prevent panic if the provider has not been configured.
+ if req.ProviderData == nil {
+ return
+ }
+
+ client, ok := req.ProviderData.(*client.CloudAvenue)
+
+ if !ok {
+ resp.Diagnostics.AddError(
+ "Unexpected Data Source Configure Type",
+ fmt.Sprintf("Expected *client.CloudAvenue, got: %T. Please report this issue to the provider developers.", req.ProviderData),
+ )
+
+ return
+ }
+
+ d.client = client
+}
+
+func (d *NetworkIsolatedDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
+ defer metrics.New("data.cloudavenue_vdc_network_isolated", d.client.GetOrgName(), metrics.Read)()
+
+ config := &networkIsolatedModel{}
+
+ // Read Terraform configuration data into the model
+ resp.Diagnostics.Append(req.Config.Get(ctx, config)...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+ // Init the resource
+ resp.Diagnostics.Append(d.Init(ctx, config)...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ /*
+ Implement the data source read logic here.
+ */
+
+ s := &NetworkIsolatedResource{
+ client: d.client,
+ vdc: d.vdc,
+ }
+
+ // Read data from the API
+ data, found, diags := s.read(ctx, config)
+ if !found {
+ resp.Diagnostics.AddError("Resource not found", fmt.Sprintf("The isolated network '%s' was not found in the VDC '%s'.", config.Name.Get(), config.VDC.Get()))
+ return
+ }
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ // Save data into Terraform state
+ resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
+}
diff --git a/internal/provider/vdc/network_isolated_resource.go b/internal/provider/vdc/network_isolated_resource.go
new file mode 100644
index 00000000..494d56e0
--- /dev/null
+++ b/internal/provider/vdc/network_isolated_resource.go
@@ -0,0 +1,360 @@
+package vdc
+
+import (
+ "context"
+ "fmt"
+ "strings"
+
+ "github.com/vmware/go-vcloud-director/v2/govcd"
+
+ "github.com/hashicorp/terraform-plugin-framework/diag"
+
+ "github.com/hashicorp/terraform-plugin-framework/resource"
+
+ supertypes "github.com/FrangipaneTeam/terraform-plugin-framework-supertypes"
+
+ "github.com/orange-cloudavenue/cloudavenue-sdk-go/pkg/urn"
+ v1 "github.com/orange-cloudavenue/cloudavenue-sdk-go/v1"
+ "github.com/orange-cloudavenue/terraform-provider-cloudavenue/internal/client"
+ "github.com/orange-cloudavenue/terraform-provider-cloudavenue/internal/metrics"
+ "github.com/orange-cloudavenue/terraform-provider-cloudavenue/internal/provider/common/vdc"
+)
+
+// Ensure the implementation satisfies the expected interfaces.
+var (
+ _ resource.Resource = &NetworkIsolatedResource{}
+ _ resource.ResourceWithConfigure = &NetworkIsolatedResource{}
+ _ resource.ResourceWithImportState = &NetworkIsolatedResource{}
+)
+
+// NewNetworkIsolatedResource is a helper function to simplify the provider implementation.
+func NewNetworkIsolatedResource() resource.Resource {
+ return &NetworkIsolatedResource{}
+}
+
+// NetworkIsolatedResource is the resource implementation.
+type NetworkIsolatedResource struct {
+ client *client.CloudAvenue
+ vdc vdc.VDC
+}
+
+// Init Initializes the resource.
+func (r *NetworkIsolatedResource) Init(ctx context.Context, rm *networkIsolatedModel) (diags diag.Diagnostics) {
+ r.vdc, diags = vdc.Init(r.client, rm.VDC.StringValue)
+ return
+}
+
+// Metadata returns the resource type name.
+func (r *NetworkIsolatedResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
+ resp.TypeName = req.ProviderTypeName + "_" + categoryName + "_network_isolated"
+}
+
+// Schema defines the schema for the resource.
+func (r *NetworkIsolatedResource) Schema(ctx context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
+ resp.Schema = networkIsolatedSchema(ctx).GetResource(ctx)
+}
+
+func (r *NetworkIsolatedResource) Configure(ctx context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) {
+ // Prevent panic if the provider has not been configured.
+ if req.ProviderData == nil {
+ return
+ }
+
+ client, ok := req.ProviderData.(*client.CloudAvenue)
+ if !ok {
+ resp.Diagnostics.AddError(
+ "Unexpected Resource Configure Type",
+ fmt.Sprintf("Expected *client.CloudAvenue, got: %T. Please report this issue to the provider developers.", req.ProviderData),
+ )
+ return
+ }
+ r.client = client
+}
+
+// Create creates the resource and sets the initial Terraform state.
+func (r *NetworkIsolatedResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
+ defer metrics.New("cloudavenue_vdc_network_isolated", r.client.GetOrgName(), metrics.Create)()
+
+ plan := &networkIsolatedModel{}
+
+ // Retrieve values from plan
+ resp.Diagnostics.Append(req.Plan.Get(ctx, plan)...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ // Init the resource
+ resp.Diagnostics.Append(r.Init(ctx, plan)...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ /*
+ Implement the resource creation logic here.
+ */
+
+ values, d := plan.ToSDK(ctx)
+ if d.HasError() {
+ resp.Diagnostics.Append(d...)
+ return
+ }
+
+ networkIsolated, err := r.vdc.CreateNetworkIsolated(values)
+ if err != nil {
+ resp.Diagnostics.AddError("Error creating isolated network", err.Error())
+ return
+ }
+
+ plan.ID.Set(networkIsolated.ID)
+
+ // Use generic read function to refresh the state
+ state, found, d := r.read(ctx, plan)
+ if !found {
+ resp.State.RemoveResource(ctx)
+ resp.Diagnostics.AddError("Resource not found after creation", "The resource was not found after creation.")
+ return
+ }
+ if d.HasError() {
+ resp.Diagnostics.Append(d...)
+ return
+ }
+
+ // Set state to fully populated data
+ resp.Diagnostics.Append(resp.State.Set(ctx, state)...)
+}
+
+// Read refreshes the Terraform state with the latest data.
+func (r *NetworkIsolatedResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
+ defer metrics.New("cloudavenue_vdc_network_isolated", r.client.GetOrgName(), metrics.Read)()
+
+ state := &networkIsolatedModel{}
+
+ // Get current state
+ resp.Diagnostics.Append(req.State.Get(ctx, state)...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ // Init the resource
+ resp.Diagnostics.Append(r.Init(ctx, state)...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ // Refresh the state
+ stateRefreshed, found, d := r.read(ctx, state)
+ if !found {
+ resp.State.RemoveResource(ctx)
+ return
+ }
+ if d.HasError() {
+ resp.Diagnostics.Append(d...)
+ return
+ }
+
+ // Set refreshed state
+ resp.Diagnostics.Append(resp.State.Set(ctx, stateRefreshed)...)
+}
+
+// Update updates the resource and sets the updated Terraform state on success.
+func (r *NetworkIsolatedResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
+ defer metrics.New("cloudavenue_vdc_network_isolated", r.client.GetOrgName(), metrics.Update)()
+
+ var (
+ plan = &networkIsolatedModel{}
+ state = &networkIsolatedModel{}
+ )
+
+ // Get current plan and state
+ resp.Diagnostics.Append(req.Plan.Get(ctx, plan)...)
+ resp.Diagnostics.Append(req.State.Get(ctx, state)...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ // Init the resource
+ resp.Diagnostics.Append(r.Init(ctx, state)...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ /*
+ Implement the resource update here
+ */
+
+ values, d := plan.ToSDK(ctx)
+ if d.HasError() {
+ resp.Diagnostics.Append(d...)
+ return
+ }
+
+ net, err := r.vdc.GetNetworkIsolated(state.ID.Get())
+ if err != nil {
+ resp.Diagnostics.AddError("Error getting isolated network", err.Error())
+ return
+ }
+
+ values.ID = state.ID.Get()
+
+ // Update the network
+ if err := net.Update(values); err != nil {
+ resp.Diagnostics.AddError("Error updating isolated network", err.Error())
+ return
+ }
+
+ // Use generic read function to refresh the state
+ stateRefreshed, found, d := r.read(ctx, state)
+ if !found {
+ resp.State.RemoveResource(ctx)
+ resp.Diagnostics.AddError("Resource not found after update", "The resource was not found after update. Please refresh the state.")
+ return
+ }
+ if d.HasError() {
+ resp.Diagnostics.Append(d...)
+ return
+ }
+
+ // Set state to fully populated data
+ resp.Diagnostics.Append(resp.State.Set(ctx, stateRefreshed)...)
+}
+
+// Delete deletes the resource and removes the Terraform state on success.
+func (r *NetworkIsolatedResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
+ defer metrics.New("cloudavenue_vdc_network_isolated", r.client.GetOrgName(), metrics.Delete)()
+
+ state := &networkIsolatedModel{}
+
+ // Get current state
+ resp.Diagnostics.Append(req.State.Get(ctx, state)...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ // Init the resource
+ resp.Diagnostics.Append(r.Init(ctx, state)...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ /*
+ Implement the resource deletion here
+ */
+
+ net, err := r.vdc.GetNetworkIsolated(state.ID.Get())
+ if err != nil {
+ resp.Diagnostics.AddError("Error getting isolated network", err.Error())
+ return
+ }
+
+ // Delete the network
+ if err := net.Delete(); err != nil {
+ resp.Diagnostics.AddError("Error deleting isolated network", err.Error())
+ return
+ }
+}
+
+func (r *NetworkIsolatedResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
+ defer metrics.New("cloudavenue_vdc_network_isolated", r.client.GetOrgName(), metrics.Import)()
+
+ // * Import with custom logic
+ idParts := strings.Split(req.ID, ".")
+
+ if len(idParts) != 2 {
+ resp.Diagnostics.AddError(
+ "Unexpected Import Identifier",
+ fmt.Sprintf("Expected import identifier with format: vdc.networkNameOrID Got: %q", req.ID),
+ )
+ return
+ }
+
+ x := &networkIsolatedModel{
+ ID: supertypes.NewStringNull(),
+ Name: supertypes.NewStringNull(),
+ VDC: supertypes.NewStringNull(),
+ }
+
+ x.VDC.Set(idParts[0])
+
+ if urn.IsNetwork(idParts[1]) {
+ x.ID.Set(idParts[1])
+ } else {
+ x.Name.Set(idParts[1])
+ }
+
+ resp.Diagnostics.Append(r.Init(ctx, x)...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ stateRefreshed, found, d := r.read(ctx, x)
+ if !found {
+ resp.State.RemoveResource(ctx)
+ return
+ }
+ if d.HasError() {
+ resp.Diagnostics.Append(d...)
+ return
+ }
+
+ // Set refreshed state
+ resp.Diagnostics.Append(resp.State.Set(ctx, stateRefreshed)...)
+}
+
+// * CustomFuncs
+
+// read is a generic read function that can be used by the resource Create, Read and Update functions.
+func (r *NetworkIsolatedResource) read(ctx context.Context, planOrState *networkIsolatedModel) (stateRefreshed *networkIsolatedModel, found bool, diags diag.Diagnostics) {
+ stateRefreshed = planOrState.Copy()
+
+ /*
+ Implement the resource read here
+ */
+
+ var (
+ net *v1.VDCNetworkIsolated
+ err error
+ )
+
+ if urn.IsNetwork(planOrState.ID.Get()) {
+ net, err = r.vdc.GetNetworkIsolated(planOrState.ID.Get())
+ } else {
+ net, err = r.vdc.GetNetworkIsolated(planOrState.Name.Get())
+ }
+ if err != nil {
+ if govcd.ContainsNotFound(err) {
+ return nil, false, nil
+ }
+ diags.AddError("Error getting isolated network", err.Error())
+ return
+ }
+
+ // Populate the state with the network data
+ stateRefreshed.ID.Set(net.ID)
+ stateRefreshed.Name.Set(net.Name)
+ stateRefreshed.Description.Set(net.Description)
+ stateRefreshed.VDC.Set(r.vdc.GetName())
+ stateRefreshed.Gateway.Set(net.Subnet.Gateway)
+ stateRefreshed.PrefixLength.SetInt(net.Subnet.PrefixLength)
+ stateRefreshed.DNS1.Set(net.Subnet.DNSServer1)
+ stateRefreshed.DNS2.Set(net.Subnet.DNSServer2)
+ stateRefreshed.DNSSuffix.Set(net.Subnet.DNSSuffix)
+ stateRefreshed.GuestVLANAllowed.SetPtr(net.GuestVLANTaggingAllowed)
+
+ x := []*networkIsolatedModelStaticIPPool{}
+ for _, ipRange := range net.Subnet.IPRanges {
+ n := &networkIsolatedModelStaticIPPool{
+ StartAddress: supertypes.NewStringNull(),
+ EndAddress: supertypes.NewStringNull(),
+ }
+ n.StartAddress.Set(ipRange.StartAddress)
+ n.EndAddress.Set(ipRange.EndAddress)
+ x = append(x, n)
+ }
+
+ diags.Append(stateRefreshed.StaticIPPool.Set(ctx, x)...)
+ if diags.HasError() {
+ return nil, true, diags
+ }
+
+ return stateRefreshed, true, nil
+}
diff --git a/internal/provider/vdc/network_isolated_schema.go b/internal/provider/vdc/network_isolated_schema.go
new file mode 100644
index 00000000..272778ca
--- /dev/null
+++ b/internal/provider/vdc/network_isolated_schema.go
@@ -0,0 +1,192 @@
+package vdc
+
+import (
+ "context"
+
+ "github.com/hashicorp/terraform-plugin-framework/schema/validator"
+
+ schemaD "github.com/hashicorp/terraform-plugin-framework/datasource/schema"
+ schemaR "github.com/hashicorp/terraform-plugin-framework/resource/schema"
+
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/int64planmodifier"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
+
+ "github.com/hashicorp/terraform-plugin-framework-validators/int64validator"
+
+ superschema "github.com/FrangipaneTeam/terraform-plugin-framework-superschema"
+ fstringvalidator "github.com/FrangipaneTeam/terraform-plugin-framework-validators/stringvalidator"
+)
+
+func networkIsolatedSchema(_ context.Context) superschema.Schema {
+ return superschema.Schema{
+ Resource: superschema.SchemaDetails{
+ MarkdownDescription: "The `cloudavenue_vdc_network_isolated` resource allows you to manage an isolated network in a `VDC`.",
+ },
+ DataSource: superschema.SchemaDetails{
+ MarkdownDescription: "The `cloudavenue_vdc_network_isolated` data source allows you to retrieve information about an isolated network in a `VDC`.",
+ },
+ Attributes: map[string]superschema.Attribute{
+ "id": superschema.SuperStringAttribute{
+ Common: &schemaR.StringAttribute{
+ Computed: true,
+ MarkdownDescription: "The ID of the isolated network.",
+ },
+ },
+ "name": superschema.SuperStringAttribute{
+ Common: &schemaR.StringAttribute{
+ MarkdownDescription: "The name of the network. This value must be unique within the `VDC` that owns the network.",
+ Required: true,
+ },
+ },
+ "description": superschema.SuperStringAttribute{
+ Common: &schemaR.StringAttribute{
+ MarkdownDescription: "A description of the network.",
+ },
+ Resource: &schemaR.StringAttribute{
+ Optional: true,
+ },
+ DataSource: &schemaD.StringAttribute{
+ Computed: true,
+ },
+ },
+ "vdc": superschema.SuperStringAttribute{
+ Common: &schemaR.StringAttribute{
+ MarkdownDescription: "The name of vDC to use",
+ Required: true,
+ },
+ Resource: &schemaR.StringAttribute{
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.RequiresReplace(),
+ },
+ },
+ },
+ "gateway": superschema.SuperStringAttribute{
+ Common: &schemaR.StringAttribute{
+ MarkdownDescription: "The gateway IP address for the network. This value define also the network IP range with the prefix length.",
+ },
+ Resource: &schemaR.StringAttribute{
+ Required: true,
+ Validators: []validator.String{
+ fstringvalidator.IsIP(),
+ },
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.RequiresReplace(),
+ },
+ },
+ DataSource: &schemaD.StringAttribute{
+ Computed: true,
+ },
+ },
+ "guest_vlan_allowed": superschema.SuperBoolAttribute{
+ Common: &schemaR.BoolAttribute{
+ MarkdownDescription: "Indicates if the network allows guest VLANs.",
+ Computed: true,
+ },
+ Resource: &schemaR.BoolAttribute{
+ Optional: true,
+ Default: booldefault.StaticBool(false),
+ },
+ },
+ "prefix_length": superschema.SuperInt64Attribute{
+ Common: &schemaR.Int64Attribute{
+ MarkdownDescription: "The prefix length for the network. This value must be a valid prefix length for the network IP range. (e.g. /24 for netmask 255.255.255.0)",
+ },
+ Resource: &schemaR.Int64Attribute{
+ Required: true,
+ Validators: []validator.Int64{
+ int64validator.Between(1, 32),
+ },
+ PlanModifiers: []planmodifier.Int64{
+ int64planmodifier.RequiresReplace(),
+ },
+ },
+ DataSource: &schemaD.Int64Attribute{
+ Computed: true,
+ },
+ },
+ "dns1": superschema.SuperStringAttribute{
+ Common: &schemaR.StringAttribute{
+ MarkdownDescription: "The primary DNS server IP address for the network.",
+ },
+ Resource: &schemaR.StringAttribute{
+ Optional: true,
+ Validators: []validator.String{
+ fstringvalidator.IsIP(),
+ },
+ },
+ DataSource: &schemaD.StringAttribute{
+ Computed: true,
+ },
+ },
+ "dns2": superschema.SuperStringAttribute{
+ Common: &schemaR.StringAttribute{
+ MarkdownDescription: "The secondary DNS server IP address for the network.",
+ },
+ Resource: &schemaR.StringAttribute{
+ Optional: true,
+ Validators: []validator.String{
+ fstringvalidator.IsIP(),
+ },
+ },
+ DataSource: &schemaD.StringAttribute{
+ Computed: true,
+ },
+ },
+ "dns_suffix": superschema.SuperStringAttribute{
+ Common: &schemaR.StringAttribute{
+ MarkdownDescription: "The DNS suffix for the network.",
+ },
+ Resource: &schemaR.StringAttribute{
+ Optional: true,
+ },
+ DataSource: &schemaD.StringAttribute{
+ Computed: true,
+ },
+ },
+ "static_ip_pool": superschema.SuperSetNestedAttributeOf[networkIsolatedModelStaticIPPool]{
+ Common: &schemaR.SetNestedAttribute{
+ MarkdownDescription: "A set of static IP pools to be used for this network.",
+ },
+ Resource: &schemaR.SetNestedAttribute{
+ Optional: true,
+ Computed: true,
+ },
+ DataSource: &schemaD.SetNestedAttribute{
+ Computed: true,
+ },
+ Attributes: map[string]superschema.Attribute{
+ "start_address": superschema.SuperStringAttribute{
+ Common: &schemaR.StringAttribute{
+ MarkdownDescription: "The start address of the IP pool. This value must be a valid IP address in the network IP range.",
+ },
+ Resource: &schemaR.StringAttribute{
+ Required: true,
+ Validators: []validator.String{
+ fstringvalidator.IsIP(),
+ },
+ },
+ DataSource: &schemaD.StringAttribute{
+ Computed: true,
+ },
+ },
+ "end_address": superschema.SuperStringAttribute{
+ Common: &schemaR.StringAttribute{
+ MarkdownDescription: "The end address of the IP pool. This value must be a valid IP address in the network IP range.",
+ },
+ Resource: &schemaR.StringAttribute{
+ Required: true,
+ Validators: []validator.String{
+ fstringvalidator.IsIP(),
+ },
+ },
+ DataSource: &schemaD.StringAttribute{
+ Computed: true,
+ },
+ },
+ },
+ },
+ },
+ }
+}
diff --git a/internal/provider/vdc/network_isolated_schema_test.go b/internal/provider/vdc/network_isolated_schema_test.go
new file mode 100644
index 00000000..db7558b3
--- /dev/null
+++ b/internal/provider/vdc/network_isolated_schema_test.go
@@ -0,0 +1,57 @@
+package vdc_test
+
+import (
+ "context"
+ "testing"
+
+ // fwdatasource "github.com/hashicorp/terraform-plugin-framework/datasource".
+ fwdatasource "github.com/hashicorp/terraform-plugin-framework/datasource"
+ fwresource "github.com/hashicorp/terraform-plugin-framework/resource"
+
+ "github.com/orange-cloudavenue/terraform-provider-cloudavenue/internal/provider/vdc"
+)
+
+// Unit test for the schema of the resource cloudavenue_vdc_NetworkIsolated.
+func TestNetworkIsolatedResourceSchema(t *testing.T) {
+ t.Parallel()
+
+ ctx := context.Background()
+ schemaResponse := &fwresource.SchemaResponse{}
+
+ // Instantiate the resource.Resource and call its Schema method
+ vdc.NewNetworkIsolatedResource().Schema(ctx, fwresource.SchemaRequest{}, schemaResponse)
+
+ if schemaResponse.Diagnostics.HasError() {
+ t.Fatalf("Schema method diagnostics: %+v", schemaResponse.Diagnostics)
+ }
+
+ // Validate the schema
+ diagnostics := schemaResponse.Schema.ValidateImplementation(ctx)
+
+ if diagnostics.HasError() {
+ t.Fatalf("Schema validation diagnostics: %+v", diagnostics)
+ }
+}
+
+// Unit test for the schema of the datasource cloudavenue_vdc_NetworkIsolated
+
+func TestNetworkIsolatedDataSourceSchema(t *testing.T) {
+ t.Parallel()
+
+ ctx := context.Background()
+ schemaResponse := &fwdatasource.SchemaResponse{}
+
+ // Instantiate the datasource.Datasource and call its Schema method
+ vdc.NewNetworkIsolatedDataSource().Schema(ctx, fwdatasource.SchemaRequest{}, schemaResponse)
+
+ if schemaResponse.Diagnostics.HasError() {
+ t.Fatalf("Schema method diagnostics: %+v", schemaResponse.Diagnostics)
+ }
+
+ // Validate the schema
+ diagnostics := schemaResponse.Schema.ValidateImplementation(ctx)
+
+ if diagnostics.HasError() {
+ t.Fatalf("Schema validation diagnostics: %+v", diagnostics)
+ }
+}
diff --git a/internal/provider/vdc/network_isolated_types.go b/internal/provider/vdc/network_isolated_types.go
new file mode 100644
index 00000000..c23c2733
--- /dev/null
+++ b/internal/provider/vdc/network_isolated_types.go
@@ -0,0 +1,76 @@
+package vdc
+
+import (
+ "context"
+
+ "github.com/hashicorp/terraform-plugin-framework/diag"
+
+ supertypes "github.com/FrangipaneTeam/terraform-plugin-framework-supertypes"
+
+ v1 "github.com/orange-cloudavenue/cloudavenue-sdk-go/v1"
+ "github.com/orange-cloudavenue/terraform-provider-cloudavenue/pkg/utils"
+)
+
+type (
+ networkIsolatedModel struct {
+ ID supertypes.StringValue `tfsdk:"id"`
+ Name supertypes.StringValue `tfsdk:"name"`
+ Description supertypes.StringValue `tfsdk:"description"`
+ VDC supertypes.StringValue `tfsdk:"vdc"`
+ Gateway supertypes.StringValue `tfsdk:"gateway"`
+ PrefixLength supertypes.Int64Value `tfsdk:"prefix_length"`
+ DNS1 supertypes.StringValue `tfsdk:"dns1"`
+ DNS2 supertypes.StringValue `tfsdk:"dns2"`
+ DNSSuffix supertypes.StringValue `tfsdk:"dns_suffix"`
+ StaticIPPool supertypes.SetNestedObjectValueOf[networkIsolatedModelStaticIPPool] `tfsdk:"static_ip_pool"`
+ GuestVLANAllowed supertypes.BoolValue `tfsdk:"guest_vlan_allowed"`
+ }
+
+ networkIsolatedModelStaticIPPool struct {
+ StartAddress supertypes.StringValue `tfsdk:"start_address"`
+ EndAddress supertypes.StringValue `tfsdk:"end_address"`
+ }
+)
+
+func (rm *networkIsolatedModel) Copy() *networkIsolatedModel {
+ x := &networkIsolatedModel{}
+ utils.ModelCopy(rm, x)
+ return x
+}
+
+// ToSDK converts the model to the SDK model.
+func (rm *networkIsolatedModel) ToSDK(ctx context.Context) (values *v1.VDCNetworkIsolatedModel, diags diag.Diagnostics) {
+ values = &v1.VDCNetworkIsolatedModel{
+ ID: rm.ID.Get(),
+ Name: rm.Name.Get(),
+ Description: rm.Description.Get(),
+ Subnet: func() v1.VDCNetworkModelSubnet {
+ return v1.VDCNetworkModelSubnet{
+ Gateway: rm.Gateway.Get(),
+ PrefixLength: rm.PrefixLength.GetInt(),
+ DNSServer1: rm.DNS1.Get(),
+ DNSServer2: rm.DNS2.Get(),
+ DNSSuffix: rm.DNSSuffix.Get(),
+ IPRanges: func() v1.VDCNetworkModelSubnetIPRanges {
+ var ipRanges v1.VDCNetworkModelSubnetIPRanges
+
+ ipPools, d := rm.StaticIPPool.Get(ctx)
+ if d.HasError() {
+ diags.Append(d...)
+ return ipRanges
+ }
+
+ for _, ipRange := range ipPools {
+ ipRanges = append(ipRanges, v1.VDCNetworkModelSubnetIPRange{
+ StartAddress: ipRange.StartAddress.Get(),
+ EndAddress: ipRange.EndAddress.Get(),
+ })
+ }
+ return ipRanges
+ }(),
+ }
+ }(),
+ }
+
+ return values, diags
+}
diff --git a/internal/testsacc/acctest_datasources_test.go b/internal/testsacc/acctest_datasources_test.go
index 7dabb59c..6b1a7fba 100644
--- a/internal/testsacc/acctest_datasources_test.go
+++ b/internal/testsacc/acctest_datasources_test.go
@@ -14,8 +14,9 @@ func GetDataSourceConfig() map[testsacc.ResourceName]func() *testsacc.ResourceCo
Tier0VRFDataSourceName: testsacc.NewResourceConfig(NewTier0VRFDataSourceTest()),
// * VDC
- VDCDataSourceName: testsacc.NewResourceConfig(NewVDCDataSourceTest()),
- VDCGroupDataSourceName: testsacc.NewResourceConfig(NewVDCGroupDataSourceTest()),
+ VDCDataSourceName: testsacc.NewResourceConfig(NewVDCDataSourceTest()),
+ VDCGroupDataSourceName: testsacc.NewResourceConfig(NewVDCGroupDataSourceTest()),
+ VDCNetworkIsolatedDataSourceName: testsacc.NewResourceConfig(NewVDCNetworkIsolatedDataSourceTest()),
// * VDC Group
VDCGDataSourceName: testsacc.NewResourceConfig(NewVDCGDataSourceTest()),
diff --git a/internal/testsacc/acctest_resources_test.go b/internal/testsacc/acctest_resources_test.go
index 0be4da8f..15981c81 100644
--- a/internal/testsacc/acctest_resources_test.go
+++ b/internal/testsacc/acctest_resources_test.go
@@ -10,8 +10,9 @@ func GetResourceConfig() map[testsacc.ResourceName]func() *testsacc.ResourceConf
CatalogVAppTemplateDataSourceName: testsacc.NewResourceConfig(NewCatalogVAppTemplateDataSourceTest()),
// * VDC
- VDCResourceName: testsacc.NewResourceConfig(NewVDCResourceTest()),
- VDCGroupResourceName: testsacc.NewResourceConfig(NewVDCGroupResourceTest()),
+ VDCResourceName: testsacc.NewResourceConfig(NewVDCResourceTest()),
+ VDCGroupResourceName: testsacc.NewResourceConfig(NewVDCGroupResourceTest()),
+ VDCNetworkIsolatedResourceName: testsacc.NewResourceConfig(NewVDCNetworkIsolatedResourceTest()),
// * VDC Group
VDCGResourceName: testsacc.NewResourceConfig(NewVDCGResourceTest()),
diff --git a/internal/testsacc/vdc_network_isolated_datasource_test.go b/internal/testsacc/vdc_network_isolated_datasource_test.go
new file mode 100644
index 00000000..cd8dbc53
--- /dev/null
+++ b/internal/testsacc/vdc_network_isolated_datasource_test.go
@@ -0,0 +1,58 @@
+package testsacc
+
+import (
+ "context"
+ "testing"
+
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
+
+ "github.com/orange-cloudavenue/terraform-provider-cloudavenue/internal/helpers/testsacc"
+)
+
+var _ testsacc.TestACC = &VDCNetworkIsolatedDataSource{}
+
+const (
+ VDCNetworkIsolatedDataSourceName = testsacc.ResourceName("data.cloudavenue_vdc_network_isolated")
+)
+
+type VDCNetworkIsolatedDataSource struct{}
+
+func NewVDCNetworkIsolatedDataSourceTest() testsacc.TestACC {
+ return &VDCNetworkIsolatedDataSource{}
+}
+
+// GetResourceName returns the name of the resource.
+func (r *VDCNetworkIsolatedDataSource) GetResourceName() string {
+ return VDCNetworkIsolatedDataSourceName.String()
+}
+
+func (r *VDCNetworkIsolatedDataSource) DependenciesConfig() (resp testsacc.DependenciesConfigResponse) {
+ resp.Append(GetResourceConfig()[VDCNetworkIsolatedResourceName]().GetDefaultConfig)
+ return
+}
+
+func (r *VDCNetworkIsolatedDataSource) Tests(ctx context.Context) map[testsacc.TestName]func(ctx context.Context, resourceName string) testsacc.Test {
+ return map[testsacc.TestName]func(ctx context.Context, resourceName string) testsacc.Test{
+ "example": func(_ context.Context, _ string) testsacc.Test {
+ return testsacc.Test{
+ // ! Create testing
+ Create: testsacc.TFConfig{
+ TFConfig: `
+ data "cloudavenue_vdc_network_isolated" "example" {
+ vdc = cloudavenue_vdc.example.name
+ name = cloudavenue_vdc_network_isolated.example.name
+ }`,
+ Checks: GetResourceConfig()[VDCNetworkIsolatedResourceName]().GetDefaultChecks(),
+ },
+ }
+ },
+ }
+}
+
+func TestAccVDCNetworkIsolatedDataSource(t *testing.T) {
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { TestAccPreCheck(t) },
+ ProtoV6ProviderFactories: TestAccProtoV6ProviderFactories,
+ Steps: testsacc.GenerateTests(&VDCNetworkIsolatedDataSource{}),
+ })
+}
diff --git a/internal/testsacc/vdc_network_isolated_resource_test.go b/internal/testsacc/vdc_network_isolated_resource_test.go
new file mode 100644
index 00000000..ccc5ef6e
--- /dev/null
+++ b/internal/testsacc/vdc_network_isolated_resource_test.go
@@ -0,0 +1,303 @@
+package testsacc
+
+import (
+ "context"
+ "testing"
+
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
+
+ "github.com/orange-cloudavenue/cloudavenue-sdk-go/pkg/urn"
+ "github.com/orange-cloudavenue/terraform-provider-cloudavenue/internal/helpers/testsacc"
+)
+
+var _ testsacc.TestACC = &VDCNetworkIsolatedResource{}
+
+const (
+ VDCNetworkIsolatedResourceName = testsacc.ResourceName("cloudavenue_vdc_network_isolated")
+)
+
+type VDCNetworkIsolatedResource struct{}
+
+func NewVDCNetworkIsolatedResourceTest() testsacc.TestACC {
+ return &VDCNetworkIsolatedResource{}
+}
+
+// GetResourceName returns the name of the resource.
+func (r *VDCNetworkIsolatedResource) GetResourceName() string {
+ return VDCNetworkIsolatedResourceName.String()
+}
+
+func (r *VDCNetworkIsolatedResource) DependenciesConfig() (resp testsacc.DependenciesConfigResponse) {
+ resp.Append(GetResourceConfig()[VDCResourceName]().GetDefaultConfig)
+ return
+}
+
+func (r *VDCNetworkIsolatedResource) Tests(ctx context.Context) map[testsacc.TestName]func(ctx context.Context, resourceName string) testsacc.Test {
+ return map[testsacc.TestName]func(ctx context.Context, resourceName string) testsacc.Test{
+ "example": func(_ context.Context, resourceName string) testsacc.Test {
+ return testsacc.Test{
+ CommonChecks: []resource.TestCheckFunc{
+ resource.TestCheckResourceAttrWith(resourceName, "id", urn.TestIsType(urn.Network)),
+ resource.TestCheckResourceAttrSet(resourceName, "vdc"),
+ },
+ // ! Create testing
+ Create: testsacc.TFConfig{
+ TFConfig: testsacc.GenerateFromTemplate(resourceName, `
+ resource "cloudavenue_vdc_network_isolated" "example" {
+ name = {{ generate . "name" }}
+ description = {{ generate . "description" }}
+ vdc = cloudavenue_vdc.example.name
+
+ gateway = "192.168.0.1"
+ prefix_length = 24
+
+ dns1 = "1.1.1.1"
+ dns2 = "1.0.0.1"
+ dns_suffix = "example.com"
+
+ static_ip_pool = [
+ {
+ start_address = "192.168.0.10"
+ end_address = "192.168.0.20"
+ },
+ {
+ start_address = "192.168.0.100"
+ end_address = "192.168.0.130"
+ }
+ ]
+ }`),
+ Checks: []resource.TestCheckFunc{
+ resource.TestCheckResourceAttr(resourceName, "name", testsacc.GetValueFromTemplate(resourceName, "name")),
+ resource.TestCheckResourceAttr(resourceName, "description", testsacc.GetValueFromTemplate(resourceName, "description")),
+ resource.TestCheckResourceAttr(resourceName, "gateway", "192.168.0.1"),
+ resource.TestCheckResourceAttr(resourceName, "prefix_length", "24"),
+ resource.TestCheckResourceAttr(resourceName, "dns1", "1.1.1.1"),
+ resource.TestCheckResourceAttr(resourceName, "dns2", "1.0.0.1"),
+ resource.TestCheckResourceAttr(resourceName, "dns_suffix", "example.com"),
+ resource.TestCheckResourceAttr(resourceName, "static_ip_pool.#", "2"),
+ resource.TestCheckResourceAttr(resourceName, "guest_vlan_allowed", "false"), // Default value
+ resource.TestCheckTypeSetElemNestedAttrs(resourceName, "static_ip_pool.*", map[string]string{
+ "start_address": "192.168.0.10",
+ "end_address": "192.168.0.20",
+ }),
+ resource.TestCheckTypeSetElemNestedAttrs(resourceName, "static_ip_pool.*", map[string]string{
+ "start_address": "192.168.0.100",
+ "end_address": "192.168.0.130",
+ }),
+ },
+ },
+ // ! Updates testing
+ // * Update name
+ Updates: []testsacc.TFConfig{
+ {
+ TFConfig: testsacc.GenerateFromTemplate(resourceName, `
+ resource "cloudavenue_vdc_network_isolated" "example" {
+ name = {{ generate . "name" }}
+ description = {{ get . "description" }}
+ vdc = cloudavenue_vdc.example.name
+
+ gateway = "192.168.0.1"
+ prefix_length = 24
+
+ dns1 = "1.1.1.1"
+ dns2 = "1.0.0.1"
+ dns_suffix = "example.com"
+
+ static_ip_pool = [
+ {
+ start_address = "192.168.0.10"
+ end_address = "192.168.0.20"
+ },
+ {
+ start_address = "192.168.0.100"
+ end_address = "192.168.0.130"
+ }
+ ]
+ }`),
+ Checks: []resource.TestCheckFunc{
+ resource.TestCheckResourceAttr(resourceName, "name", testsacc.GetValueFromTemplate(resourceName, "name")),
+ resource.TestCheckResourceAttr(resourceName, "description", testsacc.GetValueFromTemplate(resourceName, "description")),
+ resource.TestCheckResourceAttr(resourceName, "gateway", "192.168.0.1"),
+ resource.TestCheckResourceAttr(resourceName, "prefix_length", "24"),
+ resource.TestCheckResourceAttr(resourceName, "dns1", "1.1.1.1"),
+ resource.TestCheckResourceAttr(resourceName, "dns2", "1.0.0.1"),
+ resource.TestCheckResourceAttr(resourceName, "dns_suffix", "example.com"),
+ resource.TestCheckResourceAttr(resourceName, "static_ip_pool.#", "2"),
+ resource.TestCheckResourceAttr(resourceName, "guest_vlan_allowed", "false"), // Default value
+ resource.TestCheckTypeSetElemNestedAttrs(resourceName, "static_ip_pool.*", map[string]string{
+ "start_address": "192.168.0.10",
+ "end_address": "192.168.0.20",
+ }),
+ resource.TestCheckTypeSetElemNestedAttrs(resourceName, "static_ip_pool.*", map[string]string{
+ "start_address": "192.168.0.100",
+ "end_address": "192.168.0.130",
+ }),
+ },
+ },
+ // * Update description
+ {
+ TFConfig: testsacc.GenerateFromTemplate(resourceName, `
+ resource "cloudavenue_vdc_network_isolated" "example" {
+ name = {{ get . "name" }}
+ description = {{ generate . "description" }}
+ vdc = cloudavenue_vdc.example.name
+
+ gateway = "192.168.0.1"
+ prefix_length = 24
+
+ dns1 = "1.1.1.1"
+ dns2 = "1.0.0.1"
+ dns_suffix = "example.com"
+
+ static_ip_pool = [
+ {
+ start_address = "192.168.0.10"
+ end_address = "192.168.0.20"
+ },
+ {
+ start_address = "192.168.0.100"
+ end_address = "192.168.0.130"
+ }
+ ]
+ }`),
+ Checks: []resource.TestCheckFunc{
+ resource.TestCheckResourceAttr(resourceName, "name", testsacc.GetValueFromTemplate(resourceName, "name")),
+ resource.TestCheckResourceAttr(resourceName, "description", testsacc.GetValueFromTemplate(resourceName, "description")),
+ resource.TestCheckResourceAttr(resourceName, "gateway", "192.168.0.1"),
+ resource.TestCheckResourceAttr(resourceName, "prefix_length", "24"),
+ resource.TestCheckResourceAttr(resourceName, "dns1", "1.1.1.1"),
+ resource.TestCheckResourceAttr(resourceName, "dns2", "1.0.0.1"),
+ resource.TestCheckResourceAttr(resourceName, "dns_suffix", "example.com"),
+ resource.TestCheckResourceAttr(resourceName, "static_ip_pool.#", "2"),
+ resource.TestCheckResourceAttr(resourceName, "guest_vlan_allowed", "false"), // Default value
+ resource.TestCheckTypeSetElemNestedAttrs(resourceName, "static_ip_pool.*", map[string]string{
+ "start_address": "192.168.0.10",
+ "end_address": "192.168.0.20",
+ }),
+ resource.TestCheckTypeSetElemNestedAttrs(resourceName, "static_ip_pool.*", map[string]string{
+ "start_address": "192.168.0.100",
+ "end_address": "192.168.0.130",
+ }),
+ },
+ },
+ // * Update DNS
+ {
+ TFConfig: testsacc.GenerateFromTemplate(resourceName, `
+ resource "cloudavenue_vdc_network_isolated" "example" {
+ name = {{ get . "name" }}
+ description = {{ generate . "description" }}
+ vdc = cloudavenue_vdc.example.name
+
+ gateway = "192.168.0.1"
+ prefix_length = 24
+
+ dns1 = "208.67.222.222"
+ dns2 = "208.67.220.220"
+ dns_suffix = "example.local"
+
+ static_ip_pool = [
+ {
+ start_address = "192.168.0.10"
+ end_address = "192.168.0.20"
+ },
+ {
+ start_address = "192.168.0.100"
+ end_address = "192.168.0.130"
+ }
+ ]
+ }`),
+ Checks: []resource.TestCheckFunc{
+ resource.TestCheckResourceAttr(resourceName, "name", testsacc.GetValueFromTemplate(resourceName, "name")),
+ resource.TestCheckResourceAttr(resourceName, "description", testsacc.GetValueFromTemplate(resourceName, "description")),
+ resource.TestCheckResourceAttr(resourceName, "gateway", "192.168.0.1"),
+ resource.TestCheckResourceAttr(resourceName, "prefix_length", "24"),
+ resource.TestCheckResourceAttr(resourceName, "dns1", "208.67.222.222"),
+ resource.TestCheckResourceAttr(resourceName, "dns2", "208.67.220.220"),
+ resource.TestCheckResourceAttr(resourceName, "dns_suffix", "example.local"),
+ resource.TestCheckResourceAttr(resourceName, "static_ip_pool.#", "2"),
+ resource.TestCheckResourceAttr(resourceName, "guest_vlan_allowed", "false"), // Default value
+ resource.TestCheckTypeSetElemNestedAttrs(resourceName, "static_ip_pool.*", map[string]string{
+ "start_address": "192.168.0.10",
+ "end_address": "192.168.0.20",
+ }),
+ resource.TestCheckTypeSetElemNestedAttrs(resourceName, "static_ip_pool.*", map[string]string{
+ "start_address": "192.168.0.100",
+ "end_address": "192.168.0.130",
+ }),
+ },
+ },
+ // * Update Static IP Pool
+ {
+ TFConfig: testsacc.GenerateFromTemplate(resourceName, `
+ resource "cloudavenue_vdc_network_isolated" "example" {
+ name = {{ get . "name" }}
+ description = {{ generate . "description" }}
+ vdc = cloudavenue_vdc.example.name
+
+ gateway = "192.168.0.1"
+ prefix_length = 24
+
+ dns1 = "208.67.222.222"
+ dns2 = "208.67.220.220"
+ dns_suffix = "example.local"
+
+ static_ip_pool = [
+ {
+ start_address = "192.168.0.40"
+ end_address = "192.168.0.60"
+ },
+ {
+ start_address = "192.168.0.100"
+ end_address = "192.168.0.130"
+ },
+ {
+ start_address = "192.168.0.200"
+ end_address = "192.168.0.220"
+ }
+ ]
+ }`),
+ Checks: []resource.TestCheckFunc{
+ resource.TestCheckResourceAttr(resourceName, "name", testsacc.GetValueFromTemplate(resourceName, "name")),
+ resource.TestCheckResourceAttr(resourceName, "description", testsacc.GetValueFromTemplate(resourceName, "description")),
+ resource.TestCheckResourceAttr(resourceName, "gateway", "192.168.0.1"),
+ resource.TestCheckResourceAttr(resourceName, "prefix_length", "24"),
+ resource.TestCheckResourceAttr(resourceName, "dns1", "208.67.222.222"),
+ resource.TestCheckResourceAttr(resourceName, "dns2", "208.67.220.220"),
+ resource.TestCheckResourceAttr(resourceName, "dns_suffix", "example.local"),
+ resource.TestCheckResourceAttr(resourceName, "static_ip_pool.#", "3"),
+ resource.TestCheckResourceAttr(resourceName, "guest_vlan_allowed", "false"), // Default value
+ resource.TestCheckTypeSetElemNestedAttrs(resourceName, "static_ip_pool.*", map[string]string{
+ "start_address": "192.168.0.40",
+ "end_address": "192.168.0.60",
+ }),
+ resource.TestCheckTypeSetElemNestedAttrs(resourceName, "static_ip_pool.*", map[string]string{
+ "start_address": "192.168.0.100",
+ "end_address": "192.168.0.130",
+ }),
+ resource.TestCheckTypeSetElemNestedAttrs(resourceName, "static_ip_pool.*", map[string]string{
+ "start_address": "192.168.0.200",
+ "end_address": "192.168.0.220",
+ }),
+ },
+ },
+ },
+ // ! Imports testing
+ Imports: []testsacc.TFImport{
+ {
+ ImportStateIDBuilder: []string{"vdc", "name"},
+ ImportState: true,
+ ImportStateVerify: true,
+ },
+ },
+ }
+ },
+ }
+}
+
+func TestAccVDCNetworkIsolatedResource(t *testing.T) {
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { TestAccPreCheck(t) },
+ ProtoV6ProviderFactories: TestAccProtoV6ProviderFactories,
+ Steps: testsacc.GenerateTests(&VDCNetworkIsolatedResource{}),
+ })
+}
diff --git a/templates/data-sources/vdc_network_isolated.md.tmpl b/templates/data-sources/vdc_network_isolated.md.tmpl
new file mode 100644
index 00000000..7e1b24ac
--- /dev/null
+++ b/templates/data-sources/vdc_network_isolated.md.tmpl
@@ -0,0 +1,25 @@
+---
+page_title: "{{.Name}} {{.Type}} - {{.ProviderName}}"
+subcategory: "vDC (Virtual Datacenter)"
+description: |-
+{{ .Description | plainmarkdown | trimspace | prefixlines " " }}
+---
+
+# {{.Name}} ({{.Type}})
+
+{{ .Description | trimspace }}
+
+{{ if .HasExample -}}
+## Example Usage
+
+{{ tffile .ExampleFile }}
+{{- end }}
+
+{{ .SchemaMarkdown | trimspace }}
+
+{{ if .HasImport -}}
+## Import
+
+Import is supported using the following syntax:
+{{ codefile "shell" .ImportFile }}
+{{- end }}
\ No newline at end of file
diff --git a/templates/resources/vdc_network_isolated.md.tmpl b/templates/resources/vdc_network_isolated.md.tmpl
new file mode 100644
index 00000000..37c8353f
--- /dev/null
+++ b/templates/resources/vdc_network_isolated.md.tmpl
@@ -0,0 +1,55 @@
+---
+page_title: "{{.Name}} {{.Type}} - {{.ProviderName}}"
+subcategory: "vDC (Virtual Datacenter)"
+description: |-
+{{ .Description | plainmarkdown | trimspace | prefixlines " " }}
+---
+
+# {{.Name}} ({{.Type}})
+
+{{ .Description | trimspace }}
+
+{{ if .HasExample -}}
+## Example Usage
+
+{{ tffile .ExampleFile }}
+{{- end }}
+
+{{ .SchemaMarkdown | trimspace }}
+
+## Advanced Usage
+
+Define `static_ip_pool` as a list of objects to create multiple IP pools.
+
+```hcl
+resource "cloudavenue_vdc_network_isolated" "example" {
+ name = "my-isolated-network"
+ vdc = cloudavenue_vdc.example.name
+
+ gateway = "192.168.0.1"
+ prefix_length = 24
+
+ dns1 = "192.168.0.2"
+ dns2 = "192.168.0.3"
+ dns_suffix = "example.local"
+
+ static_ip_pool = [
+ {
+ start_address = "192.168.0.10"
+ end_address = "192.168.0.20"
+ },
+ {
+ start_address = "192.168.0.100"
+ end_address = "192.168.0.130"
+ }
+ ]
+}
+
+```
+
+{{ if .HasImport -}}
+## Import
+
+Import is supported using the following syntax:
+{{ codefile "shell" .ImportFile }}
+{{- end }}