diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9ae6c484e..1a35d2945 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,7 @@
- Add `ip_ssh_bulk_mode` and `ip_ssh_bulk_mode_window_size` attributes to `iosxe_system` resource and data source
- Add `set_ip_next_hop_unchanged` attribute to `iosxe_route_map` resource and data source
- Enhance `set_communities` attribute documentation in `iosxe_route_map` to clarify support for well-known BGP community values (internet, local-AS, no-advertise, no-export, gshut)
+- Add `iosxe_bgp_template_peer_policy` resource
## 0.9.3
@@ -21,7 +22,7 @@
- Add `passive_interface_disable_*` attributes to `iosxe_ospf` and `iosxe_ospf_vrf` resources and data sources
- Fix issue with destroying `iosxe_interface_ethernet` resources
- Change route target attributes of `iosxe_vrf` from type "List" to "Set"
-- Add `role_based_enforcement` attributes to `iosxe_cts`
+- Add `role_based_enforcement` attributes to `iosxe_cts`
- Add `tftp_source_interface_*` attributes to `iosxe_system` resource and data source
- Add `hash` attribute to `iosxe_crypto_pki` resource and data source
- Add `snooping_information_option`, `snooping_information_option_allow_untrusted` and `snooping_information_option_format_remote_id_string` attributes to `iosxe_dhcp` resource and data source
@@ -66,7 +67,7 @@
- Add `level`, `list_name`, `action_type`, `broadcast`, `group_broadcast`, `group_logger`, `group1_group`, `group2_group`, `group3_group`, `group4_group`, `name`, `default`, `none`, `start_stop_broadcast`, `start_stop_logger`, `start_stop_group1`, `start_stop_group2`, `start_stop_group3`, `start_stop_group4`, `stop_only_broadcast`, `stop_only_logger`, `stop_only_group1`, `stop_only_group2`, `stop_only_group3`, `stop_only_group4`, `wait_start_broadcast`, `wait_start_logger`, `wait_start_group1`, `wait_start_group2`, `wait_start_group3`, `wait_start_group4`, `name`, `none`, `start_stop_broadcast`, `start_stop_logger`, `start_stop_group1`, `start_stop_group2`, `start_stop_group3`, `start_stop_group4`, `stop_only_broadcast`, `stop_only_logger`, `stop_only_group1`, `stop_only_group2`, `stop_only_group3`, `stop_only_group4`, `wait_start_broadcast`, `wait_start_logger`, `wait_start_group1`, `wait_start_group2`, `wait_start_group3`, and `wait_start_group4` attributes to `iosxe_aaa_accounting` resource and data source
- Add `enable_default_group1_cache`, `enable_default_group1_enable`, `enable_default_group1_group`, `enable_default_group1_line`, `enable_default_group1_none`, `enable_default_group2_cache`, `enable_default_group2_enable`, `enable_default_group2_group`, `enable_default_group2_line`, `enable_default_group2_none`, `enable_default_group3_cache`, `enable_default_group3_enable`, `enable_default_group3_group`, `enable_default_group3_line`, `enable_default_group3_none`, `enable_default_group4_cache`, `enable_default_group4_enable`, `enable_default_group4_group`, `enable_default_group4_line`, and `enable_default_group4_none` attributes to `iosxe_aaa_authentication` resource and data source
- Add `level`, `list_name`, `a1_group`, `a1_local`, `a1_if_authenticated`, `a1_none`, `a1_radius`, `a1_tacacs`, `a2_group`, `a2_local`, `a2_if_authenticated`, `a2_none`, `a2_radius`, `a2_tacacs`, `a3_group`, `a3_local`, `a3_if_authenticated`, `a3_none`, `a3_radius`, `a3_tacacs`, `a4_group`, `a4_local`, `a4_if_authenticated`, `a4_none`, `a4_radius`, `a4_tacacs`, `name`, `group1_cache`, `group1_group`, `group1_radius`, and `group1_tacacs` attributes to `iosxe_aaa_authorization` resource and data source
-- Add `vrf`, `local_authentication_type`, `local_authorization`, and `local_auth_max_fail_attempts` attributes to `iosxe_aaa` resrouce and data source
+- Add `vrf`, `local_authentication_type`, `local_authorization`, and `local_auth_max_fail_attempts` attributes to `iosxe_aaa` resrouce and data source
- Add `icmp_named_msg_type`, `destination_port_equal_2`, `destination_port_equal_3`, `destination_port_equal_4`, `destination_port_equal_5`, `destination_port_equal_6`, `destination_port_equal_7`, `destination_port_equal_8`, `destination_port_equal_9`, `destination_port_equal_10`, `icmp_msg_type`, and `icmp_msg_code` attributes to `iosxe_access_list_extended` resource and data source
- Add `iosxe_access_list_role_based` resource and data source
- Add `filter_lists_cdp` attribute to `iosxe_device_sensor` resource and data source
diff --git a/docs/data-sources/bgp_template_peer_policy.md b/docs/data-sources/bgp_template_peer_policy.md
new file mode 100644
index 000000000..71ba2d6d2
--- /dev/null
+++ b/docs/data-sources/bgp_template_peer_policy.md
@@ -0,0 +1,49 @@
+---
+# generated by https://github.com/hashicorp/terraform-plugin-docs
+page_title: "iosxe_bgp_template_peer_policy Data Source - terraform-provider-iosxe"
+subcategory: "BGP"
+description: |-
+ This data source can read the BGP Template Peer Policy configuration.
+---
+
+# iosxe_bgp_template_peer_policy (Data Source)
+
+This data source can read the BGP Template Peer Policy configuration.
+
+## Example Usage
+
+```terraform
+data "iosxe_bgp_template_peer_policy" "example" {
+ asn = "65000"
+ name = "PEERPOLICY_1"
+}
+```
+
+
+## Schema
+
+### Required
+
+- `asn` (String)
+- `name` (String)
+
+### Optional
+
+- `device` (String) A device name from the provider configuration.
+
+### Read-Only
+
+- `allowas_in_as_number` (Number)
+- `as_override_split_horizon` (Boolean)
+- `id` (String) The path of the retrieved object.
+- `route_maps` (Attributes List) Apply route map to neighbor (see [below for nested schema](#nestedatt--route_maps))
+- `route_reflector_client` (Boolean) Configure a neighbor as Route Reflector client
+- `send_community` (String)
+
+
+### Nested Schema for `route_maps`
+
+Read-Only:
+
+- `in_out` (String)
+- `route_map_name` (String)
diff --git a/docs/guides/changelog.md b/docs/guides/changelog.md
index 7fa3bd4df..517dfc963 100644
--- a/docs/guides/changelog.md
+++ b/docs/guides/changelog.md
@@ -16,6 +16,7 @@ description: |-
- Add `ip_ssh_bulk_mode` and `ip_ssh_bulk_mode_window_size` attributes to `iosxe_system` resource and data source
- Add `set_ip_next_hop_unchanged` attribute to `iosxe_route_map` resource and data source
- Enhance `set_communities` attribute documentation in `iosxe_route_map` to clarify support for well-known BGP community values (internet, local-AS, no-advertise, no-export, gshut)
+- Add `iosxe_bgp_template_peer_policy` resource
## 0.9.3
@@ -30,7 +31,7 @@ description: |-
- Add `passive_interface_disable_*` attributes to `iosxe_ospf` and `iosxe_ospf_vrf` resources and data sources
- Fix issue with destroying `iosxe_interface_ethernet` resources
- Change route target attributes of `iosxe_vrf` from type "List" to "Set"
-- Add `role_based_enforcement` attributes to `iosxe_cts`
+- Add `role_based_enforcement` attributes to `iosxe_cts`
- Add `tftp_source_interface_*` attributes to `iosxe_system` resource and data source
- Add `hash` attribute to `iosxe_crypto_pki` resource and data source
- Add `snooping_information_option`, `snooping_information_option_allow_untrusted` and `snooping_information_option_format_remote_id_string` attributes to `iosxe_dhcp` resource and data source
@@ -75,7 +76,7 @@ description: |-
- Add `level`, `list_name`, `action_type`, `broadcast`, `group_broadcast`, `group_logger`, `group1_group`, `group2_group`, `group3_group`, `group4_group`, `name`, `default`, `none`, `start_stop_broadcast`, `start_stop_logger`, `start_stop_group1`, `start_stop_group2`, `start_stop_group3`, `start_stop_group4`, `stop_only_broadcast`, `stop_only_logger`, `stop_only_group1`, `stop_only_group2`, `stop_only_group3`, `stop_only_group4`, `wait_start_broadcast`, `wait_start_logger`, `wait_start_group1`, `wait_start_group2`, `wait_start_group3`, `wait_start_group4`, `name`, `none`, `start_stop_broadcast`, `start_stop_logger`, `start_stop_group1`, `start_stop_group2`, `start_stop_group3`, `start_stop_group4`, `stop_only_broadcast`, `stop_only_logger`, `stop_only_group1`, `stop_only_group2`, `stop_only_group3`, `stop_only_group4`, `wait_start_broadcast`, `wait_start_logger`, `wait_start_group1`, `wait_start_group2`, `wait_start_group3`, and `wait_start_group4` attributes to `iosxe_aaa_accounting` resource and data source
- Add `enable_default_group1_cache`, `enable_default_group1_enable`, `enable_default_group1_group`, `enable_default_group1_line`, `enable_default_group1_none`, `enable_default_group2_cache`, `enable_default_group2_enable`, `enable_default_group2_group`, `enable_default_group2_line`, `enable_default_group2_none`, `enable_default_group3_cache`, `enable_default_group3_enable`, `enable_default_group3_group`, `enable_default_group3_line`, `enable_default_group3_none`, `enable_default_group4_cache`, `enable_default_group4_enable`, `enable_default_group4_group`, `enable_default_group4_line`, and `enable_default_group4_none` attributes to `iosxe_aaa_authentication` resource and data source
- Add `level`, `list_name`, `a1_group`, `a1_local`, `a1_if_authenticated`, `a1_none`, `a1_radius`, `a1_tacacs`, `a2_group`, `a2_local`, `a2_if_authenticated`, `a2_none`, `a2_radius`, `a2_tacacs`, `a3_group`, `a3_local`, `a3_if_authenticated`, `a3_none`, `a3_radius`, `a3_tacacs`, `a4_group`, `a4_local`, `a4_if_authenticated`, `a4_none`, `a4_radius`, `a4_tacacs`, `name`, `group1_cache`, `group1_group`, `group1_radius`, and `group1_tacacs` attributes to `iosxe_aaa_authorization` resource and data source
-- Add `vrf`, `local_authentication_type`, `local_authorization`, and `local_auth_max_fail_attempts` attributes to `iosxe_aaa` resrouce and data source
+- Add `vrf`, `local_authentication_type`, `local_authorization`, and `local_auth_max_fail_attempts` attributes to `iosxe_aaa` resrouce and data source
- Add `icmp_named_msg_type`, `destination_port_equal_2`, `destination_port_equal_3`, `destination_port_equal_4`, `destination_port_equal_5`, `destination_port_equal_6`, `destination_port_equal_7`, `destination_port_equal_8`, `destination_port_equal_9`, `destination_port_equal_10`, `icmp_msg_type`, and `icmp_msg_code` attributes to `iosxe_access_list_extended` resource and data source
- Add `iosxe_access_list_role_based` resource and data source
- Add `filter_lists_cdp` attribute to `iosxe_device_sensor` resource and data source
diff --git a/docs/resources/bgp_template_peer_policy.md b/docs/resources/bgp_template_peer_policy.md
new file mode 100644
index 000000000..113870420
--- /dev/null
+++ b/docs/resources/bgp_template_peer_policy.md
@@ -0,0 +1,71 @@
+---
+# generated by https://github.com/hashicorp/terraform-plugin-docs
+page_title: "iosxe_bgp_template_peer_policy Resource - terraform-provider-iosxe"
+subcategory: "BGP"
+description: |-
+ This resource can manage the BGP Template Peer Policy configuration.
+---
+
+# iosxe_bgp_template_peer_policy (Resource)
+
+This resource can manage the BGP Template Peer Policy configuration.
+
+## Example Usage
+
+```terraform
+resource "iosxe_bgp_template_peer_policy" "example" {
+ asn = "65000"
+ name = "PEERPOLICY_1"
+ route_reflector_client = true
+ send_community = "both"
+ route_maps = [
+ {
+ in_out = "in"
+ route_map_name = "ROUTEMAP_1"
+ }
+ ]
+ allowas_in_as_number = 2
+ as_override_split_horizon = true
+}
+```
+
+
+## Schema
+
+### Required
+
+- `asn` (String)
+- `name` (String)
+
+### Optional
+
+- `allowas_in_as_number` (Number) - Range: `1`-`10`
+- `as_override_split_horizon` (Boolean)
+- `delete_mode` (String) Configure behavior when deleting/destroying the resource. Either delete the entire object (YANG container) being managed, or only delete the individual resource attributes configured explicitly and leave everything else as-is. Default value is `all`.
+ - Choices: `all`, `attributes`
+- `device` (String) A device name from the provider configuration.
+- `route_maps` (Attributes List) Apply route map to neighbor (see [below for nested schema](#nestedatt--route_maps))
+- `route_reflector_client` (Boolean) Configure a neighbor as Route Reflector client
+- `send_community` (String) - Choices: `both`, `extended`, `standard`
+
+### Read-Only
+
+- `id` (String) The path of the object.
+
+
+### Nested Schema for `route_maps`
+
+Required:
+
+- `in_out` (String) - Choices: `in`, `out`
+- `route_map_name` (String)
+
+## Import
+
+Import is supported using the following syntax:
+
+The [`terraform import` command](https://developer.hashicorp.com/terraform/cli/commands/import) can be used, for example:
+
+```shell
+terraform import iosxe_bgp_template_peer_policy.example ","
+```
diff --git a/examples/data-sources/iosxe_bgp_template_peer_policy/data-source.tf b/examples/data-sources/iosxe_bgp_template_peer_policy/data-source.tf
new file mode 100644
index 000000000..ee67e9d5e
--- /dev/null
+++ b/examples/data-sources/iosxe_bgp_template_peer_policy/data-source.tf
@@ -0,0 +1,4 @@
+data "iosxe_bgp_template_peer_policy" "example" {
+ asn = "65000"
+ name = "PEERPOLICY_1"
+}
diff --git a/examples/resources/iosxe_bgp_template_peer_policy/import.sh b/examples/resources/iosxe_bgp_template_peer_policy/import.sh
new file mode 100644
index 000000000..b2c3190da
--- /dev/null
+++ b/examples/resources/iosxe_bgp_template_peer_policy/import.sh
@@ -0,0 +1 @@
+terraform import iosxe_bgp_template_peer_policy.example ","
diff --git a/examples/resources/iosxe_bgp_template_peer_policy/resource.tf b/examples/resources/iosxe_bgp_template_peer_policy/resource.tf
new file mode 100644
index 000000000..180fc1e3d
--- /dev/null
+++ b/examples/resources/iosxe_bgp_template_peer_policy/resource.tf
@@ -0,0 +1,14 @@
+resource "iosxe_bgp_template_peer_policy" "example" {
+ asn = "65000"
+ name = "PEERPOLICY_1"
+ route_reflector_client = true
+ send_community = "both"
+ route_maps = [
+ {
+ in_out = "in"
+ route_map_name = "ROUTEMAP_1"
+ }
+ ]
+ allowas_in_as_number = 2
+ as_override_split_horizon = true
+}
diff --git a/gen/definitions/bgp_template_peer_policy.yaml b/gen/definitions/bgp_template_peer_policy.yaml
new file mode 100644
index 000000000..1857e48c2
--- /dev/null
+++ b/gen/definitions/bgp_template_peer_policy.yaml
@@ -0,0 +1,40 @@
+---
+name: BGP Template Peer Policy
+path: Cisco-IOS-XE-native:native/router/Cisco-IOS-XE-bgp:bgp=%v/template/peer-policy=%v
+doc_category: BGP
+attributes:
+ - yang_name: id
+ tf_name: asn
+ example: 65000
+ - yang_name: name
+ example: PEERPOLICY_1
+ - yang_name: route-reflector-client
+ example: true
+ - yang_name: send-community/send-community-where
+ tf_name: send_community
+ example: both
+ - yang_name: route-map1
+ type: List
+ tf_name: route_maps
+ attributes:
+ - yang_name: inout
+ tf_name: in_out
+ id: true
+ example: in
+ - yang_name: route-map-name
+ example: ROUTEMAP_1
+ - yang_name: allowas-in/as-number
+ tf_name: allowas_in_as_number
+ example: 2
+ - yang_name: as-override/split-horizon
+ tf_name: as_override_split_horizon
+ example: true
+test_prerequisites:
+ - path: Cisco-IOS-XE-native:native/router/Cisco-IOS-XE-bgp:bgp=65000
+ attributes:
+ - name: id
+ value: 65000
+ - path: Cisco-IOS-XE-native:native/route-map=ROUTEMAP_1
+ attributes:
+ - name: name
+ value: ROUTEMAP_1
diff --git a/internal/provider/data_source_iosxe_bgp_template_peer_policy.go b/internal/provider/data_source_iosxe_bgp_template_peer_policy.go
new file mode 100644
index 000000000..6603ad9a0
--- /dev/null
+++ b/internal/provider/data_source_iosxe_bgp_template_peer_policy.go
@@ -0,0 +1,164 @@
+// 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
+
+// Code generated by "gen/generator.go"; DO NOT EDIT.
+
+package provider
+
+// Section below is generated&owned by "gen/generator.go". //template:begin imports
+import (
+ "context"
+ "fmt"
+
+ "github.com/hashicorp/terraform-plugin-framework/datasource"
+ "github.com/hashicorp/terraform-plugin-framework/datasource/schema"
+ "github.com/hashicorp/terraform-plugin-framework/path"
+ "github.com/hashicorp/terraform-plugin-framework/types"
+ "github.com/hashicorp/terraform-plugin-log/tflog"
+)
+
+// 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 = &BGPTemplatePeerPolicyDataSource{}
+ _ datasource.DataSourceWithConfigure = &BGPTemplatePeerPolicyDataSource{}
+)
+
+func NewBGPTemplatePeerPolicyDataSource() datasource.DataSource {
+ return &BGPTemplatePeerPolicyDataSource{}
+}
+
+type BGPTemplatePeerPolicyDataSource struct {
+ data *IosxeProviderData
+}
+
+func (d *BGPTemplatePeerPolicyDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
+ resp.TypeName = req.ProviderTypeName + "_bgp_template_peer_policy"
+}
+
+func (d *BGPTemplatePeerPolicyDataSource) 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 BGP Template Peer Policy configuration.",
+
+ Attributes: map[string]schema.Attribute{
+ "device": schema.StringAttribute{
+ MarkdownDescription: "A device name from the provider configuration.",
+ Optional: true,
+ },
+ "id": schema.StringAttribute{
+ MarkdownDescription: "The path of the retrieved object.",
+ Computed: true,
+ },
+ "asn": schema.StringAttribute{
+ MarkdownDescription: "",
+ Required: true,
+ },
+ "name": schema.StringAttribute{
+ MarkdownDescription: "",
+ Required: true,
+ },
+ "route_reflector_client": schema.BoolAttribute{
+ MarkdownDescription: "Configure a neighbor as Route Reflector client",
+ Computed: true,
+ },
+ "send_community": schema.StringAttribute{
+ MarkdownDescription: "",
+ Computed: true,
+ },
+ "route_maps": schema.ListNestedAttribute{
+ MarkdownDescription: "Apply route map to neighbor",
+ Computed: true,
+ NestedObject: schema.NestedAttributeObject{
+ Attributes: map[string]schema.Attribute{
+ "in_out": schema.StringAttribute{
+ MarkdownDescription: "",
+ Computed: true,
+ },
+ "route_map_name": schema.StringAttribute{
+ MarkdownDescription: "",
+ Computed: true,
+ },
+ },
+ },
+ },
+ "allowas_in_as_number": schema.Int64Attribute{
+ MarkdownDescription: "",
+ Computed: true,
+ },
+ "as_override_split_horizon": schema.BoolAttribute{
+ MarkdownDescription: "",
+ Computed: true,
+ },
+ },
+ }
+}
+
+func (d *BGPTemplatePeerPolicyDataSource) Configure(_ context.Context, req datasource.ConfigureRequest, _ *datasource.ConfigureResponse) {
+ if req.ProviderData == nil {
+ return
+ }
+
+ d.data = req.ProviderData.(*IosxeProviderData)
+}
+
+// End of section. //template:end model
+
+// Section below is generated&owned by "gen/generator.go". //template:begin read
+
+func (d *BGPTemplatePeerPolicyDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
+ var config BGPTemplatePeerPolicyData
+
+ // 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.getPath()))
+
+ device, ok := d.data.Devices[config.Device.ValueString()]
+ if !ok {
+ resp.Diagnostics.AddAttributeError(path.Root("device"), "Invalid device", fmt.Sprintf("Device '%s' does not exist in provider configuration.", config.Device.ValueString()))
+ return
+ }
+
+ res, err := device.Client.GetData(config.getPath())
+ if res.StatusCode == 404 {
+ config = BGPTemplatePeerPolicyData{Device: config.Device}
+ } else {
+ if err != nil {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to retrieve object (%s), got error: %s", config.getPath(), err))
+ return
+ }
+
+ config.fromBody(ctx, res.Res)
+ }
+
+ config.Id = types.StringValue(config.getPath())
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Read finished successfully", config.getPath()))
+
+ diags = resp.State.Set(ctx, &config)
+ resp.Diagnostics.Append(diags...)
+}
+
+// End of section. //template:end read
diff --git a/internal/provider/data_source_iosxe_bgp_template_peer_policy_test.go b/internal/provider/data_source_iosxe_bgp_template_peer_policy_test.go
new file mode 100644
index 000000000..baf664758
--- /dev/null
+++ b/internal/provider/data_source_iosxe_bgp_template_peer_policy_test.go
@@ -0,0 +1,103 @@
+// 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
+
+// Code generated by "gen/generator.go"; DO NOT EDIT.
+
+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 testAccDataSource
+
+func TestAccDataSourceIosxeBGPTemplatePeerPolicy(t *testing.T) {
+ var checks []resource.TestCheckFunc
+ checks = append(checks, resource.TestCheckResourceAttr("data.iosxe_bgp_template_peer_policy.test", "route_reflector_client", "true"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.iosxe_bgp_template_peer_policy.test", "send_community", "both"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.iosxe_bgp_template_peer_policy.test", "route_maps.0.in_out", "in"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.iosxe_bgp_template_peer_policy.test", "route_maps.0.route_map_name", "ROUTEMAP_1"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.iosxe_bgp_template_peer_policy.test", "allowas_in_as_number", "2"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.iosxe_bgp_template_peer_policy.test", "as_override_split_horizon", "true"))
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { testAccPreCheck(t) },
+ ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
+ Steps: []resource.TestStep{
+ {
+ Config: testAccDataSourceIosxeBGPTemplatePeerPolicyPrerequisitesConfig + testAccDataSourceIosxeBGPTemplatePeerPolicyConfig(),
+ Check: resource.ComposeTestCheckFunc(checks...),
+ },
+ },
+ })
+}
+
+// End of section. //template:end testAccDataSource
+
+// Section below is generated&owned by "gen/generator.go". //template:begin testPrerequisites
+const testAccDataSourceIosxeBGPTemplatePeerPolicyPrerequisitesConfig = `
+resource "iosxe_restconf" "PreReq0" {
+ path = "Cisco-IOS-XE-native:native/router/Cisco-IOS-XE-bgp:bgp=65000"
+ attributes = {
+ "id" = "65000"
+ }
+}
+
+resource "iosxe_restconf" "PreReq1" {
+ path = "Cisco-IOS-XE-native:native/route-map=ROUTEMAP_1"
+ attributes = {
+ "name" = "ROUTEMAP_1"
+ }
+}
+
+`
+
+// End of section. //template:end testPrerequisites
+
+// Section below is generated&owned by "gen/generator.go". //template:begin testAccDataSourceConfig
+
+func testAccDataSourceIosxeBGPTemplatePeerPolicyConfig() string {
+ config := `resource "iosxe_bgp_template_peer_policy" "test" {` + "\n"
+ config += ` delete_mode = "attributes"` + "\n"
+ config += ` asn = "65000"` + "\n"
+ config += ` name = "PEERPOLICY_1"` + "\n"
+ config += ` route_reflector_client = true` + "\n"
+ config += ` send_community = "both"` + "\n"
+ config += ` route_maps = [{` + "\n"
+ config += ` in_out = "in"` + "\n"
+ config += ` route_map_name = "ROUTEMAP_1"` + "\n"
+ config += ` }]` + "\n"
+ config += ` allowas_in_as_number = 2` + "\n"
+ config += ` as_override_split_horizon = true` + "\n"
+ config += ` depends_on = [iosxe_restconf.PreReq0, iosxe_restconf.PreReq1, ]` + "\n"
+ config += `}` + "\n"
+
+ config += `
+ data "iosxe_bgp_template_peer_policy" "test" {
+ asn = "65000"
+ name = "PEERPOLICY_1"
+ depends_on = [iosxe_bgp_template_peer_policy.test]
+ }
+ `
+ return config
+}
+
+// End of section. //template:end testAccDataSourceConfig
diff --git a/internal/provider/model_iosxe_bgp_template_peer_policy.go b/internal/provider/model_iosxe_bgp_template_peer_policy.go
new file mode 100644
index 000000000..e4a8a6bbb
--- /dev/null
+++ b/internal/provider/model_iosxe_bgp_template_peer_policy.go
@@ -0,0 +1,386 @@
+// 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
+
+// Code generated by "gen/generator.go"; DO NOT EDIT.
+
+package provider
+
+// Section below is generated&owned by "gen/generator.go". //template:begin imports
+import (
+ "context"
+ "fmt"
+ "net/url"
+ "reflect"
+ "regexp"
+ "strconv"
+ "strings"
+
+ "github.com/CiscoDevNet/terraform-provider-iosxe/internal/provider/helpers"
+ "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 BGPTemplatePeerPolicy struct {
+ Device types.String `tfsdk:"device"`
+ Id types.String `tfsdk:"id"`
+ DeleteMode types.String `tfsdk:"delete_mode"`
+ Asn types.String `tfsdk:"asn"`
+ Name types.String `tfsdk:"name"`
+ RouteReflectorClient types.Bool `tfsdk:"route_reflector_client"`
+ SendCommunity types.String `tfsdk:"send_community"`
+ RouteMaps []BGPTemplatePeerPolicyRouteMaps `tfsdk:"route_maps"`
+ AllowasInAsNumber types.Int64 `tfsdk:"allowas_in_as_number"`
+ AsOverrideSplitHorizon types.Bool `tfsdk:"as_override_split_horizon"`
+}
+
+type BGPTemplatePeerPolicyData struct {
+ Device types.String `tfsdk:"device"`
+ Id types.String `tfsdk:"id"`
+ Asn types.String `tfsdk:"asn"`
+ Name types.String `tfsdk:"name"`
+ RouteReflectorClient types.Bool `tfsdk:"route_reflector_client"`
+ SendCommunity types.String `tfsdk:"send_community"`
+ RouteMaps []BGPTemplatePeerPolicyRouteMaps `tfsdk:"route_maps"`
+ AllowasInAsNumber types.Int64 `tfsdk:"allowas_in_as_number"`
+ AsOverrideSplitHorizon types.Bool `tfsdk:"as_override_split_horizon"`
+}
+type BGPTemplatePeerPolicyRouteMaps struct {
+ InOut types.String `tfsdk:"in_out"`
+ RouteMapName types.String `tfsdk:"route_map_name"`
+}
+
+// End of section. //template:end types
+
+// Section below is generated&owned by "gen/generator.go". //template:begin getPath
+
+func (data BGPTemplatePeerPolicy) getPath() string {
+ return fmt.Sprintf("Cisco-IOS-XE-native:native/router/Cisco-IOS-XE-bgp:bgp=%v/template/peer-policy=%v", url.QueryEscape(fmt.Sprintf("%v", data.Asn.ValueString())), url.QueryEscape(fmt.Sprintf("%v", data.Name.ValueString())))
+}
+
+func (data BGPTemplatePeerPolicyData) getPath() string {
+ return fmt.Sprintf("Cisco-IOS-XE-native:native/router/Cisco-IOS-XE-bgp:bgp=%v/template/peer-policy=%v", url.QueryEscape(fmt.Sprintf("%v", data.Asn.ValueString())), url.QueryEscape(fmt.Sprintf("%v", data.Name.ValueString())))
+}
+
+// if last path element has a key -> remove it
+func (data BGPTemplatePeerPolicy) getPathShort() string {
+ path := data.getPath()
+ re := regexp.MustCompile(`(.*)=[^\/]*$`)
+ matches := re.FindStringSubmatch(path)
+ if len(matches) <= 1 {
+ return path
+ }
+ return matches[1]
+}
+
+// End of section. //template:end getPath
+
+// Section below is generated&owned by "gen/generator.go". //template:begin toBody
+
+func (data BGPTemplatePeerPolicy) toBody(ctx context.Context) string {
+ body := `{"` + helpers.LastElement(data.getPath()) + `":{}}`
+ if !data.Name.IsNull() && !data.Name.IsUnknown() {
+ body, _ = sjson.Set(body, helpers.LastElement(data.getPath())+"."+"name", data.Name.ValueString())
+ }
+ if !data.RouteReflectorClient.IsNull() && !data.RouteReflectorClient.IsUnknown() {
+ if data.RouteReflectorClient.ValueBool() {
+ body, _ = sjson.Set(body, helpers.LastElement(data.getPath())+"."+"route-reflector-client", map[string]string{})
+ }
+ }
+ if !data.SendCommunity.IsNull() && !data.SendCommunity.IsUnknown() {
+ body, _ = sjson.Set(body, helpers.LastElement(data.getPath())+"."+"send-community.send-community-where", data.SendCommunity.ValueString())
+ }
+ if !data.AllowasInAsNumber.IsNull() && !data.AllowasInAsNumber.IsUnknown() {
+ body, _ = sjson.Set(body, helpers.LastElement(data.getPath())+"."+"allowas-in.as-number", strconv.FormatInt(data.AllowasInAsNumber.ValueInt64(), 10))
+ }
+ if !data.AsOverrideSplitHorizon.IsNull() && !data.AsOverrideSplitHorizon.IsUnknown() {
+ if data.AsOverrideSplitHorizon.ValueBool() {
+ body, _ = sjson.Set(body, helpers.LastElement(data.getPath())+"."+"as-override.split-horizon", map[string]string{})
+ }
+ }
+ if len(data.RouteMaps) > 0 {
+ body, _ = sjson.Set(body, helpers.LastElement(data.getPath())+"."+"route-map1", []interface{}{})
+ for index, item := range data.RouteMaps {
+ if !item.InOut.IsNull() && !item.InOut.IsUnknown() {
+ body, _ = sjson.Set(body, helpers.LastElement(data.getPath())+"."+"route-map1"+"."+strconv.Itoa(index)+"."+"inout", item.InOut.ValueString())
+ }
+ if !item.RouteMapName.IsNull() && !item.RouteMapName.IsUnknown() {
+ body, _ = sjson.Set(body, helpers.LastElement(data.getPath())+"."+"route-map1"+"."+strconv.Itoa(index)+"."+"route-map-name", item.RouteMapName.ValueString())
+ }
+ }
+ }
+ return body
+}
+
+// End of section. //template:end toBody
+
+// Section below is generated&owned by "gen/generator.go". //template:begin updateFromBody
+
+func (data *BGPTemplatePeerPolicy) updateFromBody(ctx context.Context, res gjson.Result) {
+ prefix := helpers.LastElement(data.getPath()) + "."
+ if res.Get(helpers.LastElement(data.getPath())).IsArray() {
+ prefix += "0."
+ }
+ if value := res.Get(prefix + "name"); value.Exists() && !data.Name.IsNull() {
+ data.Name = types.StringValue(value.String())
+ } else {
+ data.Name = types.StringNull()
+ }
+ if value := res.Get(prefix + "route-reflector-client"); !data.RouteReflectorClient.IsNull() {
+ if value.Exists() {
+ data.RouteReflectorClient = types.BoolValue(true)
+ } else {
+ data.RouteReflectorClient = types.BoolValue(false)
+ }
+ } else {
+ data.RouteReflectorClient = types.BoolNull()
+ }
+ if value := res.Get(prefix + "send-community.send-community-where"); value.Exists() && !data.SendCommunity.IsNull() {
+ data.SendCommunity = types.StringValue(value.String())
+ } else {
+ data.SendCommunity = types.StringNull()
+ }
+ for i := range data.RouteMaps {
+ keys := [...]string{"inout"}
+ keyValues := [...]string{data.RouteMaps[i].InOut.ValueString()}
+
+ var r gjson.Result
+ res.Get(prefix + "route-map1").ForEach(
+ func(_, v gjson.Result) bool {
+ found := false
+ for ik := range keys {
+ if v.Get(keys[ik]).String() == keyValues[ik] {
+ found = true
+ continue
+ }
+ found = false
+ break
+ }
+ if found {
+ r = v
+ return false
+ }
+ return true
+ },
+ )
+ if value := r.Get("inout"); value.Exists() && !data.RouteMaps[i].InOut.IsNull() {
+ data.RouteMaps[i].InOut = types.StringValue(value.String())
+ } else {
+ data.RouteMaps[i].InOut = types.StringNull()
+ }
+ if value := r.Get("route-map-name"); value.Exists() && !data.RouteMaps[i].RouteMapName.IsNull() {
+ data.RouteMaps[i].RouteMapName = types.StringValue(value.String())
+ } else {
+ data.RouteMaps[i].RouteMapName = types.StringNull()
+ }
+ }
+ if value := res.Get(prefix + "allowas-in.as-number"); value.Exists() && !data.AllowasInAsNumber.IsNull() {
+ data.AllowasInAsNumber = types.Int64Value(value.Int())
+ } else {
+ data.AllowasInAsNumber = types.Int64Null()
+ }
+ if value := res.Get(prefix + "as-override.split-horizon"); !data.AsOverrideSplitHorizon.IsNull() {
+ if value.Exists() {
+ data.AsOverrideSplitHorizon = types.BoolValue(true)
+ } else {
+ data.AsOverrideSplitHorizon = types.BoolValue(false)
+ }
+ } else {
+ data.AsOverrideSplitHorizon = types.BoolNull()
+ }
+}
+
+// End of section. //template:end updateFromBody
+
+// Section below is generated&owned by "gen/generator.go". //template:begin fromBody
+
+func (data *BGPTemplatePeerPolicy) fromBody(ctx context.Context, res gjson.Result) {
+ prefix := helpers.LastElement(data.getPath()) + "."
+ if res.Get(helpers.LastElement(data.getPath())).IsArray() {
+ prefix += "0."
+ }
+ if value := res.Get(prefix + "route-reflector-client"); value.Exists() {
+ data.RouteReflectorClient = types.BoolValue(true)
+ } else {
+ data.RouteReflectorClient = types.BoolValue(false)
+ }
+ if value := res.Get(prefix + "send-community.send-community-where"); value.Exists() {
+ data.SendCommunity = types.StringValue(value.String())
+ }
+ if value := res.Get(prefix + "route-map1"); value.Exists() {
+ data.RouteMaps = make([]BGPTemplatePeerPolicyRouteMaps, 0)
+ value.ForEach(func(k, v gjson.Result) bool {
+ item := BGPTemplatePeerPolicyRouteMaps{}
+ if cValue := v.Get("inout"); cValue.Exists() {
+ item.InOut = types.StringValue(cValue.String())
+ }
+ if cValue := v.Get("route-map-name"); cValue.Exists() {
+ item.RouteMapName = types.StringValue(cValue.String())
+ }
+ data.RouteMaps = append(data.RouteMaps, item)
+ return true
+ })
+ }
+ if value := res.Get(prefix + "allowas-in.as-number"); value.Exists() {
+ data.AllowasInAsNumber = types.Int64Value(value.Int())
+ }
+ if value := res.Get(prefix + "as-override.split-horizon"); value.Exists() {
+ data.AsOverrideSplitHorizon = types.BoolValue(true)
+ } else {
+ data.AsOverrideSplitHorizon = types.BoolValue(false)
+ }
+}
+
+// End of section. //template:end fromBody
+
+// Section below is generated&owned by "gen/generator.go". //template:begin fromBodyData
+
+func (data *BGPTemplatePeerPolicyData) fromBody(ctx context.Context, res gjson.Result) {
+ prefix := helpers.LastElement(data.getPath()) + "."
+ if res.Get(helpers.LastElement(data.getPath())).IsArray() {
+ prefix += "0."
+ }
+ if value := res.Get(prefix + "route-reflector-client"); value.Exists() {
+ data.RouteReflectorClient = types.BoolValue(true)
+ } else {
+ data.RouteReflectorClient = types.BoolValue(false)
+ }
+ if value := res.Get(prefix + "send-community.send-community-where"); value.Exists() {
+ data.SendCommunity = types.StringValue(value.String())
+ }
+ if value := res.Get(prefix + "route-map1"); value.Exists() {
+ data.RouteMaps = make([]BGPTemplatePeerPolicyRouteMaps, 0)
+ value.ForEach(func(k, v gjson.Result) bool {
+ item := BGPTemplatePeerPolicyRouteMaps{}
+ if cValue := v.Get("inout"); cValue.Exists() {
+ item.InOut = types.StringValue(cValue.String())
+ }
+ if cValue := v.Get("route-map-name"); cValue.Exists() {
+ item.RouteMapName = types.StringValue(cValue.String())
+ }
+ data.RouteMaps = append(data.RouteMaps, item)
+ return true
+ })
+ }
+ if value := res.Get(prefix + "allowas-in.as-number"); value.Exists() {
+ data.AllowasInAsNumber = types.Int64Value(value.Int())
+ }
+ if value := res.Get(prefix + "as-override.split-horizon"); value.Exists() {
+ data.AsOverrideSplitHorizon = types.BoolValue(true)
+ } else {
+ data.AsOverrideSplitHorizon = types.BoolValue(false)
+ }
+}
+
+// End of section. //template:end fromBodyData
+
+// Section below is generated&owned by "gen/generator.go". //template:begin getDeletedItems
+
+func (data *BGPTemplatePeerPolicy) getDeletedItems(ctx context.Context, state BGPTemplatePeerPolicy) []string {
+ deletedItems := make([]string, 0)
+ if !state.AsOverrideSplitHorizon.IsNull() && data.AsOverrideSplitHorizon.IsNull() {
+ deletedItems = append(deletedItems, fmt.Sprintf("%v/as-override/split-horizon", state.getPath()))
+ }
+ if !state.AllowasInAsNumber.IsNull() && data.AllowasInAsNumber.IsNull() {
+ deletedItems = append(deletedItems, fmt.Sprintf("%v/allowas-in/as-number", state.getPath()))
+ }
+ for i := range state.RouteMaps {
+ stateKeyValues := [...]string{state.RouteMaps[i].InOut.ValueString()}
+
+ emptyKeys := true
+ if !reflect.ValueOf(state.RouteMaps[i].InOut.ValueString()).IsZero() {
+ emptyKeys = false
+ }
+ if emptyKeys {
+ continue
+ }
+
+ found := false
+ for j := range data.RouteMaps {
+ found = true
+ if state.RouteMaps[i].InOut.ValueString() != data.RouteMaps[j].InOut.ValueString() {
+ found = false
+ }
+ if found {
+ if !state.RouteMaps[i].RouteMapName.IsNull() && data.RouteMaps[j].RouteMapName.IsNull() {
+ deletedItems = append(deletedItems, fmt.Sprintf("%v/route-map1=%v/route-map-name", state.getPath(), strings.Join(stateKeyValues[:], ",")))
+ }
+ break
+ }
+ }
+ if !found {
+ deletedItems = append(deletedItems, fmt.Sprintf("%v/route-map1=%v", state.getPath(), strings.Join(stateKeyValues[:], ",")))
+ }
+ }
+ if !state.SendCommunity.IsNull() && data.SendCommunity.IsNull() {
+ deletedItems = append(deletedItems, fmt.Sprintf("%v/send-community/send-community-where", state.getPath()))
+ }
+ if !state.RouteReflectorClient.IsNull() && data.RouteReflectorClient.IsNull() {
+ deletedItems = append(deletedItems, fmt.Sprintf("%v/route-reflector-client", state.getPath()))
+ }
+
+ return deletedItems
+}
+
+// End of section. //template:end getDeletedItems
+
+// Section below is generated&owned by "gen/generator.go". //template:begin getEmptyLeafsDelete
+
+func (data *BGPTemplatePeerPolicy) getEmptyLeafsDelete(ctx context.Context) []string {
+ emptyLeafsDelete := make([]string, 0)
+ if !data.AsOverrideSplitHorizon.IsNull() && !data.AsOverrideSplitHorizon.ValueBool() {
+ emptyLeafsDelete = append(emptyLeafsDelete, fmt.Sprintf("%v/as-override/split-horizon", data.getPath()))
+ }
+
+ if !data.RouteReflectorClient.IsNull() && !data.RouteReflectorClient.ValueBool() {
+ emptyLeafsDelete = append(emptyLeafsDelete, fmt.Sprintf("%v/route-reflector-client", data.getPath()))
+ }
+
+ return emptyLeafsDelete
+}
+
+// End of section. //template:end getEmptyLeafsDelete
+
+// Section below is generated&owned by "gen/generator.go". //template:begin getDeletePaths
+
+func (data *BGPTemplatePeerPolicy) getDeletePaths(ctx context.Context) []string {
+ var deletePaths []string
+ if !data.AsOverrideSplitHorizon.IsNull() {
+ deletePaths = append(deletePaths, fmt.Sprintf("%v/as-override/split-horizon", data.getPath()))
+ }
+ if !data.AllowasInAsNumber.IsNull() {
+ deletePaths = append(deletePaths, fmt.Sprintf("%v/allowas-in/as-number", data.getPath()))
+ }
+ for i := range data.RouteMaps {
+ keyValues := [...]string{data.RouteMaps[i].InOut.ValueString()}
+
+ deletePaths = append(deletePaths, fmt.Sprintf("%v/route-map1=%v", data.getPath(), strings.Join(keyValues[:], ",")))
+ }
+ if !data.SendCommunity.IsNull() {
+ deletePaths = append(deletePaths, fmt.Sprintf("%v/send-community/send-community-where", data.getPath()))
+ }
+ if !data.RouteReflectorClient.IsNull() {
+ deletePaths = append(deletePaths, fmt.Sprintf("%v/route-reflector-client", data.getPath()))
+ }
+
+ return deletePaths
+}
+
+// End of section. //template:end getDeletePaths
diff --git a/internal/provider/provider.go b/internal/provider/provider.go
index 8c8ba8a87..8648656c4 100644
--- a/internal/provider/provider.go
+++ b/internal/provider/provider.go
@@ -391,6 +391,7 @@ func (p *IosxeProvider) Resources(ctx context.Context) []func() resource.Resourc
NewBGPL2VPNEVPNNeighborResource,
NewBGPNeighborResource,
NewBGPPeerSessionTemplateResource,
+ NewBGPTemplatePeerPolicyResource,
NewCDPResource,
NewClassMapResource,
NewClockResource,
@@ -496,6 +497,7 @@ func (p *IosxeProvider) DataSources(ctx context.Context) []func() datasource.Dat
NewBGPL2VPNEVPNNeighborDataSource,
NewBGPNeighborDataSource,
NewBGPPeerSessionTemplateDataSource,
+ NewBGPTemplatePeerPolicyDataSource,
NewCDPDataSource,
NewClassMapDataSource,
NewClockDataSource,
diff --git a/internal/provider/resource_iosxe_bgp_template_peer_policy.go b/internal/provider/resource_iosxe_bgp_template_peer_policy.go
new file mode 100644
index 000000000..226d4014b
--- /dev/null
+++ b/internal/provider/resource_iosxe_bgp_template_peer_policy.go
@@ -0,0 +1,462 @@
+// 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
+
+// Code generated by "gen/generator.go"; DO NOT EDIT.
+
+package provider
+
+// Section below is generated&owned by "gen/generator.go". //template:begin imports
+import (
+ "context"
+ "fmt"
+ "strings"
+
+ "github.com/CiscoDevNet/terraform-provider-iosxe/internal/provider/helpers"
+ "github.com/hashicorp/terraform-plugin-framework-validators/int64validator"
+ "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/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"
+ "github.com/netascode/go-restconf"
+)
+
+// 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 = &BGPTemplatePeerPolicyResource{}
+ _ resource.ResourceWithImportState = &BGPTemplatePeerPolicyResource{}
+)
+
+func NewBGPTemplatePeerPolicyResource() resource.Resource {
+ return &BGPTemplatePeerPolicyResource{}
+}
+
+type BGPTemplatePeerPolicyResource struct {
+ data *IosxeProviderData
+}
+
+func (r *BGPTemplatePeerPolicyResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
+ resp.TypeName = req.ProviderTypeName + "_bgp_template_peer_policy"
+}
+
+func (r *BGPTemplatePeerPolicyResource) 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: "This resource can manage the BGP Template Peer Policy configuration.",
+
+ Attributes: map[string]schema.Attribute{
+ "device": schema.StringAttribute{
+ MarkdownDescription: "A device name from the provider configuration.",
+ Optional: true,
+ },
+ "id": schema.StringAttribute{
+ MarkdownDescription: "The path of the object.",
+ Computed: true,
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.UseStateForUnknown(),
+ },
+ },
+ "delete_mode": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Configure behavior when deleting/destroying the resource. Either delete the entire object (YANG container) being managed, or only delete the individual resource attributes configured explicitly and leave everything else as-is. Default value is `all`.").AddStringEnumDescription("all", "attributes").String,
+ Optional: true,
+ Validators: []validator.String{
+ stringvalidator.OneOf("all", "attributes"),
+ },
+ },
+ "asn": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("").String,
+ Required: true,
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.RequiresReplace(),
+ },
+ },
+ "name": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("").String,
+ Required: true,
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.RequiresReplace(),
+ },
+ },
+ "route_reflector_client": schema.BoolAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Configure a neighbor as Route Reflector client").String,
+ Optional: true,
+ },
+ "send_community": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("").AddStringEnumDescription("both", "extended", "standard").String,
+ Optional: true,
+ Validators: []validator.String{
+ stringvalidator.OneOf("both", "extended", "standard"),
+ },
+ },
+ "route_maps": schema.ListNestedAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Apply route map to neighbor").String,
+ Optional: true,
+ NestedObject: schema.NestedAttributeObject{
+ Attributes: map[string]schema.Attribute{
+ "in_out": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("").AddStringEnumDescription("in", "out").String,
+ Required: true,
+ Validators: []validator.String{
+ stringvalidator.OneOf("in", "out"),
+ },
+ },
+ "route_map_name": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("").String,
+ Required: true,
+ },
+ },
+ },
+ },
+ "allowas_in_as_number": schema.Int64Attribute{
+ MarkdownDescription: helpers.NewAttributeDescription("").AddIntegerRangeDescription(1, 10).String,
+ Optional: true,
+ Validators: []validator.Int64{
+ int64validator.Between(1, 10),
+ },
+ },
+ "as_override_split_horizon": schema.BoolAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("").String,
+ Optional: true,
+ },
+ },
+ }
+}
+
+func (r *BGPTemplatePeerPolicyResource) Configure(_ context.Context, req resource.ConfigureRequest, _ *resource.ConfigureResponse) {
+ if req.ProviderData == nil {
+ return
+ }
+
+ r.data = req.ProviderData.(*IosxeProviderData)
+}
+
+// End of section. //template:end model
+
+// Section below is generated&owned by "gen/generator.go". //template:begin create
+
+func (r *BGPTemplatePeerPolicyResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
+ var plan BGPTemplatePeerPolicy
+
+ // 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.getPath()))
+
+ device, ok := r.data.Devices[plan.Device.ValueString()]
+ if !ok {
+ resp.Diagnostics.AddAttributeError(path.Root("device"), "Invalid device", fmt.Sprintf("Device '%s' does not exist in provider configuration.", plan.Device.ValueString()))
+ return
+ }
+
+ if device.Managed {
+ // Create object
+ body := plan.toBody(ctx)
+
+ emptyLeafsDelete := plan.getEmptyLeafsDelete(ctx)
+ tflog.Debug(ctx, fmt.Sprintf("List of empty leafs to delete: %+v", emptyLeafsDelete))
+
+ if YangPatch {
+ edits := []restconf.YangPatchEdit{restconf.NewYangPatchEdit("merge", plan.getPath(), restconf.Body{Str: body})}
+ for _, i := range emptyLeafsDelete {
+ edits = append(edits, restconf.NewYangPatchEdit("remove", i, restconf.Body{}))
+ }
+ _, err := device.Client.YangPatchData("", "1", "", edits)
+ if err != nil {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to configure object, got error: %s", err))
+ return
+ }
+ } else {
+ res, err := device.Client.PatchData(plan.getPathShort(), body)
+ if len(res.Errors.Error) > 0 && res.Errors.Error[0].ErrorMessage == "patch to a nonexistent resource" {
+ _, err = device.Client.PutData(plan.getPath(), body)
+ }
+ if err != nil {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to configure object (PATCH, %s), got error: %s", plan.getPathShort(), err))
+ return
+ }
+ for _, i := range emptyLeafsDelete {
+ res, err := device.Client.DeleteData(i)
+ if err != nil && res.StatusCode != 404 {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to delete object (%s), got error: %s", i, err))
+ return
+ }
+ }
+ }
+ }
+
+ plan.Id = types.StringValue(plan.getPath())
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Create finished successfully", plan.getPath()))
+
+ diags = resp.State.Set(ctx, &plan)
+ resp.Diagnostics.Append(diags...)
+
+ helpers.SetFlagImporting(ctx, false, resp.Private, &resp.Diagnostics)
+}
+
+// End of section. //template:end create
+
+// Section below is generated&owned by "gen/generator.go". //template:begin read
+
+func (r *BGPTemplatePeerPolicyResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
+ var state BGPTemplatePeerPolicy
+
+ // 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.ValueString()))
+
+ device, ok := r.data.Devices[state.Device.ValueString()]
+ if !ok {
+ resp.Diagnostics.AddAttributeError(path.Root("device"), "Invalid device", fmt.Sprintf("Device '%s' does not exist in provider configuration.", state.Device.ValueString()))
+ return
+ }
+
+ if device.Managed {
+ res, err := device.Client.GetData(state.Id.ValueString())
+ if res.StatusCode == 404 {
+ state = BGPTemplatePeerPolicy{Device: state.Device, Id: state.Id}
+ } else {
+ if err != nil {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to retrieve object (%s), got error: %s", state.Id.ValueString(), err))
+ return
+ }
+
+ imp, diags := helpers.IsFlagImporting(ctx, req)
+ if resp.Diagnostics.Append(diags...); resp.Diagnostics.HasError() {
+ return
+ }
+
+ // After `terraform import` we switch to a full read.
+ if imp {
+ state.fromBody(ctx, res.Res)
+ } else {
+ state.updateFromBody(ctx, res.Res)
+ }
+ }
+ }
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Read finished successfully", state.Id.ValueString()))
+
+ diags = resp.State.Set(ctx, &state)
+ resp.Diagnostics.Append(diags...)
+
+ helpers.SetFlagImporting(ctx, false, resp.Private, &resp.Diagnostics)
+}
+
+// End of section. //template:end read
+
+// Section below is generated&owned by "gen/generator.go". //template:begin update
+
+func (r *BGPTemplatePeerPolicyResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
+ var plan, state BGPTemplatePeerPolicy
+
+ // 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()))
+
+ device, ok := r.data.Devices[plan.Device.ValueString()]
+ if !ok {
+ resp.Diagnostics.AddAttributeError(path.Root("device"), "Invalid device", fmt.Sprintf("Device '%s' does not exist in provider configuration.", plan.Device.ValueString()))
+ return
+ }
+
+ if device.Managed {
+ body := plan.toBody(ctx)
+
+ deletedItems := plan.getDeletedItems(ctx, state)
+ tflog.Debug(ctx, fmt.Sprintf("Removed items to delete: %+v", deletedItems))
+
+ emptyLeafsDelete := plan.getEmptyLeafsDelete(ctx)
+ tflog.Debug(ctx, fmt.Sprintf("List of empty leafs to delete: %+v", emptyLeafsDelete))
+
+ if YangPatch {
+ var edits []restconf.YangPatchEdit
+ for _, i := range deletedItems {
+ edits = append(edits, restconf.NewYangPatchEdit("remove", i, restconf.Body{}))
+ }
+ edits = append(edits, restconf.NewYangPatchEdit("merge", plan.getPath(), restconf.Body{Str: body}))
+ for _, i := range emptyLeafsDelete {
+ edits = append(edits, restconf.NewYangPatchEdit("remove", i, restconf.Body{}))
+ }
+ _, err := device.Client.YangPatchData("", "1", "", edits)
+ if err != nil {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to update object, got error: %s", err))
+ return
+ }
+ } else {
+ for _, i := range deletedItems {
+ res, err := device.Client.DeleteData(i)
+ if err != nil && res.StatusCode != 404 {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to delete object (%s), got error: %s", i, err))
+ return
+ }
+ }
+ res, err := device.Client.PatchData(plan.getPathShort(), body)
+ if len(res.Errors.Error) > 0 && res.Errors.Error[0].ErrorMessage == "patch to a nonexistent resource" {
+ _, err = device.Client.PutData(plan.getPath(), body)
+ }
+ if err != nil {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to configure object (PATCH, %s), got error: %s", plan.getPathShort(), err))
+ return
+ }
+ for _, i := range emptyLeafsDelete {
+ res, err := device.Client.DeleteData(i)
+ if err != nil && res.StatusCode != 404 {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to delete object (%s), got error: %s", i, err))
+ 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 *BGPTemplatePeerPolicyResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
+ var state BGPTemplatePeerPolicy
+
+ // 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()))
+
+ device, ok := r.data.Devices[state.Device.ValueString()]
+ if !ok {
+ resp.Diagnostics.AddAttributeError(path.Root("device"), "Invalid device", fmt.Sprintf("Device '%s' does not exist in provider configuration.", state.Device.ValueString()))
+ return
+ }
+
+ if device.Managed {
+ deleteMode := "all"
+ if state.DeleteMode.ValueString() == "all" {
+ deleteMode = "all"
+ } else if state.DeleteMode.ValueString() == "attributes" {
+ deleteMode = "attributes"
+ }
+
+ if deleteMode == "all" {
+ res, err := device.Client.DeleteData(state.Id.ValueString())
+ if err != nil && res.StatusCode != 404 && res.StatusCode != 400 {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to delete object (%s), got error: %s", state.Id.ValueString(), err))
+ return
+ }
+ } else {
+ deletePaths := state.getDeletePaths(ctx)
+ tflog.Debug(ctx, fmt.Sprintf("Paths to delete: %+v", deletePaths))
+
+ if YangPatch {
+ edits := []restconf.YangPatchEdit{}
+ for _, i := range deletePaths {
+ edits = append(edits, restconf.NewYangPatchEdit("remove", i, restconf.Body{}))
+ }
+ _, err := device.Client.YangPatchData("", "1", "", edits)
+ if err != nil {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to delete object, got error: %s", err))
+ return
+ }
+ } else {
+ for _, i := range deletePaths {
+ res, err := device.Client.DeleteData(i)
+ if err != nil && res.StatusCode != 404 {
+ resp.Diagnostics.AddWarning("Client Warning", fmt.Sprintf("Failed to delete object (%s), got error: %s", i, err))
+ }
+ }
+ }
+ }
+ }
+
+ 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 *BGPTemplatePeerPolicyResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
+ idParts := strings.Split(req.ID, ",")
+ idParts = helpers.RemoveEmptyStrings(idParts)
+
+ if len(idParts) != 2 && len(idParts) != 3 {
+ expectedIdentifier := "Expected import identifier with format: ','"
+ expectedIdentifier += " or ',,'"
+ resp.Diagnostics.AddError(
+ "Unexpected Import Identifier",
+ fmt.Sprintf("%s. Got: %q", expectedIdentifier, req.ID),
+ )
+ return
+ }
+ resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("asn"), idParts[0])...)
+ resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("name"), idParts[1])...)
+ if len(idParts) == 3 {
+ resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("device"), idParts[len(idParts)-1])...)
+ }
+
+ // construct path for 'id' attribute
+ var state BGPTemplatePeerPolicy
+ diags := resp.State.Get(ctx, &state)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+ resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("id"), state.getPath())...)
+
+ helpers.SetFlagImporting(ctx, true, resp.Private, &resp.Diagnostics)
+}
+
+// End of section. //template:end import
diff --git a/internal/provider/resource_iosxe_bgp_template_peer_policy_test.go b/internal/provider/resource_iosxe_bgp_template_peer_policy_test.go
new file mode 100644
index 000000000..2f1fa4fd0
--- /dev/null
+++ b/internal/provider/resource_iosxe_bgp_template_peer_policy_test.go
@@ -0,0 +1,135 @@
+// 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
+
+// Code generated by "gen/generator.go"; DO NOT EDIT.
+
+package provider
+
+// Section below is generated&owned by "gen/generator.go". //template:begin imports
+import (
+ "fmt"
+ "testing"
+
+ "github.com/hashicorp/terraform-plugin-testing/helper/resource"
+ "github.com/hashicorp/terraform-plugin-testing/terraform"
+)
+
+// End of section. //template:end imports
+
+// Section below is generated&owned by "gen/generator.go". //template:begin testAcc
+
+func TestAccIosxeBGPTemplatePeerPolicy(t *testing.T) {
+ var checks []resource.TestCheckFunc
+ checks = append(checks, resource.TestCheckResourceAttr("iosxe_bgp_template_peer_policy.test", "name", "PEERPOLICY_1"))
+ checks = append(checks, resource.TestCheckResourceAttr("iosxe_bgp_template_peer_policy.test", "route_reflector_client", "true"))
+ checks = append(checks, resource.TestCheckResourceAttr("iosxe_bgp_template_peer_policy.test", "send_community", "both"))
+ checks = append(checks, resource.TestCheckResourceAttr("iosxe_bgp_template_peer_policy.test", "route_maps.0.in_out", "in"))
+ checks = append(checks, resource.TestCheckResourceAttr("iosxe_bgp_template_peer_policy.test", "route_maps.0.route_map_name", "ROUTEMAP_1"))
+ checks = append(checks, resource.TestCheckResourceAttr("iosxe_bgp_template_peer_policy.test", "allowas_in_as_number", "2"))
+ checks = append(checks, resource.TestCheckResourceAttr("iosxe_bgp_template_peer_policy.test", "as_override_split_horizon", "true"))
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { testAccPreCheck(t) },
+ ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
+ Steps: []resource.TestStep{
+ {
+ Config: testAccIosxeBGPTemplatePeerPolicyPrerequisitesConfig + testAccIosxeBGPTemplatePeerPolicyConfig_minimum(),
+ },
+ {
+ Config: testAccIosxeBGPTemplatePeerPolicyPrerequisitesConfig + testAccIosxeBGPTemplatePeerPolicyConfig_all(),
+ Check: resource.ComposeTestCheckFunc(checks...),
+ },
+ {
+ ResourceName: "iosxe_bgp_template_peer_policy.test",
+ ImportState: true,
+ ImportStateVerify: true,
+ ImportStateIdFunc: iosxeBGPTemplatePeerPolicyImportStateIdFunc("iosxe_bgp_template_peer_policy.test"),
+ ImportStateVerifyIgnore: []string{},
+ Check: resource.ComposeTestCheckFunc(checks...),
+ },
+ },
+ })
+}
+
+// End of section. //template:end testAcc
+
+// Section below is generated&owned by "gen/generator.go". //template:begin importStateIdFunc
+
+func iosxeBGPTemplatePeerPolicyImportStateIdFunc(resourceName string) resource.ImportStateIdFunc {
+ return func(s *terraform.State) (string, error) {
+ primary := s.RootModule().Resources[resourceName].Primary
+ Asn := primary.Attributes["asn"]
+ Name := primary.Attributes["name"]
+
+ return fmt.Sprintf("%s,%s", Asn, Name), nil
+ }
+}
+
+// End of section. //template:end importStateIdFunc
+
+// Section below is generated&owned by "gen/generator.go". //template:begin testPrerequisites
+const testAccIosxeBGPTemplatePeerPolicyPrerequisitesConfig = `
+resource "iosxe_restconf" "PreReq0" {
+ path = "Cisco-IOS-XE-native:native/router/Cisco-IOS-XE-bgp:bgp=65000"
+ attributes = {
+ "id" = "65000"
+ }
+}
+
+resource "iosxe_restconf" "PreReq1" {
+ path = "Cisco-IOS-XE-native:native/route-map=ROUTEMAP_1"
+ attributes = {
+ "name" = "ROUTEMAP_1"
+ }
+}
+
+`
+
+// End of section. //template:end testPrerequisites
+
+// Section below is generated&owned by "gen/generator.go". //template:begin testAccConfigMinimal
+
+func testAccIosxeBGPTemplatePeerPolicyConfig_minimum() string {
+ config := `resource "iosxe_bgp_template_peer_policy" "test" {` + "\n"
+ config += ` asn = "65000"` + "\n"
+ config += ` name = "PEERPOLICY_1"` + "\n"
+ config += ` depends_on = [iosxe_restconf.PreReq0, iosxe_restconf.PreReq1, ]` + "\n"
+ config += `}` + "\n"
+ return config
+}
+
+// End of section. //template:end testAccConfigMinimal
+
+// Section below is generated&owned by "gen/generator.go". //template:begin testAccConfigAll
+
+func testAccIosxeBGPTemplatePeerPolicyConfig_all() string {
+ config := `resource "iosxe_bgp_template_peer_policy" "test" {` + "\n"
+ config += ` asn = "65000"` + "\n"
+ config += ` name = "PEERPOLICY_1"` + "\n"
+ config += ` route_reflector_client = true` + "\n"
+ config += ` send_community = "both"` + "\n"
+ config += ` route_maps = [{` + "\n"
+ config += ` in_out = "in"` + "\n"
+ config += ` route_map_name = "ROUTEMAP_1"` + "\n"
+ config += ` }]` + "\n"
+ config += ` allowas_in_as_number = 2` + "\n"
+ config += ` as_override_split_horizon = true` + "\n"
+ config += ` depends_on = [iosxe_restconf.PreReq0, iosxe_restconf.PreReq1, ]` + "\n"
+ config += `}` + "\n"
+ return config
+}
+
+// End of section. //template:end testAccConfigAll
diff --git a/templates/guides/changelog.md.tmpl b/templates/guides/changelog.md.tmpl
index 7fa3bd4df..517dfc963 100644
--- a/templates/guides/changelog.md.tmpl
+++ b/templates/guides/changelog.md.tmpl
@@ -16,6 +16,7 @@ description: |-
- Add `ip_ssh_bulk_mode` and `ip_ssh_bulk_mode_window_size` attributes to `iosxe_system` resource and data source
- Add `set_ip_next_hop_unchanged` attribute to `iosxe_route_map` resource and data source
- Enhance `set_communities` attribute documentation in `iosxe_route_map` to clarify support for well-known BGP community values (internet, local-AS, no-advertise, no-export, gshut)
+- Add `iosxe_bgp_template_peer_policy` resource
## 0.9.3
@@ -30,7 +31,7 @@ description: |-
- Add `passive_interface_disable_*` attributes to `iosxe_ospf` and `iosxe_ospf_vrf` resources and data sources
- Fix issue with destroying `iosxe_interface_ethernet` resources
- Change route target attributes of `iosxe_vrf` from type "List" to "Set"
-- Add `role_based_enforcement` attributes to `iosxe_cts`
+- Add `role_based_enforcement` attributes to `iosxe_cts`
- Add `tftp_source_interface_*` attributes to `iosxe_system` resource and data source
- Add `hash` attribute to `iosxe_crypto_pki` resource and data source
- Add `snooping_information_option`, `snooping_information_option_allow_untrusted` and `snooping_information_option_format_remote_id_string` attributes to `iosxe_dhcp` resource and data source
@@ -75,7 +76,7 @@ description: |-
- Add `level`, `list_name`, `action_type`, `broadcast`, `group_broadcast`, `group_logger`, `group1_group`, `group2_group`, `group3_group`, `group4_group`, `name`, `default`, `none`, `start_stop_broadcast`, `start_stop_logger`, `start_stop_group1`, `start_stop_group2`, `start_stop_group3`, `start_stop_group4`, `stop_only_broadcast`, `stop_only_logger`, `stop_only_group1`, `stop_only_group2`, `stop_only_group3`, `stop_only_group4`, `wait_start_broadcast`, `wait_start_logger`, `wait_start_group1`, `wait_start_group2`, `wait_start_group3`, `wait_start_group4`, `name`, `none`, `start_stop_broadcast`, `start_stop_logger`, `start_stop_group1`, `start_stop_group2`, `start_stop_group3`, `start_stop_group4`, `stop_only_broadcast`, `stop_only_logger`, `stop_only_group1`, `stop_only_group2`, `stop_only_group3`, `stop_only_group4`, `wait_start_broadcast`, `wait_start_logger`, `wait_start_group1`, `wait_start_group2`, `wait_start_group3`, and `wait_start_group4` attributes to `iosxe_aaa_accounting` resource and data source
- Add `enable_default_group1_cache`, `enable_default_group1_enable`, `enable_default_group1_group`, `enable_default_group1_line`, `enable_default_group1_none`, `enable_default_group2_cache`, `enable_default_group2_enable`, `enable_default_group2_group`, `enable_default_group2_line`, `enable_default_group2_none`, `enable_default_group3_cache`, `enable_default_group3_enable`, `enable_default_group3_group`, `enable_default_group3_line`, `enable_default_group3_none`, `enable_default_group4_cache`, `enable_default_group4_enable`, `enable_default_group4_group`, `enable_default_group4_line`, and `enable_default_group4_none` attributes to `iosxe_aaa_authentication` resource and data source
- Add `level`, `list_name`, `a1_group`, `a1_local`, `a1_if_authenticated`, `a1_none`, `a1_radius`, `a1_tacacs`, `a2_group`, `a2_local`, `a2_if_authenticated`, `a2_none`, `a2_radius`, `a2_tacacs`, `a3_group`, `a3_local`, `a3_if_authenticated`, `a3_none`, `a3_radius`, `a3_tacacs`, `a4_group`, `a4_local`, `a4_if_authenticated`, `a4_none`, `a4_radius`, `a4_tacacs`, `name`, `group1_cache`, `group1_group`, `group1_radius`, and `group1_tacacs` attributes to `iosxe_aaa_authorization` resource and data source
-- Add `vrf`, `local_authentication_type`, `local_authorization`, and `local_auth_max_fail_attempts` attributes to `iosxe_aaa` resrouce and data source
+- Add `vrf`, `local_authentication_type`, `local_authorization`, and `local_auth_max_fail_attempts` attributes to `iosxe_aaa` resrouce and data source
- Add `icmp_named_msg_type`, `destination_port_equal_2`, `destination_port_equal_3`, `destination_port_equal_4`, `destination_port_equal_5`, `destination_port_equal_6`, `destination_port_equal_7`, `destination_port_equal_8`, `destination_port_equal_9`, `destination_port_equal_10`, `icmp_msg_type`, and `icmp_msg_code` attributes to `iosxe_access_list_extended` resource and data source
- Add `iosxe_access_list_role_based` resource and data source
- Add `filter_lists_cdp` attribute to `iosxe_device_sensor` resource and data source