diff --git a/CHANGELOG.md b/CHANGELOG.md
index 721f0478..33f0cfc5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,11 @@
+## 0.1.16 (unreleased)
+
+- Add Device Unreachability Warning to `catalystcenter_fabric_l3_handoff_ip_transit` resource, [link](https://github.com/CiscoDevNet/terraform-provider-catalystcenter/issues/150)
+- Add `catalystcenter_fabric_l2_virtual_network` resource and data source
+- Remove `max_async_wait_time` attribute and use timeout from `CC_MAX_TIMEOUT`
+- Modify `catalystcenter_deploy_template` resource to support deploying composite templates
+- Modify `catalystcenter_template_version` resource to use versioned template id as `id` and remove data_source
+
## 0.1.15
- Fix issue in `catalystcenter_fabric_l3_handoff_ip_transit` resource, [link](https://github.com/CiscoDevNet/terraform-provider-catalystcenter/issues/146)
diff --git a/docs/data-sources/fabric_l2_virtual_network.md b/docs/data-sources/fabric_l2_virtual_network.md
new file mode 100644
index 00000000..d1f56629
--- /dev/null
+++ b/docs/data-sources/fabric_l2_virtual_network.md
@@ -0,0 +1,36 @@
+---
+# generated by https://github.com/hashicorp/terraform-plugin-docs
+page_title: "catalystcenter_fabric_l2_virtual_network Data Source - terraform-provider-catalystcenter"
+subcategory: "SDA"
+description: |-
+ This data source can read the Fabric L2 Virtual Network.
+---
+
+# catalystcenter_fabric_l2_virtual_network (Data Source)
+
+This data source can read the Fabric L2 Virtual Network.
+
+## Example Usage
+
+```terraform
+data "catalystcenter_fabric_l2_virtual_network" "example" {
+ fabric_id = "5e6f7b3a-2b0b-4a7d-8b1c-0d4b1cd5e1b1"
+ vlan_name = "VLAN401"
+}
+```
+
+
+## Schema
+
+### Required
+
+- `fabric_id` (String) ID of the fabric this layer 2 virtual network is to be assigned to
+- `vlan_name` (String) Name of the VLAN of the layer 2 virtual network. Must contain only alphanumeric characters, underscores, and hyphens
+
+### Read-Only
+
+- `associated_l3_virtual_network_name` (String) Name of the layer 3 virtual network associated with the layer 2 virtual network. This field is provided to support requests related to virtual network anchoring. The layer 3 virtual network must have already been added to the fabric before association. This field must either be present in all payload elements or none
+- `fabric_enabled_wireless` (Boolean) Set to true to enable wireless. Default is false
+- `id` (String) The id of the object
+- `traffic_type` (String) The type of traffic that is served
+- `vlan_id` (Number) ID of the VLAN of the layer 2 virtual network. Allowed VLAN range is 2-4093 except for reserved VLANs 1002-1005, and 2046. If deploying on a fabric zone, this vlanId must match the vlanId of the corresponding layer 2 virtual network on the fabric site
diff --git a/docs/data-sources/template_version.md b/docs/data-sources/template_version.md
deleted file mode 100644
index 1a5230ad..00000000
--- a/docs/data-sources/template_version.md
+++ /dev/null
@@ -1,31 +0,0 @@
----
-# generated by https://github.com/hashicorp/terraform-plugin-docs
-page_title: "catalystcenter_template_version Data Source - terraform-provider-catalystcenter"
-subcategory: "Templates"
-description: |-
- This data source can read the Template Version.
----
-
-# catalystcenter_template_version (Data Source)
-
-This data source can read the Template Version.
-
-## Example Usage
-
-```terraform
-data "catalystcenter_template_version" "example" {
- id = "12345678-1234-1234-1234-123456789012"
-}
-```
-
-
-## Schema
-
-### Required
-
-- `id` (String) The id of the object
-
-### Read-Only
-
-- `comments` (String) Template version comments
-- `template_id` (String) UUID of template
diff --git a/docs/guides/changelog.md b/docs/guides/changelog.md
index fc8f69ca..945044a5 100644
--- a/docs/guides/changelog.md
+++ b/docs/guides/changelog.md
@@ -7,6 +7,14 @@ description: |-
# Changelog
+## 0.1.16 (unreleased)
+
+- Add Device Unreachability Warning to `catalystcenter_fabric_l3_handoff_ip_transit` resource, [link](https://github.com/CiscoDevNet/terraform-provider-catalystcenter/issues/150)
+- Add `catalystcenter_fabric_l2_virtual_network` resource and data source
+- Remove `max_async_wait_time` attribute and use timeout from `CC_MAX_TIMEOUT`
+- Modify `catalystcenter_deploy_template` resource to support deploying composite templates
+- Modify `catalystcenter_template_version` resource to use versioned template id as `id` and remove data_source
+
## 0.1.15
- Fix issue in `catalystcenter_fabric_l3_handoff_ip_transit` resource, [link](https://github.com/CiscoDevNet/terraform-provider-catalystcenter/issues/146)
diff --git a/docs/resources/deploy_template.md b/docs/resources/deploy_template.md
index d46151e2..2149806c 100644
--- a/docs/resources/deploy_template.md
+++ b/docs/resources/deploy_template.md
@@ -53,7 +53,6 @@ Required:
- `type` (String) Target type of device
- Choices: `MANAGED_DEVICE_IP`, `MANAGED_DEVICE_UUID`, `PRE_PROVISIONED_SERIAL`, `PRE_PROVISIONED_MAC`, `DEFAULT`, `MANAGED_DEVICE_HOSTNAME`
-- `versioned_template_id` (String) Versioned template ID to be provisioned
Optional:
@@ -61,6 +60,7 @@ Optional:
- `id` (String) ID of device is required if `type` is MANAGED_DEVICE_UUID
- `params` (Map of String) Template params/values to be provisioned
- `resource_params` (Attributes List) Resource params to be provisioned (see [below for nested schema](#nestedatt--target_info--resource_params))
+- `versioned_template_id` (String) Versioned template ID to be provisioned
### Nested Schema for `target_info.resource_params`
@@ -80,13 +80,14 @@ Optional:
Required:
- `target_info` (Attributes List) Target info to deploy template (see [below for nested schema](#nestedatt--member_template_deployment_info--target_info))
-- `template_id` (String) ID of template to be provisioned
+- `template_id` (String) Versioned Template ID
Optional:
+- `copying_config` (Boolean) Copying Config
- `force_push_template` (Boolean) Force Push Template
- `is_composite` (Boolean) Composite template flag
-- `main_template_id` (String) Composite Template ID
+- `main_template_id` (String) Template ID
### Nested Schema for `member_template_deployment_info.target_info`
@@ -95,7 +96,6 @@ Required:
- `type` (String) Target type of device
- Choices: `MANAGED_DEVICE_IP`, `MANAGED_DEVICE_UUID`, `PRE_PROVISIONED_SERIAL`, `PRE_PROVISIONED_MAC`, `DEFAULT`, `MANAGED_DEVICE_HOSTNAME`
-- `versioned_template_id` (String) Versioned template ID to be provisioned
Optional:
@@ -103,6 +103,7 @@ Optional:
- `id` (String) ID of device is required if targetType is MANAGED_DEVICE_UUID
- `params` (Map of String) Template params/values to be provisioned
- `resource_params` (Attributes List) Resource params to be provisioned (see [below for nested schema](#nestedatt--member_template_deployment_info--target_info--resource_params))
+- `versioned_template_id` (String) Versioned template ID to be provisioned
### Nested Schema for `member_template_deployment_info.target_info.resource_params`
diff --git a/docs/resources/fabric_l2_virtual_network.md b/docs/resources/fabric_l2_virtual_network.md
new file mode 100644
index 00000000..f6857a32
--- /dev/null
+++ b/docs/resources/fabric_l2_virtual_network.md
@@ -0,0 +1,51 @@
+---
+# generated by https://github.com/hashicorp/terraform-plugin-docs
+page_title: "catalystcenter_fabric_l2_virtual_network Resource - terraform-provider-catalystcenter"
+subcategory: "SDA"
+description: |-
+ This resource can manage a Fabric L2 Virtual Network.
+---
+
+# catalystcenter_fabric_l2_virtual_network (Resource)
+
+This resource can manage a Fabric L2 Virtual Network.
+
+## Example Usage
+
+```terraform
+resource "catalystcenter_fabric_l2_virtual_network" "example" {
+ fabric_id = "5e6f7b3a-2b0b-4a7d-8b1c-0d4b1cd5e1b1"
+ vlan_name = "VLAN401"
+ vlan_id = 401
+ traffic_type = "DATA"
+ fabric_enabled_wireless = false
+}
+```
+
+
+## Schema
+
+### Required
+
+- `fabric_id` (String) ID of the fabric this layer 2 virtual network is to be assigned to
+- `traffic_type` (String) The type of traffic that is served
+ - Choices: `DATA`, `VOICE`
+- `vlan_name` (String) Name of the VLAN of the layer 2 virtual network. Must contain only alphanumeric characters, underscores, and hyphens
+
+### Optional
+
+- `associated_l3_virtual_network_name` (String) Name of the layer 3 virtual network associated with the layer 2 virtual network. This field is provided to support requests related to virtual network anchoring. The layer 3 virtual network must have already been added to the fabric before association. This field must either be present in all payload elements or none
+- `fabric_enabled_wireless` (Boolean) Set to true to enable wireless. Default is false
+- `vlan_id` (Number) ID of the VLAN of the layer 2 virtual network. Allowed VLAN range is 2-4093 except for reserved VLANs 1002-1005, and 2046. If deploying on a fabric zone, this vlanId must match the vlanId of the corresponding layer 2 virtual network on the fabric site
+
+### Read-Only
+
+- `id` (String) The id of the object
+
+## Import
+
+Import is supported using the following syntax:
+
+```shell
+terraform import catalystcenter_fabric_l2_virtual_network.example ","
+```
diff --git a/docs/resources/template_version.md b/docs/resources/template_version.md
index 686e16ae..e9df82f3 100644
--- a/docs/resources/template_version.md
+++ b/docs/resources/template_version.md
@@ -22,13 +22,10 @@ resource "catalystcenter_template_version" "example" {
## Schema
-### Required
-
-- `template_id` (String) UUID of template
-
### Optional
- `comments` (String) Template version comments
+- `template_id` (String) UUID of template
### Read-Only
diff --git a/examples/data-sources/catalystcenter_fabric_l2_virtual_network/data-source.tf b/examples/data-sources/catalystcenter_fabric_l2_virtual_network/data-source.tf
new file mode 100644
index 00000000..30dd1670
--- /dev/null
+++ b/examples/data-sources/catalystcenter_fabric_l2_virtual_network/data-source.tf
@@ -0,0 +1,4 @@
+data "catalystcenter_fabric_l2_virtual_network" "example" {
+ fabric_id = "5e6f7b3a-2b0b-4a7d-8b1c-0d4b1cd5e1b1"
+ vlan_name = "VLAN401"
+}
diff --git a/examples/data-sources/catalystcenter_template_version/data-source.tf b/examples/data-sources/catalystcenter_template_version/data-source.tf
deleted file mode 100644
index 70e2ee74..00000000
--- a/examples/data-sources/catalystcenter_template_version/data-source.tf
+++ /dev/null
@@ -1,3 +0,0 @@
-data "catalystcenter_template_version" "example" {
- id = "12345678-1234-1234-1234-123456789012"
-}
diff --git a/examples/resources/catalystcenter_fabric_l2_virtual_network/import.sh b/examples/resources/catalystcenter_fabric_l2_virtual_network/import.sh
new file mode 100644
index 00000000..8968cc6f
--- /dev/null
+++ b/examples/resources/catalystcenter_fabric_l2_virtual_network/import.sh
@@ -0,0 +1 @@
+terraform import catalystcenter_fabric_l2_virtual_network.example ","
diff --git a/examples/resources/catalystcenter_fabric_l2_virtual_network/resource.tf b/examples/resources/catalystcenter_fabric_l2_virtual_network/resource.tf
new file mode 100644
index 00000000..c11323aa
--- /dev/null
+++ b/examples/resources/catalystcenter_fabric_l2_virtual_network/resource.tf
@@ -0,0 +1,7 @@
+resource "catalystcenter_fabric_l2_virtual_network" "example" {
+ fabric_id = "5e6f7b3a-2b0b-4a7d-8b1c-0d4b1cd5e1b1"
+ vlan_name = "VLAN401"
+ vlan_id = 401
+ traffic_type = "DATA"
+ fabric_enabled_wireless = false
+}
diff --git a/gen/definitions/anycast_gateway.yaml b/gen/definitions/anycast_gateway.yaml
index f0a08cd8..c5a4bf15 100644
--- a/gen/definitions/anycast_gateway.yaml
+++ b/gen/definitions/anycast_gateway.yaml
@@ -9,7 +9,6 @@ data_source_no_id: true
skip_minimum_test: true
put_id_include_path: "0.id"
put_no_id: true
-max_async_wait_time: 120
doc_category: SDA
attributes:
- model_name: fabricId
@@ -147,7 +146,6 @@ test_prerequisites: |
resource "catalystcenter_area" "test" {
name = "Area1"
parent_name = "Global"
- depends_on = [catalystcenter_ip_pool.test]
}
resource "catalystcenter_ip_pool" "test" {
name = "MyPool1"
@@ -167,7 +165,6 @@ test_prerequisites: |
site_id = catalystcenter_area.test.id
pub_sub_enabled = false
authentication_profile_name = "No Authentication"
- depends_on = [catalystcenter_area.test]
}
resource "catalystcenter_fabric_virtual_network" "test" {
virtual_network_name = "SDA_VN1"
@@ -175,7 +172,7 @@ test_prerequisites: |
sg_names = ["Employees"]
}
resource "catalystcenter_virtual_network_to_fabric_site" "test" {
- virtual_network_name = "SDA_VN1"
+ virtual_network_name = catalystcenter_fabric_virtual_network.test.id
site_name_hierarchy = "Global/Area1"
- depends_on = [catalystcenter_fabric_virtual_network.test, catalystcenter_fabric_site.test]
+ depends_on = [catalystcenter_fabric_site.test]
}
\ No newline at end of file
diff --git a/gen/definitions/deploy_template.yaml b/gen/definitions/deploy_template.yaml
index 7d702968..7c7f587e 100644
--- a/gen/definitions/deploy_template.yaml
+++ b/gen/definitions/deploy_template.yaml
@@ -36,16 +36,19 @@ attributes:
- model_name: templateId
type: String
id: true
- description: ID of template to be provisioned
+ description: Versioned Template ID
- model_name: forcePushTemplate
type: Bool
description: Force Push Template
- model_name: isComposite
type: Bool
description: Composite template flag
+ - model_name: copyingConfig
+ type: Bool
+ description: Copying Config
- model_name: mainTemplateId
type: String
- description: Composite Template ID
+ description: Template ID
- model_name: targetInfo
type: List
mandatory: true
@@ -93,7 +96,6 @@ attributes:
description: Target type of device
- model_name: versionedTemplateId
type: String
- mandatory: true
description: Versioned template ID to be provisioned
- model_name: targetInfo
type: List
@@ -147,7 +149,6 @@ attributes:
example: MANAGED_DEVICE_HOSTNAME
- model_name: versionedTemplateId
type: String
- mandatory: true
description: Versioned template ID to be provisioned
example: 12345678-1234-1234-1234-123456789012
test_value: catalystcenter_template_version.example.id
diff --git a/gen/definitions/discovery.yaml b/gen/definitions/discovery.yaml
index 8921e9da..cca9491d 100644
--- a/gen/definitions/discovery.yaml
+++ b/gen/definitions/discovery.yaml
@@ -19,7 +19,6 @@ no_update: true
no_import: true
get_from_all: true
id_from_query_path: response
-max_async_wait_time: 600
doc_category: Discovery
attributes:
- model_name: cdpLevel
diff --git a/gen/definitions/fabric_device.yaml b/gen/definitions/fabric_device.yaml
index f65cadc3..6d1ca9f1 100644
--- a/gen/definitions/fabric_device.yaml
+++ b/gen/definitions/fabric_device.yaml
@@ -8,7 +8,6 @@ put_id_include_path: 0.id
import_no_id: true
data_source_no_id: true
put_no_id: true
-max_async_wait_time: 300
doc_category: SDA
test_tags: [SDA]
attributes:
diff --git a/gen/definitions/fabric_l2_virtual_network.yaml b/gen/definitions/fabric_l2_virtual_network.yaml
new file mode 100644
index 00000000..ed94bd81
--- /dev/null
+++ b/gen/definitions/fabric_l2_virtual_network.yaml
@@ -0,0 +1,72 @@
+---
+name: Fabric L2 Virtual Network
+rest_endpoint: /dna/intent/api/v1/sda/layer2VirtualNetworks
+id_from_query_path: response.0
+id_from_query_path_attribute: id
+import_no_id: true
+data_source_no_id: true
+skip_minimum_test: true
+put_id_include_path: "0.id"
+put_no_id: true
+doc_category: SDA
+attributes:
+ - model_name: fabricId
+ requires_replace: true
+ data_path: '0'
+ query_param: true
+ response_data_path: response.0.fabricId
+ mandatory: true
+ description: ID of the fabric this layer 2 virtual network is to be assigned to
+ type: String
+ example: 5e6f7b3a-2b0b-4a7d-8b1c-0d4b1cd5e1b1
+ test_value: catalystcenter_fabric_site.test.id
+ - model_name: vlanName
+ requires_replace: true
+ data_path: '0'
+ query_param: true
+ response_data_path: response.0.vlanName
+ type: String
+ mandatory: true
+ description: Name of the VLAN of the layer 2 virtual network. Must contain only alphanumeric characters, underscores, and hyphens
+ example: VLAN401
+ - model_name: vlanId
+ requires_replace: true
+ data_path: '0'
+ response_data_path: response.0.vlanId
+ type: Int64
+ description: ID of the VLAN of the layer 2 virtual network. Allowed VLAN range is 2-4093 except for reserved VLANs 1002-1005, and 2046. If deploying on a fabric zone, this vlanId must match the vlanId of the corresponding layer 2 virtual network on the fabric site
+ example: 401
+ - model_name: trafficType
+ data_path: '0'
+ response_data_path: response.0.trafficType
+ type: String
+ enum_values: [DATA, VOICE]
+ mandatory: true
+ description: The type of traffic that is served
+ example: DATA
+ - model_name: isFabricEnabledWireless
+ data_path: '0'
+ response_data_path: response.0.isFabricEnabledWireless
+ tf_name: fabric_enabled_wireless
+ type: Bool
+ description: Set to true to enable wireless. Default is false
+ example: false
+ - model_name: associatedLayer3VirtualNetworkName
+ requires_replace: true
+ data_path: '0'
+ response_data_path: response.0.associatedLayer3VirtualNetworkName
+ tf_name: associated_l3_virtual_network_name
+ type: String
+ description: Name of the layer 3 virtual network associated with the layer 2 virtual network. This field is provided to support requests related to virtual network anchoring. The layer 3 virtual network must have already been added to the fabric before association. This field must either be present in all payload elements or none
+ example: SDA_VN1
+ exclude_test: true
+test_prerequisites: |
+ resource "catalystcenter_area" "test" {
+ name = "Area1"
+ parent_name = "Global"
+ }
+ resource "catalystcenter_fabric_site" "test" {
+ site_id = catalystcenter_area.test.id
+ pub_sub_enabled = false
+ authentication_profile_name = "No Authentication"
+ }
diff --git a/gen/definitions/fabric_provision_device.yaml b/gen/definitions/fabric_provision_device.yaml
index bd5d5edd..a5065a1a 100644
--- a/gen/definitions/fabric_provision_device.yaml
+++ b/gen/definitions/fabric_provision_device.yaml
@@ -7,7 +7,6 @@ import_no_id: true
data_source_no_id: true
put_id_include_path: "0.id"
put_no_id: true
-max_async_wait_time: 300
doc_category: SDA
test_tags: [SDA]
attributes:
diff --git a/gen/definitions/template_version.yaml b/gen/definitions/template_version.yaml
index 89c08cfb..6681fe7f 100644
--- a/gen/definitions/template_version.yaml
+++ b/gen/definitions/template_version.yaml
@@ -1,13 +1,16 @@
---
name: Template Version
+# Manual modifications in Create and Read functions to read Template Version Id
rest_endpoint: /dna/intent/api/v1/template-programmer/template/version
no_delete: true
+no_data_source: true
id_from_attribute: true
doc_category: Templates
attributes:
- model_name: templateId
type: String
- id: true
+ query_param: true
+ data_source_query: true
response_data_path: 0.templateId
description: UUID of template
example: 12345678-1234-1234-1234-123456789012
diff --git a/gen/definitions/wireless_device_provision.yaml b/gen/definitions/wireless_device_provision.yaml
index 89f01ca3..35246ede 100644
--- a/gen/definitions/wireless_device_provision.yaml
+++ b/gen/definitions/wireless_device_provision.yaml
@@ -10,7 +10,6 @@ no_import: true
put_no_id: true
id_from_attribute: true
doc_category: Wireless
-max_async_wait_time: 300
test_tags: [WIRELESS]
attributes:
- model_name: deviceName
diff --git a/gen/generator.go b/gen/generator.go
index 891522f8..761bc40e 100644
--- a/gen/generator.go
+++ b/gen/generator.go
@@ -164,6 +164,7 @@ type YamlConfigAttribute struct {
DataSourceQuery bool `yaml:"data_source_query"`
QueryParamNoBody bool `yaml:"query_param_no_body"`
Mandatory bool `yaml:"mandatory"`
+ Computed bool `yaml:"computed"`
WriteOnly bool `yaml:"write_only"`
ExcludeFromPut bool `yaml:"exclude_from_put"`
ExcludeTest bool `yaml:"exclude_test"`
@@ -498,10 +499,18 @@ func GenerateQueryParamString(method string, inputSource string, attributes []Ya
// Construct the query parameter string if includeParam is true
if includeParam {
if first {
- params = append(params, `"?`+queryParamName+`=" + url.QueryEscape(`+inputSource+`.`+ToGoName(attr.TfName)+`.Value`+attr.Type+`())`)
+ if attr.Type == "Int64" {
+ params = append(params, `"?`+queryParamName+`=" + url.QueryEscape(strconv.FormatInt(`+inputSource+`.`+ToGoName(attr.TfName)+`.Value`+attr.Type+`(), 10))`)
+ } else {
+ params = append(params, `"?`+queryParamName+`=" + url.QueryEscape(`+inputSource+`.`+ToGoName(attr.TfName)+`.Value`+attr.Type+`())`)
+ }
first = false
} else {
- params = append(params, `"&`+queryParamName+`=" + url.QueryEscape(`+inputSource+`.`+ToGoName(attr.TfName)+`.Value`+attr.Type+`())`)
+ if attr.Type == "Int64" {
+ params = append(params, `"&`+queryParamName+`=" + url.QueryEscape(strconv.FormatInt(`+inputSource+`.`+ToGoName(attr.TfName)+`.Value`+attr.Type+`(), 10))`)
+ } else {
+ params = append(params, `"&`+queryParamName+`=" + url.QueryEscape(`+inputSource+`.`+ToGoName(attr.TfName)+`.Value`+attr.Type+`())`)
+ }
}
}
}
diff --git a/gen/schema/schema.yaml b/gen/schema/schema.yaml
index 43e167f6..f84433b0 100644
--- a/gen/schema/schema.yaml
+++ b/gen/schema/schema.yaml
@@ -67,6 +67,7 @@ attribute:
query_param_no_body: bool(required=False) # Set to true if the attribute is a query parameter and not part of the body
data_source_query: bool(required=False) # Set to true if the attribute is an alternative query parameter for the data source
mandatory: bool(required=False) # Set to true if the attribute is mandatory
+ computed: bool(required=False) # Set to true if the attribute is computed
write_only: bool(required=False) # Set to true if the attribute is write-only, meaning we cannot read the value
exclude_from_put: bool(required=False) # Set to true if the attribute should be excluded from the PUT request
exclude_test: bool(required=False) # Exclude attribute from example (documentation) and acceptance test
diff --git a/gen/templates/resource.go b/gen/templates/resource.go
index 9eedc51b..980b4aec 100644
--- a/gen/templates/resource.go
+++ b/gen/templates/resource.go
@@ -106,7 +106,7 @@ func (r *{{camelCase .Name}}Resource) Schema(ctx context.Context, req resource.S
{{- else}}
Optional: true,
{{- end}}
- {{- if len .DefaultValue}}
+ {{- if or (len .DefaultValue) .Computed}}
Computed: true,
{{- end}}
{{- if len .EnumValues}}
@@ -143,6 +143,11 @@ func (r *{{camelCase .Name}}Resource) Schema(ctx context.Context, req resource.S
{{if eq .Type "StringList"}}list{{else}}{{snakeCase .Type}}{{end}}planmodifier.RequiresReplace(),
},
{{- end}}
+ {{- if .Computed}}
+ PlanModifiers: []planmodifier.{{.Type}}{
+ {{snakeCase .Type}}planmodifier.UseStateForUnknown(),
+ },
+ {{- end}}
{{- if isNestedListSet .}}
NestedObject: schema.NestedAttributeObject{
Attributes: map[string]schema.Attribute{
@@ -173,7 +178,7 @@ func (r *{{camelCase .Name}}Resource) Schema(ctx context.Context, req resource.S
{{- else}}
Optional: true,
{{- end}}
- {{- if len .DefaultValue}}
+ {{- if or (len .DefaultValue) .Computed}}
Computed: true,
{{- end}}
{{- if len .EnumValues}}
@@ -210,6 +215,11 @@ func (r *{{camelCase .Name}}Resource) Schema(ctx context.Context, req resource.S
{{if eq .Type "StringList"}}list{{else}}{{snakeCase .Type}}{{end}}planmodifier.RequiresReplace(),
},
{{- end}}
+ {{- if .Computed}}
+ PlanModifiers: []planmodifier.{{.Type}}{
+ {{snakeCase .Type}}planmodifier.UseStateForUnknown(),
+ },
+ {{- end}}
{{- if isNestedListSet .}}
NestedObject: schema.NestedAttributeObject{
Attributes: map[string]schema.Attribute{
@@ -240,7 +250,7 @@ func (r *{{camelCase .Name}}Resource) Schema(ctx context.Context, req resource.S
{{- else}}
Optional: true,
{{- end}}
- {{- if len .DefaultValue}}
+ {{- if or (len .DefaultValue) .Computed}}
Computed: true,
{{- end}}
{{- if len .EnumValues}}
@@ -277,6 +287,11 @@ func (r *{{camelCase .Name}}Resource) Schema(ctx context.Context, req resource.S
{{if eq .Type "StringList"}}list{{else}}{{snakeCase .Type}}{{end}}planmodifier.RequiresReplace(),
},
{{- end}}
+ {{- if .Computed}}
+ PlanModifiers: []planmodifier.{{.Type}}{
+ {{snakeCase .Type}}planmodifier.UseStateForUnknown(),
+ },
+ {{- end}}
{{- if isNestedListSet .}}
NestedObject: schema.NestedAttributeObject{
Attributes: map[string]schema.Attribute{
@@ -307,7 +322,7 @@ func (r *{{camelCase .Name}}Resource) Schema(ctx context.Context, req resource.S
{{- else}}
Optional: true,
{{- end}}
- {{- if len .DefaultValue}}
+ {{- if or (len .DefaultValue) .Computed}}
Computed: true,
{{- end}}
{{- if len .EnumValues}}
@@ -344,6 +359,11 @@ func (r *{{camelCase .Name}}Resource) Schema(ctx context.Context, req resource.S
{{if eq .Type "StringList"}}list{{else}}{{snakeCase .Type}}{{end}}planmodifier.RequiresReplace(),
},
{{- end}}
+ {{- if .Computed}}
+ PlanModifiers: []planmodifier.{{.Type}}{
+ {{snakeCase .Type}}planmodifier.UseStateForUnknown(),
+ },
+ {{- end}}
},
{{- end}}
{{- end}}
diff --git a/internal/provider/data_source_catalystcenter_anycast_gateway_test.go b/internal/provider/data_source_catalystcenter_anycast_gateway_test.go
index 77121dd9..ac494023 100644
--- a/internal/provider/data_source_catalystcenter_anycast_gateway_test.go
+++ b/internal/provider/data_source_catalystcenter_anycast_gateway_test.go
@@ -58,7 +58,6 @@ const testAccDataSourceCcAnycastGatewayPrerequisitesConfig = `
resource "catalystcenter_area" "test" {
name = "Area1"
parent_name = "Global"
- depends_on = [catalystcenter_ip_pool.test]
}
resource "catalystcenter_ip_pool" "test" {
name = "MyPool1"
@@ -78,7 +77,6 @@ resource "catalystcenter_fabric_site" "test" {
site_id = catalystcenter_area.test.id
pub_sub_enabled = false
authentication_profile_name = "No Authentication"
- depends_on = [catalystcenter_area.test]
}
resource "catalystcenter_fabric_virtual_network" "test" {
virtual_network_name = "SDA_VN1"
@@ -86,9 +84,9 @@ resource "catalystcenter_fabric_virtual_network" "test" {
sg_names = ["Employees"]
}
resource "catalystcenter_virtual_network_to_fabric_site" "test" {
- virtual_network_name = "SDA_VN1"
+ virtual_network_name = catalystcenter_fabric_virtual_network.test.id
site_name_hierarchy = "Global/Area1"
- depends_on = [catalystcenter_fabric_virtual_network.test, catalystcenter_fabric_site.test]
+ depends_on = [catalystcenter_fabric_site.test]
}
`
diff --git a/internal/provider/data_source_catalystcenter_fabric_l2_virtual_network.go b/internal/provider/data_source_catalystcenter_fabric_l2_virtual_network.go
new file mode 100644
index 00000000..1a1eda20
--- /dev/null
+++ b/internal/provider/data_source_catalystcenter_fabric_l2_virtual_network.go
@@ -0,0 +1,131 @@
+// Copyright © 2023 Cisco Systems, Inc. and its affiliates.
+// All rights reserved.
+//
+// Licensed under the Mozilla Public License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://mozilla.org/MPL/2.0/
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// SPDX-License-Identifier: MPL-2.0
+
+package provider
+
+// Section below is generated&owned by "gen/generator.go". //template:begin imports
+import (
+ "context"
+ "fmt"
+ "net/url"
+
+ "github.com/hashicorp/terraform-plugin-framework/datasource"
+ "github.com/hashicorp/terraform-plugin-framework/datasource/schema"
+ "github.com/hashicorp/terraform-plugin-log/tflog"
+ cc "github.com/netascode/go-catalystcenter"
+)
+
+// End of section. //template:end imports
+
+// Section below is generated&owned by "gen/generator.go". //template:begin model
+
+// Ensure the implementation satisfies the expected interfaces.
+var (
+ _ datasource.DataSource = &FabricL2VirtualNetworkDataSource{}
+ _ datasource.DataSourceWithConfigure = &FabricL2VirtualNetworkDataSource{}
+)
+
+func NewFabricL2VirtualNetworkDataSource() datasource.DataSource {
+ return &FabricL2VirtualNetworkDataSource{}
+}
+
+type FabricL2VirtualNetworkDataSource struct {
+ client *cc.Client
+}
+
+func (d *FabricL2VirtualNetworkDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
+ resp.TypeName = req.ProviderTypeName + "_fabric_l2_virtual_network"
+}
+
+func (d *FabricL2VirtualNetworkDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) {
+ resp.Schema = schema.Schema{
+ // This description is used by the documentation generator and the language server.
+ MarkdownDescription: "This data source can read the Fabric L2 Virtual Network.",
+
+ Attributes: map[string]schema.Attribute{
+ "id": schema.StringAttribute{
+ MarkdownDescription: "The id of the object",
+ Computed: true,
+ },
+ "fabric_id": schema.StringAttribute{
+ MarkdownDescription: "ID of the fabric this layer 2 virtual network is to be assigned to",
+ Required: true,
+ },
+ "vlan_name": schema.StringAttribute{
+ MarkdownDescription: "Name of the VLAN of the layer 2 virtual network. Must contain only alphanumeric characters, underscores, and hyphens",
+ Required: true,
+ },
+ "vlan_id": schema.Int64Attribute{
+ MarkdownDescription: "ID of the VLAN of the layer 2 virtual network. Allowed VLAN range is 2-4093 except for reserved VLANs 1002-1005, and 2046. If deploying on a fabric zone, this vlanId must match the vlanId of the corresponding layer 2 virtual network on the fabric site",
+ Computed: true,
+ },
+ "traffic_type": schema.StringAttribute{
+ MarkdownDescription: "The type of traffic that is served",
+ Computed: true,
+ },
+ "fabric_enabled_wireless": schema.BoolAttribute{
+ MarkdownDescription: "Set to true to enable wireless. Default is false",
+ Computed: true,
+ },
+ "associated_l3_virtual_network_name": schema.StringAttribute{
+ MarkdownDescription: "Name of the layer 3 virtual network associated with the layer 2 virtual network. This field is provided to support requests related to virtual network anchoring. The layer 3 virtual network must have already been added to the fabric before association. This field must either be present in all payload elements or none",
+ Computed: true,
+ },
+ },
+ }
+}
+
+func (d *FabricL2VirtualNetworkDataSource) Configure(_ context.Context, req datasource.ConfigureRequest, _ *datasource.ConfigureResponse) {
+ if req.ProviderData == nil {
+ return
+ }
+
+ d.client = req.ProviderData.(*CcProviderData).Client
+}
+
+// End of section. //template:end model
+
+// Section below is generated&owned by "gen/generator.go". //template:begin read
+func (d *FabricL2VirtualNetworkDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
+ var config FabricL2VirtualNetwork
+
+ // Read config
+ diags := req.Config.Get(ctx, &config)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Beginning Read", config.Id.String()))
+
+ params := ""
+ params += "?fabricId=" + url.QueryEscape(config.FabricId.ValueString()) + "&vlanName=" + url.QueryEscape(config.VlanName.ValueString())
+ res, err := d.client.Get(config.getPath() + params)
+ if err != nil {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to retrieve object, got error: %s", err))
+ return
+ }
+
+ config.fromBody(ctx, res)
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Read finished successfully", config.Id.ValueString()))
+
+ diags = resp.State.Set(ctx, &config)
+ resp.Diagnostics.Append(diags...)
+}
+
+// End of section. //template:end read
diff --git a/internal/provider/data_source_catalystcenter_template_version_test.go b/internal/provider/data_source_catalystcenter_fabric_l2_virtual_network_test.go
similarity index 50%
rename from internal/provider/data_source_catalystcenter_template_version_test.go
rename to internal/provider/data_source_catalystcenter_fabric_l2_virtual_network_test.go
index d5a96894..cfd6529e 100644
--- a/internal/provider/data_source_catalystcenter_template_version_test.go
+++ b/internal/provider/data_source_catalystcenter_fabric_l2_virtual_network_test.go
@@ -27,14 +27,18 @@ import (
// End of section. //template:end imports
// Section below is generated&owned by "gen/generator.go". //template:begin testAccDataSource
-func TestAccDataSourceCcTemplateVersion(t *testing.T) {
+func TestAccDataSourceCcFabricL2VirtualNetwork(t *testing.T) {
var checks []resource.TestCheckFunc
+ checks = append(checks, resource.TestCheckResourceAttr("data.catalystcenter_fabric_l2_virtual_network.test", "vlan_name", "VLAN401"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.catalystcenter_fabric_l2_virtual_network.test", "vlan_id", "401"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.catalystcenter_fabric_l2_virtual_network.test", "traffic_type", "DATA"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.catalystcenter_fabric_l2_virtual_network.test", "fabric_enabled_wireless", "false"))
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
Steps: []resource.TestStep{
{
- Config: testAccDataSourceCcTemplateVersionPrerequisitesConfig + testAccDataSourceCcTemplateVersionConfig(),
+ Config: testAccDataSourceCcFabricL2VirtualNetworkPrerequisitesConfig + testAccDataSourceCcFabricL2VirtualNetworkConfig(),
Check: resource.ComposeTestCheckFunc(checks...),
},
},
@@ -44,42 +48,36 @@ func TestAccDataSourceCcTemplateVersion(t *testing.T) {
// End of section. //template:end testAccDataSource
// Section below is generated&owned by "gen/generator.go". //template:begin testPrerequisites
-const testAccDataSourceCcTemplateVersionPrerequisitesConfig = `
-resource "catalystcenter_project" "test" {
- name = "Project1"
+const testAccDataSourceCcFabricL2VirtualNetworkPrerequisitesConfig = `
+resource "catalystcenter_area" "test" {
+ name = "Area1"
+ parent_name = "Global"
}
-
-resource "catalystcenter_template" "test" {
- project_id = catalystcenter_project.test.id
- name = "Template1"
- description = "My description"
- device_types = [
- {
- product_family = "Switches and Hubs"
- product_series = "Cisco Catalyst 9300 Series Switches"
- product_type = "Cisco Catalyst 9300 Switch"
- }
- ]
- language = "JINJA"
- software_type = "IOS-XE"
- software_variant = "XE"
- software_version = "16.12.1a"
- template_content = "hostname SW1"
+resource "catalystcenter_fabric_site" "test" {
+ site_id = catalystcenter_area.test.id
+ pub_sub_enabled = false
+ authentication_profile_name = "No Authentication"
}
+
`
// End of section. //template:end testPrerequisites
// Section below is generated&owned by "gen/generator.go". //template:begin testAccDataSourceConfig
-func testAccDataSourceCcTemplateVersionConfig() string {
- config := `resource "catalystcenter_template_version" "test" {` + "\n"
- config += ` template_id = catalystcenter_template.test.id` + "\n"
- config += ` comments = "New Version"` + "\n"
+func testAccDataSourceCcFabricL2VirtualNetworkConfig() string {
+ config := `resource "catalystcenter_fabric_l2_virtual_network" "test" {` + "\n"
+ config += ` fabric_id = catalystcenter_fabric_site.test.id` + "\n"
+ config += ` vlan_name = "VLAN401"` + "\n"
+ config += ` vlan_id = 401` + "\n"
+ config += ` traffic_type = "DATA"` + "\n"
+ config += ` fabric_enabled_wireless = false` + "\n"
config += `}` + "\n"
config += `
- data "catalystcenter_template_version" "test" {
- id = catalystcenter_template_version.test.id
+ data "catalystcenter_fabric_l2_virtual_network" "test" {
+ fabric_id = catalystcenter_fabric_site.test.id
+ vlan_name = "VLAN401"
+ depends_on = [catalystcenter_fabric_l2_virtual_network.test]
}
`
return config
diff --git a/internal/provider/data_source_catalystcenter_template_version.go b/internal/provider/data_source_catalystcenter_template_version.go
deleted file mode 100644
index c0f51ee3..00000000
--- a/internal/provider/data_source_catalystcenter_template_version.go
+++ /dev/null
@@ -1,115 +0,0 @@
-// Copyright © 2023 Cisco Systems, Inc. and its affiliates.
-// All rights reserved.
-//
-// Licensed under the Mozilla Public License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://mozilla.org/MPL/2.0/
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// SPDX-License-Identifier: MPL-2.0
-
-package provider
-
-// Section below is generated&owned by "gen/generator.go". //template:begin imports
-import (
- "context"
- "fmt"
- "net/url"
-
- "github.com/hashicorp/terraform-plugin-framework/datasource"
- "github.com/hashicorp/terraform-plugin-framework/datasource/schema"
- "github.com/hashicorp/terraform-plugin-log/tflog"
- cc "github.com/netascode/go-catalystcenter"
-)
-
-// End of section. //template:end imports
-
-// Section below is generated&owned by "gen/generator.go". //template:begin model
-
-// Ensure the implementation satisfies the expected interfaces.
-var (
- _ datasource.DataSource = &TemplateVersionDataSource{}
- _ datasource.DataSourceWithConfigure = &TemplateVersionDataSource{}
-)
-
-func NewTemplateVersionDataSource() datasource.DataSource {
- return &TemplateVersionDataSource{}
-}
-
-type TemplateVersionDataSource struct {
- client *cc.Client
-}
-
-func (d *TemplateVersionDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
- resp.TypeName = req.ProviderTypeName + "_template_version"
-}
-
-func (d *TemplateVersionDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) {
- resp.Schema = schema.Schema{
- // This description is used by the documentation generator and the language server.
- MarkdownDescription: "This data source can read the Template Version.",
-
- Attributes: map[string]schema.Attribute{
- "id": schema.StringAttribute{
- MarkdownDescription: "The id of the object",
- Required: true,
- },
- "template_id": schema.StringAttribute{
- MarkdownDescription: "UUID of template",
- Computed: true,
- },
- "comments": schema.StringAttribute{
- MarkdownDescription: "Template version comments",
- Computed: true,
- },
- },
- }
-}
-
-func (d *TemplateVersionDataSource) Configure(_ context.Context, req datasource.ConfigureRequest, _ *datasource.ConfigureResponse) {
- if req.ProviderData == nil {
- return
- }
-
- d.client = req.ProviderData.(*CcProviderData).Client
-}
-
-// End of section. //template:end model
-
-// Section below is generated&owned by "gen/generator.go". //template:begin read
-func (d *TemplateVersionDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
- var config TemplateVersion
-
- // Read config
- diags := req.Config.Get(ctx, &config)
- resp.Diagnostics.Append(diags...)
- if resp.Diagnostics.HasError() {
- return
- }
-
- tflog.Debug(ctx, fmt.Sprintf("%s: Beginning Read", config.Id.String()))
-
- params := ""
- params += "/" + url.QueryEscape(config.Id.ValueString())
- res, err := d.client.Get(config.getPath() + params)
- if err != nil {
- resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to retrieve object, got error: %s", err))
- return
- }
-
- config.fromBody(ctx, res)
-
- tflog.Debug(ctx, fmt.Sprintf("%s: Read finished successfully", config.Id.ValueString()))
-
- diags = resp.State.Set(ctx, &config)
- resp.Diagnostics.Append(diags...)
-}
-
-// End of section. //template:end read
diff --git a/internal/provider/model_catalystcenter_deploy_template.go b/internal/provider/model_catalystcenter_deploy_template.go
index db801d39..af21f56c 100644
--- a/internal/provider/model_catalystcenter_deploy_template.go
+++ b/internal/provider/model_catalystcenter_deploy_template.go
@@ -44,6 +44,7 @@ type DeployTemplateMemberTemplateDeploymentInfo struct {
TemplateId types.String `tfsdk:"template_id"`
ForcePushTemplate types.Bool `tfsdk:"force_push_template"`
IsComposite types.Bool `tfsdk:"is_composite"`
+ CopyingConfig types.Bool `tfsdk:"copying_config"`
MainTemplateId types.String `tfsdk:"main_template_id"`
TargetInfo []DeployTemplateMemberTemplateDeploymentInfoTargetInfo `tfsdk:"target_info"`
}
@@ -124,6 +125,9 @@ func (data DeployTemplate) toBody(ctx context.Context, state DeployTemplate) str
if !item.IsComposite.IsNull() {
itemBody, _ = sjson.Set(itemBody, "isComposite", item.IsComposite.ValueBool())
}
+ if !item.CopyingConfig.IsNull() {
+ itemBody, _ = sjson.Set(itemBody, "copyingConfig", item.CopyingConfig.ValueBool())
+ }
if !item.MainTemplateId.IsNull() {
itemBody, _ = sjson.Set(itemBody, "mainTemplateId", item.MainTemplateId.ValueString())
}
@@ -256,6 +260,11 @@ func (data *DeployTemplate) fromBody(ctx context.Context, res gjson.Result) {
} else {
item.IsComposite = types.BoolNull()
}
+ if cValue := v.Get("copyingConfig"); cValue.Exists() {
+ item.CopyingConfig = types.BoolValue(cValue.Bool())
+ } else {
+ item.CopyingConfig = types.BoolNull()
+ }
if cValue := v.Get("mainTemplateId"); cValue.Exists() {
item.MainTemplateId = types.StringValue(cValue.String())
} else {
@@ -441,6 +450,11 @@ func (data *DeployTemplate) updateFromBody(ctx context.Context, res gjson.Result
} else {
data.MemberTemplateDeploymentInfo[i].IsComposite = types.BoolNull()
}
+ if value := r.Get("copyingConfig"); value.Exists() && !data.MemberTemplateDeploymentInfo[i].CopyingConfig.IsNull() {
+ data.MemberTemplateDeploymentInfo[i].CopyingConfig = types.BoolValue(value.Bool())
+ } else {
+ data.MemberTemplateDeploymentInfo[i].CopyingConfig = types.BoolNull()
+ }
if value := r.Get("mainTemplateId"); value.Exists() && !data.MemberTemplateDeploymentInfo[i].MainTemplateId.IsNull() {
data.MemberTemplateDeploymentInfo[i].MainTemplateId = types.StringValue(value.String())
} else {
diff --git a/internal/provider/model_catalystcenter_fabric_l2_virtual_network.go b/internal/provider/model_catalystcenter_fabric_l2_virtual_network.go
new file mode 100644
index 00000000..11492f82
--- /dev/null
+++ b/internal/provider/model_catalystcenter_fabric_l2_virtual_network.go
@@ -0,0 +1,182 @@
+// Copyright © 2023 Cisco Systems, Inc. and its affiliates.
+// All rights reserved.
+//
+// Licensed under the Mozilla Public License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://mozilla.org/MPL/2.0/
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// SPDX-License-Identifier: MPL-2.0
+
+package provider
+
+// Section below is generated&owned by "gen/generator.go". //template:begin imports
+import (
+ "context"
+
+ "github.com/hashicorp/terraform-plugin-framework/types"
+ "github.com/tidwall/gjson"
+ "github.com/tidwall/sjson"
+)
+
+// End of section. //template:end imports
+
+// Section below is generated&owned by "gen/generator.go". //template:begin types
+type FabricL2VirtualNetwork struct {
+ Id types.String `tfsdk:"id"`
+ FabricId types.String `tfsdk:"fabric_id"`
+ VlanName types.String `tfsdk:"vlan_name"`
+ VlanId types.Int64 `tfsdk:"vlan_id"`
+ TrafficType types.String `tfsdk:"traffic_type"`
+ FabricEnabledWireless types.Bool `tfsdk:"fabric_enabled_wireless"`
+ AssociatedL3VirtualNetworkName types.String `tfsdk:"associated_l3_virtual_network_name"`
+}
+
+// End of section. //template:end types
+
+// Section below is generated&owned by "gen/generator.go". //template:begin getPath
+func (data FabricL2VirtualNetwork) getPath() string {
+ return "/dna/intent/api/v1/sda/layer2VirtualNetworks"
+}
+
+// End of section. //template:end getPath
+
+// Section below is generated&owned by "gen/generator.go". //template:begin getPathDelete
+
+// End of section. //template:end getPathDelete
+
+// Section below is generated&owned by "gen/generator.go". //template:begin toBody
+func (data FabricL2VirtualNetwork) toBody(ctx context.Context, state FabricL2VirtualNetwork) string {
+ body := ""
+ put := false
+ if state.Id.ValueString() != "" {
+ put = true
+ body, _ = sjson.Set(body, "0.id", state.Id.ValueString())
+ }
+ _ = put
+ if !data.FabricId.IsNull() {
+ body, _ = sjson.Set(body, "0.fabricId", data.FabricId.ValueString())
+ }
+ if !data.VlanName.IsNull() {
+ body, _ = sjson.Set(body, "0.vlanName", data.VlanName.ValueString())
+ }
+ if !data.VlanId.IsNull() {
+ body, _ = sjson.Set(body, "0.vlanId", data.VlanId.ValueInt64())
+ }
+ if !data.TrafficType.IsNull() {
+ body, _ = sjson.Set(body, "0.trafficType", data.TrafficType.ValueString())
+ }
+ if !data.FabricEnabledWireless.IsNull() {
+ body, _ = sjson.Set(body, "0.isFabricEnabledWireless", data.FabricEnabledWireless.ValueBool())
+ }
+ if !data.AssociatedL3VirtualNetworkName.IsNull() {
+ body, _ = sjson.Set(body, "0.associatedLayer3VirtualNetworkName", data.AssociatedL3VirtualNetworkName.ValueString())
+ }
+ return body
+}
+
+// End of section. //template:end toBody
+
+// Section below is generated&owned by "gen/generator.go". //template:begin fromBody
+func (data *FabricL2VirtualNetwork) fromBody(ctx context.Context, res gjson.Result) {
+ // Retrieve the 'id' attribute, if Data Source doesn't require id
+ if value := res.Get("response.0.id"); value.Exists() {
+ data.Id = types.StringValue(value.String())
+ } else {
+ data.Id = types.StringNull()
+ }
+ if value := res.Get("response.0.fabricId"); value.Exists() {
+ data.FabricId = types.StringValue(value.String())
+ } else {
+ data.FabricId = types.StringNull()
+ }
+ if value := res.Get("response.0.vlanName"); value.Exists() {
+ data.VlanName = types.StringValue(value.String())
+ } else {
+ data.VlanName = types.StringNull()
+ }
+ if value := res.Get("response.0.vlanId"); value.Exists() {
+ data.VlanId = types.Int64Value(value.Int())
+ } else {
+ data.VlanId = types.Int64Null()
+ }
+ if value := res.Get("response.0.trafficType"); value.Exists() {
+ data.TrafficType = types.StringValue(value.String())
+ } else {
+ data.TrafficType = types.StringNull()
+ }
+ if value := res.Get("response.0.isFabricEnabledWireless"); value.Exists() {
+ data.FabricEnabledWireless = types.BoolValue(value.Bool())
+ } else {
+ data.FabricEnabledWireless = types.BoolNull()
+ }
+ if value := res.Get("response.0.associatedLayer3VirtualNetworkName"); value.Exists() {
+ data.AssociatedL3VirtualNetworkName = types.StringValue(value.String())
+ } else {
+ data.AssociatedL3VirtualNetworkName = types.StringNull()
+ }
+}
+
+// End of section. //template:end fromBody
+
+// Section below is generated&owned by "gen/generator.go". //template:begin updateFromBody
+func (data *FabricL2VirtualNetwork) updateFromBody(ctx context.Context, res gjson.Result) {
+ if value := res.Get("response.0.fabricId"); value.Exists() && !data.FabricId.IsNull() {
+ data.FabricId = types.StringValue(value.String())
+ } else {
+ data.FabricId = types.StringNull()
+ }
+ if value := res.Get("response.0.vlanName"); value.Exists() && !data.VlanName.IsNull() {
+ data.VlanName = types.StringValue(value.String())
+ } else {
+ data.VlanName = types.StringNull()
+ }
+ if value := res.Get("response.0.vlanId"); value.Exists() && !data.VlanId.IsNull() {
+ data.VlanId = types.Int64Value(value.Int())
+ } else {
+ data.VlanId = types.Int64Null()
+ }
+ if value := res.Get("response.0.trafficType"); value.Exists() && !data.TrafficType.IsNull() {
+ data.TrafficType = types.StringValue(value.String())
+ } else {
+ data.TrafficType = types.StringNull()
+ }
+ if value := res.Get("response.0.isFabricEnabledWireless"); value.Exists() && !data.FabricEnabledWireless.IsNull() {
+ data.FabricEnabledWireless = types.BoolValue(value.Bool())
+ } else {
+ data.FabricEnabledWireless = types.BoolNull()
+ }
+ if value := res.Get("response.0.associatedLayer3VirtualNetworkName"); value.Exists() && !data.AssociatedL3VirtualNetworkName.IsNull() {
+ data.AssociatedL3VirtualNetworkName = types.StringValue(value.String())
+ } else {
+ data.AssociatedL3VirtualNetworkName = types.StringNull()
+ }
+}
+
+// End of section. //template:end updateFromBody
+
+// Section below is generated&owned by "gen/generator.go". //template:begin isNull
+func (data *FabricL2VirtualNetwork) isNull(ctx context.Context, res gjson.Result) bool {
+ if !data.VlanId.IsNull() {
+ return false
+ }
+ if !data.TrafficType.IsNull() {
+ return false
+ }
+ if !data.FabricEnabledWireless.IsNull() {
+ return false
+ }
+ if !data.AssociatedL3VirtualNetworkName.IsNull() {
+ return false
+ }
+ return true
+}
+
+// End of section. //template:end isNull
diff --git a/internal/provider/provider.go b/internal/provider/provider.go
index 457d309b..9a875fd3 100644
--- a/internal/provider/provider.go
+++ b/internal/provider/provider.go
@@ -288,6 +288,7 @@ func (p *CcProvider) Resources(ctx context.Context) []func() resource.Resource {
NewFabricAuthenticationProfileResource,
NewFabricDeviceResource,
NewFabricL2HandoffResource,
+ NewFabricL2VirtualNetworkResource,
NewFabricL3HandoffIPTransitResource,
NewFabricPortAssignmentResource,
NewFabricProvisionDeviceResource,
@@ -346,6 +347,7 @@ func (p *CcProvider) DataSources(ctx context.Context) []func() datasource.DataSo
NewFabricAuthenticationProfileDataSource,
NewFabricDeviceDataSource,
NewFabricL2HandoffDataSource,
+ NewFabricL2VirtualNetworkDataSource,
NewFabricL3HandoffIPTransitDataSource,
NewFabricPortAssignmentDataSource,
NewFabricProvisionDeviceDataSource,
@@ -365,7 +367,6 @@ func (p *CcProvider) DataSources(ctx context.Context) []func() datasource.DataSo
NewSPProfileDataSource,
NewTagDataSource,
NewTemplateDataSource,
- NewTemplateVersionDataSource,
NewTransitNetworkDataSource,
NewUserDataSource,
NewWirelessEnterpriseSSIDDataSource,
diff --git a/internal/provider/resource_catalystcenter_anycast_gateway.go b/internal/provider/resource_catalystcenter_anycast_gateway.go
index ccdbd403..5f3a8914 100644
--- a/internal/provider/resource_catalystcenter_anycast_gateway.go
+++ b/internal/provider/resource_catalystcenter_anycast_gateway.go
@@ -202,7 +202,7 @@ func (r *AnycastGatewayResource) Create(ctx context.Context, req resource.Create
body := plan.toBody(ctx, AnycastGateway{})
params := ""
- res, err := r.client.Post(plan.getPath()+params, body, func(r *cc.Req) { r.MaxAsyncWaitTime = 120 })
+ res, err := r.client.Post(plan.getPath()+params, body)
if err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to configure object (%s), got error: %s, %s", "POST", err, res.String()))
return
@@ -284,7 +284,7 @@ func (r *AnycastGatewayResource) Update(ctx context.Context, req resource.Update
body := plan.toBody(ctx, state)
params := ""
- res, err := r.client.Put(plan.getPath()+params, body, func(r *cc.Req) { r.MaxAsyncWaitTime = 120 })
+ res, err := r.client.Put(plan.getPath()+params, body)
if err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to configure object (PUT), got error: %s, %s", err, res.String()))
return
diff --git a/internal/provider/resource_catalystcenter_anycast_gateway_test.go b/internal/provider/resource_catalystcenter_anycast_gateway_test.go
index 8d6c4bad..6cae5de7 100644
--- a/internal/provider/resource_catalystcenter_anycast_gateway_test.go
+++ b/internal/provider/resource_catalystcenter_anycast_gateway_test.go
@@ -60,7 +60,6 @@ const testAccCcAnycastGatewayPrerequisitesConfig = `
resource "catalystcenter_area" "test" {
name = "Area1"
parent_name = "Global"
- depends_on = [catalystcenter_ip_pool.test]
}
resource "catalystcenter_ip_pool" "test" {
name = "MyPool1"
@@ -80,7 +79,6 @@ resource "catalystcenter_fabric_site" "test" {
site_id = catalystcenter_area.test.id
pub_sub_enabled = false
authentication_profile_name = "No Authentication"
- depends_on = [catalystcenter_area.test]
}
resource "catalystcenter_fabric_virtual_network" "test" {
virtual_network_name = "SDA_VN1"
@@ -88,9 +86,9 @@ resource "catalystcenter_fabric_virtual_network" "test" {
sg_names = ["Employees"]
}
resource "catalystcenter_virtual_network_to_fabric_site" "test" {
- virtual_network_name = "SDA_VN1"
+ virtual_network_name = catalystcenter_fabric_virtual_network.test.id
site_name_hierarchy = "Global/Area1"
- depends_on = [catalystcenter_fabric_virtual_network.test, catalystcenter_fabric_site.test]
+ depends_on = [catalystcenter_fabric_site.test]
}
`
diff --git a/internal/provider/resource_catalystcenter_deploy_template.go b/internal/provider/resource_catalystcenter_deploy_template.go
index d8156c2c..93427984 100644
--- a/internal/provider/resource_catalystcenter_deploy_template.go
+++ b/internal/provider/resource_catalystcenter_deploy_template.go
@@ -91,7 +91,7 @@ func (r *DeployTemplateResource) Schema(ctx context.Context, req resource.Schema
NestedObject: schema.NestedAttributeObject{
Attributes: map[string]schema.Attribute{
"template_id": schema.StringAttribute{
- MarkdownDescription: helpers.NewAttributeDescription("ID of template to be provisioned").String,
+ MarkdownDescription: helpers.NewAttributeDescription("Versioned Template ID").String,
Required: true,
},
"force_push_template": schema.BoolAttribute{
@@ -102,8 +102,12 @@ func (r *DeployTemplateResource) Schema(ctx context.Context, req resource.Schema
MarkdownDescription: helpers.NewAttributeDescription("Composite template flag").String,
Optional: true,
},
+ "copying_config": schema.BoolAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Copying Config").String,
+ Optional: true,
+ },
"main_template_id": schema.StringAttribute{
- MarkdownDescription: helpers.NewAttributeDescription("Composite Template ID").String,
+ MarkdownDescription: helpers.NewAttributeDescription("Template ID").String,
Optional: true,
},
"target_info": schema.ListNestedAttribute{
@@ -156,7 +160,7 @@ func (r *DeployTemplateResource) Schema(ctx context.Context, req resource.Schema
},
"versioned_template_id": schema.StringAttribute{
MarkdownDescription: helpers.NewAttributeDescription("Versioned template ID to be provisioned").String,
- Required: true,
+ Optional: true,
},
},
},
@@ -214,7 +218,7 @@ func (r *DeployTemplateResource) Schema(ctx context.Context, req resource.Schema
},
"versioned_template_id": schema.StringAttribute{
MarkdownDescription: helpers.NewAttributeDescription("Versioned template ID to be provisioned").String,
- Required: true,
+ Optional: true,
},
},
},
diff --git a/internal/provider/resource_catalystcenter_deploy_template_test.go b/internal/provider/resource_catalystcenter_deploy_template_test.go
index c1a4410d..c4b2994e 100644
--- a/internal/provider/resource_catalystcenter_deploy_template_test.go
+++ b/internal/provider/resource_catalystcenter_deploy_template_test.go
@@ -92,7 +92,6 @@ func testAccCcDeployTemplateConfig_minimum() string {
config += ` template_id = catalystcenter_template_version.example.id` + "\n"
config += ` target_info = [{` + "\n"
config += ` type = "MANAGED_DEVICE_HOSTNAME"` + "\n"
- config += ` versioned_template_id = catalystcenter_template_version.example.id` + "\n"
config += ` }]` + "\n"
config += `}` + "\n"
return config
diff --git a/internal/provider/resource_catalystcenter_discovery.go b/internal/provider/resource_catalystcenter_discovery.go
index 115e6bb8..b680d096 100644
--- a/internal/provider/resource_catalystcenter_discovery.go
+++ b/internal/provider/resource_catalystcenter_discovery.go
@@ -323,7 +323,7 @@ func (r *DiscoveryResource) Create(ctx context.Context, req resource.CreateReque
body := plan.toBody(ctx, Discovery{})
params := ""
- res, err := r.client.Post(plan.getPath()+params, body, func(r *cc.Req) { r.MaxAsyncWaitTime = 600 })
+ res, err := r.client.Post(plan.getPath()+params, body)
if err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to configure object (%s), got error: %s, %s", "POST", err, res.String()))
return
diff --git a/internal/provider/resource_catalystcenter_fabric_device.go b/internal/provider/resource_catalystcenter_fabric_device.go
index be656763..b0f8fcf7 100644
--- a/internal/provider/resource_catalystcenter_fabric_device.go
+++ b/internal/provider/resource_catalystcenter_fabric_device.go
@@ -155,7 +155,7 @@ func (r *FabricDeviceResource) Create(ctx context.Context, req resource.CreateRe
body := plan.toBody(ctx, FabricDevice{})
params := ""
- res, err := r.client.Post(plan.getPath()+params, body, func(r *cc.Req) { r.MaxAsyncWaitTime = 300 })
+ res, err := r.client.Post(plan.getPath()+params, body)
if err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to configure object (%s), got error: %s, %s", "POST", err, res.String()))
return
@@ -237,7 +237,7 @@ func (r *FabricDeviceResource) Update(ctx context.Context, req resource.UpdateRe
body := plan.toBody(ctx, state)
params := ""
- res, err := r.client.Put(plan.getPath()+params, body, func(r *cc.Req) { r.MaxAsyncWaitTime = 300 })
+ res, err := r.client.Put(plan.getPath()+params, body)
if err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to configure object (PUT), got error: %s, %s", err, res.String()))
return
diff --git a/internal/provider/resource_catalystcenter_fabric_l2_virtual_network.go b/internal/provider/resource_catalystcenter_fabric_l2_virtual_network.go
new file mode 100644
index 00000000..439bc1b1
--- /dev/null
+++ b/internal/provider/resource_catalystcenter_fabric_l2_virtual_network.go
@@ -0,0 +1,280 @@
+// Copyright © 2023 Cisco Systems, Inc. and its affiliates.
+// All rights reserved.
+//
+// Licensed under the Mozilla Public License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://mozilla.org/MPL/2.0/
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// SPDX-License-Identifier: MPL-2.0
+
+package provider
+
+// Section below is generated&owned by "gen/generator.go". //template:begin imports
+import (
+ "context"
+ "fmt"
+ "net/url"
+ "strings"
+
+ "github.com/CiscoDevNet/terraform-provider-catalystcenter/internal/provider/helpers"
+ "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
+ "github.com/hashicorp/terraform-plugin-framework/path"
+ "github.com/hashicorp/terraform-plugin-framework/resource"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/int64planmodifier"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
+ "github.com/hashicorp/terraform-plugin-framework/schema/validator"
+ "github.com/hashicorp/terraform-plugin-framework/types"
+ "github.com/hashicorp/terraform-plugin-log/tflog"
+ cc "github.com/netascode/go-catalystcenter"
+)
+
+// End of section. //template:end imports
+
+// Section below is generated&owned by "gen/generator.go". //template:begin model
+
+// Ensure provider defined types fully satisfy framework interfaces
+var _ resource.Resource = &FabricL2VirtualNetworkResource{}
+var _ resource.ResourceWithImportState = &FabricL2VirtualNetworkResource{}
+
+func NewFabricL2VirtualNetworkResource() resource.Resource {
+ return &FabricL2VirtualNetworkResource{}
+}
+
+type FabricL2VirtualNetworkResource struct {
+ client *cc.Client
+}
+
+func (r *FabricL2VirtualNetworkResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
+ resp.TypeName = req.ProviderTypeName + "_fabric_l2_virtual_network"
+}
+
+func (r *FabricL2VirtualNetworkResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
+ resp.Schema = schema.Schema{
+ // This description is used by the documentation generator and the language server.
+ MarkdownDescription: helpers.NewAttributeDescription("This resource can manage a Fabric L2 Virtual Network.").String,
+
+ Attributes: map[string]schema.Attribute{
+ "id": schema.StringAttribute{
+ MarkdownDescription: "The id of the object",
+ Computed: true,
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.UseStateForUnknown(),
+ },
+ },
+ "fabric_id": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("ID of the fabric this layer 2 virtual network is to be assigned to").String,
+ Required: true,
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.RequiresReplace(),
+ },
+ },
+ "vlan_name": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Name of the VLAN of the layer 2 virtual network. Must contain only alphanumeric characters, underscores, and hyphens").String,
+ Required: true,
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.RequiresReplace(),
+ },
+ },
+ "vlan_id": schema.Int64Attribute{
+ MarkdownDescription: helpers.NewAttributeDescription("ID of the VLAN of the layer 2 virtual network. Allowed VLAN range is 2-4093 except for reserved VLANs 1002-1005, and 2046. If deploying on a fabric zone, this vlanId must match the vlanId of the corresponding layer 2 virtual network on the fabric site").String,
+ Optional: true,
+ PlanModifiers: []planmodifier.Int64{
+ int64planmodifier.RequiresReplace(),
+ },
+ },
+ "traffic_type": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("The type of traffic that is served").AddStringEnumDescription("DATA", "VOICE").String,
+ Required: true,
+ Validators: []validator.String{
+ stringvalidator.OneOf("DATA", "VOICE"),
+ },
+ },
+ "fabric_enabled_wireless": schema.BoolAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Set to true to enable wireless. Default is false").String,
+ Optional: true,
+ },
+ "associated_l3_virtual_network_name": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Name of the layer 3 virtual network associated with the layer 2 virtual network. This field is provided to support requests related to virtual network anchoring. The layer 3 virtual network must have already been added to the fabric before association. This field must either be present in all payload elements or none").String,
+ Optional: true,
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.RequiresReplace(),
+ },
+ },
+ },
+ }
+}
+
+func (r *FabricL2VirtualNetworkResource) Configure(_ context.Context, req resource.ConfigureRequest, _ *resource.ConfigureResponse) {
+ if req.ProviderData == nil {
+ return
+ }
+
+ r.client = req.ProviderData.(*CcProviderData).Client
+}
+
+// End of section. //template:end model
+
+// Section below is generated&owned by "gen/generator.go". //template:begin create
+func (r *FabricL2VirtualNetworkResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
+ var plan FabricL2VirtualNetwork
+
+ // Read plan
+ diags := req.Plan.Get(ctx, &plan)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Beginning Create", plan.Id.ValueString()))
+
+ // Create object
+ body := plan.toBody(ctx, FabricL2VirtualNetwork{})
+
+ params := ""
+ res, err := r.client.Post(plan.getPath()+params, body)
+ if err != nil {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to configure object (%s), got error: %s, %s", "POST", err, res.String()))
+ return
+ }
+ params = ""
+ params += "?fabricId=" + url.QueryEscape(plan.FabricId.ValueString()) + "&vlanName=" + url.QueryEscape(plan.VlanName.ValueString())
+ res, err = r.client.Get(plan.getPath() + params)
+ if err != nil {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to retrieve object (GET), got error: %s, %s", err, res.String()))
+ return
+ }
+ plan.Id = types.StringValue(res.Get("response.0.id").String())
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Create finished successfully", plan.Id.ValueString()))
+
+ diags = resp.State.Set(ctx, &plan)
+ resp.Diagnostics.Append(diags...)
+}
+
+// End of section. //template:end create
+
+// Section below is generated&owned by "gen/generator.go". //template:begin read
+func (r *FabricL2VirtualNetworkResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
+ var state FabricL2VirtualNetwork
+
+ // Read state
+ diags := req.State.Get(ctx, &state)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Beginning Read", state.Id.String()))
+
+ params := ""
+ params += "?fabricId=" + url.QueryEscape(state.FabricId.ValueString()) + "&vlanName=" + url.QueryEscape(state.VlanName.ValueString())
+ res, err := r.client.Get(state.getPath() + params)
+ if err != nil && strings.Contains(err.Error(), "StatusCode 404") {
+ resp.State.RemoveResource(ctx)
+ return
+ } else if err != nil {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to retrieve object (GET), got error: %s, %s", err, res.String()))
+ return
+ }
+
+ // If every attribute is set to null we are dealing with an import operation and therefore reading all attributes
+ if state.isNull(ctx, res) {
+ state.fromBody(ctx, res)
+ } else {
+ state.updateFromBody(ctx, res)
+ }
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Read finished successfully", state.Id.ValueString()))
+
+ diags = resp.State.Set(ctx, &state)
+ resp.Diagnostics.Append(diags...)
+}
+
+// End of section. //template:end read
+
+// Section below is generated&owned by "gen/generator.go". //template:begin update
+func (r *FabricL2VirtualNetworkResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
+ var plan, state FabricL2VirtualNetwork
+
+ // Read plan
+ diags := req.Plan.Get(ctx, &plan)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+ // Read state
+ diags = req.State.Get(ctx, &state)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Beginning Update", plan.Id.ValueString()))
+
+ body := plan.toBody(ctx, state)
+ params := ""
+ res, err := r.client.Put(plan.getPath()+params, body)
+ if err != nil {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to configure object (PUT), got error: %s, %s", err, res.String()))
+ return
+ }
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Update finished successfully", plan.Id.ValueString()))
+
+ diags = resp.State.Set(ctx, &plan)
+ resp.Diagnostics.Append(diags...)
+}
+
+// End of section. //template:end update
+
+// Section below is generated&owned by "gen/generator.go". //template:begin delete
+func (r *FabricL2VirtualNetworkResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
+ var state FabricL2VirtualNetwork
+
+ // Read state
+ diags := req.State.Get(ctx, &state)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Beginning Delete", state.Id.ValueString()))
+ res, err := r.client.Delete(state.getPath() + "/" + url.QueryEscape(state.Id.ValueString()))
+ if err != nil {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to delete object (DELETE), got error: %s, %s", err, res.String()))
+ return
+ }
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Delete finished successfully", state.Id.ValueString()))
+
+ resp.State.RemoveResource(ctx)
+}
+
+// End of section. //template:end delete
+
+// Section below is generated&owned by "gen/generator.go". //template:begin import
+func (r *FabricL2VirtualNetworkResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
+ idParts := strings.Split(req.ID, ",")
+
+ if len(idParts) != 2 || idParts[0] == "" || idParts[1] == "" {
+ resp.Diagnostics.AddError(
+ "Unexpected Import Identifier",
+ fmt.Sprintf("Expected import identifier with format: ,. Got: %q", req.ID),
+ )
+ return
+ }
+ resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("fabric_id"), idParts[0])...)
+ resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("vlan_name"), idParts[1])...)
+}
+
+// End of section. //template:end import
diff --git a/internal/provider/resource_catalystcenter_fabric_l2_virtual_network_test.go b/internal/provider/resource_catalystcenter_fabric_l2_virtual_network_test.go
new file mode 100644
index 00000000..db143e40
--- /dev/null
+++ b/internal/provider/resource_catalystcenter_fabric_l2_virtual_network_test.go
@@ -0,0 +1,92 @@
+// Copyright © 2023 Cisco Systems, Inc. and its affiliates.
+// All rights reserved.
+//
+// Licensed under the Mozilla Public License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://mozilla.org/MPL/2.0/
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// SPDX-License-Identifier: MPL-2.0
+
+package provider
+
+// Section below is generated&owned by "gen/generator.go". //template:begin imports
+import (
+ "testing"
+
+ "github.com/hashicorp/terraform-plugin-testing/helper/resource"
+)
+
+// End of section. //template:end imports
+
+// Section below is generated&owned by "gen/generator.go". //template:begin testAcc
+func TestAccCcFabricL2VirtualNetwork(t *testing.T) {
+ var checks []resource.TestCheckFunc
+ checks = append(checks, resource.TestCheckResourceAttr("catalystcenter_fabric_l2_virtual_network.test", "vlan_name", "VLAN401"))
+ checks = append(checks, resource.TestCheckResourceAttr("catalystcenter_fabric_l2_virtual_network.test", "vlan_id", "401"))
+ checks = append(checks, resource.TestCheckResourceAttr("catalystcenter_fabric_l2_virtual_network.test", "traffic_type", "DATA"))
+ checks = append(checks, resource.TestCheckResourceAttr("catalystcenter_fabric_l2_virtual_network.test", "fabric_enabled_wireless", "false"))
+
+ var steps []resource.TestStep
+ steps = append(steps, resource.TestStep{
+ Config: testAccCcFabricL2VirtualNetworkPrerequisitesConfig + testAccCcFabricL2VirtualNetworkConfig_all(),
+ Check: resource.ComposeTestCheckFunc(checks...),
+ })
+
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { testAccPreCheck(t) },
+ ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
+ Steps: steps,
+ })
+}
+
+// End of section. //template:end testAcc
+
+// Section below is generated&owned by "gen/generator.go". //template:begin testPrerequisites
+const testAccCcFabricL2VirtualNetworkPrerequisitesConfig = `
+resource "catalystcenter_area" "test" {
+ name = "Area1"
+ parent_name = "Global"
+}
+resource "catalystcenter_fabric_site" "test" {
+ site_id = catalystcenter_area.test.id
+ pub_sub_enabled = false
+ authentication_profile_name = "No Authentication"
+}
+
+`
+
+// End of section. //template:end testPrerequisites
+
+// Section below is generated&owned by "gen/generator.go". //template:begin testAccConfigMinimal
+func testAccCcFabricL2VirtualNetworkConfig_minimum() string {
+ config := `resource "catalystcenter_fabric_l2_virtual_network" "test" {` + "\n"
+ config += ` fabric_id = catalystcenter_fabric_site.test.id` + "\n"
+ config += ` vlan_name = "VLAN401"` + "\n"
+ config += ` traffic_type = "DATA"` + "\n"
+ config += `}` + "\n"
+ return config
+}
+
+// End of section. //template:end testAccConfigMinimal
+
+// Section below is generated&owned by "gen/generator.go". //template:begin testAccConfigAll
+func testAccCcFabricL2VirtualNetworkConfig_all() string {
+ config := `resource "catalystcenter_fabric_l2_virtual_network" "test" {` + "\n"
+ config += ` fabric_id = catalystcenter_fabric_site.test.id` + "\n"
+ config += ` vlan_name = "VLAN401"` + "\n"
+ config += ` vlan_id = 401` + "\n"
+ config += ` traffic_type = "DATA"` + "\n"
+ config += ` fabric_enabled_wireless = false` + "\n"
+ config += `}` + "\n"
+ return config
+}
+
+// End of section. //template:end testAccConfigAll
diff --git a/internal/provider/resource_catalystcenter_fabric_l3_handoff_ip_transit.go b/internal/provider/resource_catalystcenter_fabric_l3_handoff_ip_transit.go
index 0587c199..815835c2 100644
--- a/internal/provider/resource_catalystcenter_fabric_l3_handoff_ip_transit.go
+++ b/internal/provider/resource_catalystcenter_fabric_l3_handoff_ip_transit.go
@@ -170,7 +170,6 @@ func (r *FabricL3HandoffIPTransitResource) Configure(_ context.Context, req reso
// End of section. //template:end model
-// Section below is generated&owned by "gen/generator.go". //template:begin create
func (r *FabricL3HandoffIPTransitResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
var plan FabricL3HandoffIPTransit
@@ -189,8 +188,15 @@ func (r *FabricL3HandoffIPTransitResource) Create(ctx context.Context, req resou
params := ""
res, err := r.client.Post(plan.getPath()+params, body)
if err != nil {
- resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to configure object (%s), got error: %s, %s", "POST", err, res.String()))
- return
+ errorCode := res.Get("response.errorCode").String()
+ if errorCode == "NCDP10000" {
+ // Log a warning and continue execution when device is unreachable
+ failureReason := res.Get("response.failureReason").String()
+ resp.Diagnostics.AddWarning("Device Unreachability Warning", fmt.Sprintf("Device unreachability detected (error code: %s, reason %s).", errorCode, failureReason))
+ } else {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to configure object (%s), got error: %s, %s", "POST", err, res.String()))
+ return
+ }
}
params = ""
params += "?networkDeviceId=" + url.QueryEscape(plan.NetworkDeviceId.ValueString()) + "&fabricId=" + url.QueryEscape(plan.FabricId.ValueString())
@@ -207,8 +213,6 @@ func (r *FabricL3HandoffIPTransitResource) Create(ctx context.Context, req resou
resp.Diagnostics.Append(diags...)
}
-// End of section. //template:end create
-
// Section below is generated&owned by "gen/generator.go". //template:begin read
func (r *FabricL3HandoffIPTransitResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
var state FabricL3HandoffIPTransit
diff --git a/internal/provider/resource_catalystcenter_fabric_provision_device.go b/internal/provider/resource_catalystcenter_fabric_provision_device.go
index f9384d1f..3ad646bc 100644
--- a/internal/provider/resource_catalystcenter_fabric_provision_device.go
+++ b/internal/provider/resource_catalystcenter_fabric_provision_device.go
@@ -113,7 +113,7 @@ func (r *FabricProvisionDeviceResource) Create(ctx context.Context, req resource
body := plan.toBody(ctx, FabricProvisionDevice{})
params := ""
- res, err := r.client.Post(plan.getPath()+params, body, func(r *cc.Req) { r.MaxAsyncWaitTime = 300 })
+ res, err := r.client.Post(plan.getPath()+params, body)
if err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to configure object (%s), got error: %s, %s", "POST", err, res.String()))
return
@@ -195,7 +195,7 @@ func (r *FabricProvisionDeviceResource) Update(ctx context.Context, req resource
body := plan.toBody(ctx, state)
params := ""
- res, err := r.client.Put(plan.getPath()+params, body, func(r *cc.Req) { r.MaxAsyncWaitTime = 300 })
+ res, err := r.client.Put(plan.getPath()+params, body)
if err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to configure object (PUT), got error: %s, %s", err, res.String()))
return
diff --git a/internal/provider/resource_catalystcenter_template_version.go b/internal/provider/resource_catalystcenter_template_version.go
index 529df3e2..634ce453 100644
--- a/internal/provider/resource_catalystcenter_template_version.go
+++ b/internal/provider/resource_catalystcenter_template_version.go
@@ -70,10 +70,7 @@ func (r *TemplateVersionResource) Schema(ctx context.Context, req resource.Schem
},
"template_id": schema.StringAttribute{
MarkdownDescription: helpers.NewAttributeDescription("UUID of template").String,
- Required: true,
- PlanModifiers: []planmodifier.String{
- stringplanmodifier.RequiresReplace(),
- },
+ Optional: true,
},
"comments": schema.StringAttribute{
MarkdownDescription: helpers.NewAttributeDescription("Template version comments").String,
@@ -96,7 +93,6 @@ func (r *TemplateVersionResource) Configure(_ context.Context, req resource.Conf
// End of section. //template:end model
-// Section below is generated&owned by "gen/generator.go". //template:begin create
func (r *TemplateVersionResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
var plan TemplateVersion
@@ -118,7 +114,12 @@ func (r *TemplateVersionResource) Create(ctx context.Context, req resource.Creat
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to configure object (%s), got error: %s, %s", "POST", err, res.String()))
return
}
- plan.Id = types.StringValue(fmt.Sprint(plan.TemplateId.ValueString()))
+ res, err = r.client.Get(plan.getPath() + "/" + url.QueryEscape(plan.TemplateId.ValueString()))
+ if err != nil {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to retrieve object (GET), got error: %s, %s", err, res.String()))
+ return
+ }
+ plan.Id = types.StringValue(res.Get("0.versionsInfo.#(versionComment==\"" + plan.Comments.ValueString() + "\").id").String())
tflog.Debug(ctx, fmt.Sprintf("%s: Create finished successfully", plan.Id.ValueString()))
@@ -126,9 +127,6 @@ func (r *TemplateVersionResource) Create(ctx context.Context, req resource.Creat
resp.Diagnostics.Append(diags...)
}
-// End of section. //template:end create
-
-// Section below is generated&owned by "gen/generator.go". //template:begin read
func (r *TemplateVersionResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
var state TemplateVersion
@@ -142,7 +140,7 @@ func (r *TemplateVersionResource) Read(ctx context.Context, req resource.ReadReq
tflog.Debug(ctx, fmt.Sprintf("%s: Beginning Read", state.Id.String()))
params := ""
- params += "/" + url.QueryEscape(state.Id.ValueString())
+ params += "/" + url.QueryEscape(state.TemplateId.ValueString())
res, err := r.client.Get(state.getPath() + params)
if err != nil && strings.Contains(err.Error(), "StatusCode 404") {
resp.State.RemoveResource(ctx)
@@ -165,8 +163,6 @@ func (r *TemplateVersionResource) Read(ctx context.Context, req resource.ReadReq
resp.Diagnostics.Append(diags...)
}
-// End of section. //template:end read
-
// Section below is generated&owned by "gen/generator.go". //template:begin update
func (r *TemplateVersionResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
var plan, state TemplateVersion
@@ -188,7 +184,7 @@ func (r *TemplateVersionResource) Update(ctx context.Context, req resource.Updat
body := plan.toBody(ctx, state)
params := ""
- res, err := r.client.Put(plan.getPath()+"/"+url.QueryEscape(plan.Id.ValueString())+params, body)
+ res, err := r.client.Put(plan.getPath()+params, body)
if err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to configure object (PUT), got error: %s, %s", err, res.String()))
return
@@ -234,7 +230,6 @@ func (r *TemplateVersionResource) ImportState(ctx context.Context, req resource.
return
}
resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("template_id"), idParts[0])...)
- resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("id"), idParts[0])...)
}
// End of section. //template:end import
diff --git a/internal/provider/resource_catalystcenter_template_version_test.go b/internal/provider/resource_catalystcenter_template_version_test.go
index 31273008..43c15626 100644
--- a/internal/provider/resource_catalystcenter_template_version_test.go
+++ b/internal/provider/resource_catalystcenter_template_version_test.go
@@ -41,10 +41,6 @@ func TestAccCcTemplateVersion(t *testing.T) {
Config: testAccCcTemplateVersionPrerequisitesConfig + testAccCcTemplateVersionConfig_all(),
Check: resource.ComposeTestCheckFunc(checks...),
})
- steps = append(steps, resource.TestStep{
- ResourceName: "catalystcenter_template_version.test",
- ImportState: true,
- })
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
diff --git a/internal/provider/resource_catalystcenter_wireless_device_provision.go b/internal/provider/resource_catalystcenter_wireless_device_provision.go
index 80ad5092..53bcb205 100644
--- a/internal/provider/resource_catalystcenter_wireless_device_provision.go
+++ b/internal/provider/resource_catalystcenter_wireless_device_provision.go
@@ -154,7 +154,7 @@ func (r *WirelessDeviceProvisionResource) Create(ctx context.Context, req resour
body := plan.toBody(ctx, WirelessDeviceProvision{})
params := ""
- res, err := r.client.Post(plan.getPath()+params, body, func(r *cc.Req) { r.MaxAsyncWaitTime = 300 })
+ res, err := r.client.Post(plan.getPath()+params, body)
if err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to configure object (%s), got error: %s, %s", "POST", err, res.String()))
return
@@ -211,7 +211,7 @@ func (r *WirelessDeviceProvisionResource) Update(ctx context.Context, req resour
body := plan.toBody(ctx, state)
params := ""
- res, err := r.client.Put(plan.getPath()+params, body, func(r *cc.Req) { r.MaxAsyncWaitTime = 300 })
+ res, err := r.client.Put(plan.getPath()+params, body)
if err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to configure object (PUT), got error: %s, %s", err, res.String()))
return
diff --git a/templates/guides/changelog.md.tmpl b/templates/guides/changelog.md.tmpl
index fc8f69ca..945044a5 100644
--- a/templates/guides/changelog.md.tmpl
+++ b/templates/guides/changelog.md.tmpl
@@ -7,6 +7,14 @@ description: |-
# Changelog
+## 0.1.16 (unreleased)
+
+- Add Device Unreachability Warning to `catalystcenter_fabric_l3_handoff_ip_transit` resource, [link](https://github.com/CiscoDevNet/terraform-provider-catalystcenter/issues/150)
+- Add `catalystcenter_fabric_l2_virtual_network` resource and data source
+- Remove `max_async_wait_time` attribute and use timeout from `CC_MAX_TIMEOUT`
+- Modify `catalystcenter_deploy_template` resource to support deploying composite templates
+- Modify `catalystcenter_template_version` resource to use versioned template id as `id` and remove data_source
+
## 0.1.15
- Fix issue in `catalystcenter_fabric_l3_handoff_ip_transit` resource, [link](https://github.com/CiscoDevNet/terraform-provider-catalystcenter/issues/146)