diff --git a/CHANGELOG.md b/CHANGELOG.md index 3a958ac6f..5921c95b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ - Add `local_routing` attribute to `iosxe_interface_nve` resource and data source - Add `ipv4_unicast_maximum_paths_ebgp` and `ipv4_unicast_maximum_paths_ibgp` attributes to the `iosxe_bgp_address_family_ipv4` and `iosxe_bgp_address_family_ipv4_vrf` resources - Add `ip_cef_load_sharing_algorithm_include_ports_source`, `ip_cef_load_sharing_algorithm_include_ports_destination`, `ipv6_cef_load_sharing_algorithm_include_ports_source`, `ipv6_cef_load_sharing_algorithm_include_ports_destination`, and `port_channel_load_balance` attributes to `iosxe_system` resource and data source +- Add `router_id_ip`, `bgp_graceful_restart`, and `bgp_update_delay` to `iosxe_bgp` resource and data source ## 0.9.3 diff --git a/docs/data-sources/bgp.md b/docs/data-sources/bgp.md index 11180d295..3b6ca7aaf 100644 --- a/docs/data-sources/bgp.md +++ b/docs/data-sources/bgp.md @@ -31,6 +31,8 @@ data "iosxe_bgp" "example" { ### Read-Only +- `bgp_graceful_restart` (Boolean) Graceful restart capability parameters +- `bgp_update_delay` (Number) Set the max initial delay for sending update - `default_ipv4_unicast` (Boolean) Activate ipv4-unicast for a peer by default - `id` (String) The path of the retrieved object. - `log_neighbor_changes` (Boolean) Log neighbor up/down and reset reason diff --git a/docs/resources/bgp.md b/docs/resources/bgp.md index 2d29f55ad..e11145eb4 100644 --- a/docs/resources/bgp.md +++ b/docs/resources/bgp.md @@ -17,6 +17,9 @@ resource "iosxe_bgp" "example" { asn = "65000" default_ipv4_unicast = false log_neighbor_changes = true + router_id_ip = "172.16.255.1" + bgp_graceful_restart = true + bgp_update_delay = 200 router_id_loopback = 100 } ``` @@ -30,6 +33,9 @@ resource "iosxe_bgp" "example" { ### Optional +- `bgp_graceful_restart` (Boolean) Graceful restart capability parameters +- `bgp_update_delay` (Number) Set the max initial delay for sending update + - Range: `1`-`3600` - `default_ipv4_unicast` (Boolean) Activate ipv4-unicast for a peer by default - `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` diff --git a/examples/resources/iosxe_bgp/resource.tf b/examples/resources/iosxe_bgp/resource.tf index c6fc353ff..c98b28050 100644 --- a/examples/resources/iosxe_bgp/resource.tf +++ b/examples/resources/iosxe_bgp/resource.tf @@ -2,5 +2,8 @@ resource "iosxe_bgp" "example" { asn = "65000" default_ipv4_unicast = false log_neighbor_changes = true + router_id_ip = "172.16.255.1" + bgp_graceful_restart = true + bgp_update_delay = 200 router_id_loopback = 100 } diff --git a/gen/definitions/bgp.yaml b/gen/definitions/bgp.yaml index 92d7d0af1..370598f59 100644 --- a/gen/definitions/bgp.yaml +++ b/gen/definitions/bgp.yaml @@ -16,11 +16,17 @@ attributes: xpath: bgp/router-id/interface/Loopback tf_name: router_id_loopback example: 100 + exclude_test: true - yang_name: bgp/router-id/id-choice/ip-id/ip-id xpath: bgp/router-id/ip-id tf_name: router_id_ip example: 172.16.255.1 exclude_test: true + - yang_name: bgp/gr-options/graceful-restart + tf_name: bgp_graceful_restart + example: true + - yang_name: bgp/update-delay + example: 200 test_prerequisites: - path: Cisco-IOS-XE-native:native/interface/Loopback=100 attributes: diff --git a/internal/provider/data_source_iosxe_bgp.go b/internal/provider/data_source_iosxe_bgp.go index 1ffc37796..947e0f129 100644 --- a/internal/provider/data_source_iosxe_bgp.go +++ b/internal/provider/data_source_iosxe_bgp.go @@ -87,6 +87,14 @@ func (d *BGPDataSource) Schema(ctx context.Context, req datasource.SchemaRequest MarkdownDescription: "Manually configured router identifier", Computed: true, }, + "bgp_graceful_restart": schema.BoolAttribute{ + MarkdownDescription: "Graceful restart capability parameters", + Computed: true, + }, + "bgp_update_delay": schema.Int64Attribute{ + MarkdownDescription: "Set the max initial delay for sending update", + Computed: true, + }, }, } } diff --git a/internal/provider/data_source_iosxe_bgp_test.go b/internal/provider/data_source_iosxe_bgp_test.go index 4ed4e1f1a..873b60c2e 100644 --- a/internal/provider/data_source_iosxe_bgp_test.go +++ b/internal/provider/data_source_iosxe_bgp_test.go @@ -34,6 +34,9 @@ func TestAccDataSourceIosxeBGP(t *testing.T) { var checks []resource.TestCheckFunc checks = append(checks, resource.TestCheckResourceAttr("data.iosxe_bgp.test", "default_ipv4_unicast", "false")) checks = append(checks, resource.TestCheckResourceAttr("data.iosxe_bgp.test", "log_neighbor_changes", "true")) + checks = append(checks, resource.TestCheckResourceAttr("data.iosxe_bgp.test", "router_id_ip", "172.16.255.1")) + checks = append(checks, resource.TestCheckResourceAttr("data.iosxe_bgp.test", "bgp_graceful_restart", "true")) + checks = append(checks, resource.TestCheckResourceAttr("data.iosxe_bgp.test", "bgp_update_delay", "200")) checks = append(checks, resource.TestCheckResourceAttr("data.iosxe_bgp.test", "router_id_loopback", "100")) resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -72,6 +75,9 @@ func testAccDataSourceIosxeBGPConfig() string { config += ` asn = "65000"` + "\n" config += ` default_ipv4_unicast = false` + "\n" config += ` log_neighbor_changes = true` + "\n" + config += ` router_id_ip = "172.16.255.1"` + "\n" + config += ` bgp_graceful_restart = true` + "\n" + config += ` bgp_update_delay = 200` + "\n" config += ` router_id_loopback = 100` + "\n" config += ` depends_on = [iosxe_restconf.PreReq0, ]` + "\n" config += `}` + "\n" diff --git a/internal/provider/model_iosxe_bgp.go b/internal/provider/model_iosxe_bgp.go index d81a0ceef..1379073c8 100644 --- a/internal/provider/model_iosxe_bgp.go +++ b/internal/provider/model_iosxe_bgp.go @@ -45,6 +45,8 @@ type BGP struct { LogNeighborChanges types.Bool `tfsdk:"log_neighbor_changes"` RouterIdLoopback types.Int64 `tfsdk:"router_id_loopback"` RouterIdIp types.String `tfsdk:"router_id_ip"` + BgpGracefulRestart types.Bool `tfsdk:"bgp_graceful_restart"` + BgpUpdateDelay types.Int64 `tfsdk:"bgp_update_delay"` } type BGPData struct { @@ -55,6 +57,8 @@ type BGPData struct { LogNeighborChanges types.Bool `tfsdk:"log_neighbor_changes"` RouterIdLoopback types.Int64 `tfsdk:"router_id_loopback"` RouterIdIp types.String `tfsdk:"router_id_ip"` + BgpGracefulRestart types.Bool `tfsdk:"bgp_graceful_restart"` + BgpUpdateDelay types.Int64 `tfsdk:"bgp_update_delay"` } // End of section. //template:end types @@ -101,6 +105,14 @@ func (data BGP) toBody(ctx context.Context) string { if !data.RouterIdIp.IsNull() && !data.RouterIdIp.IsUnknown() { body, _ = sjson.Set(body, helpers.LastElement(data.getPath())+"."+"bgp.router-id.ip-id", data.RouterIdIp.ValueString()) } + if !data.BgpGracefulRestart.IsNull() && !data.BgpGracefulRestart.IsUnknown() { + if data.BgpGracefulRestart.ValueBool() { + body, _ = sjson.Set(body, helpers.LastElement(data.getPath())+"."+"bgp.gr-options.graceful-restart", map[string]string{}) + } + } + if !data.BgpUpdateDelay.IsNull() && !data.BgpUpdateDelay.IsUnknown() { + body, _ = sjson.Set(body, helpers.LastElement(data.getPath())+"."+"bgp.update-delay", strconv.FormatInt(data.BgpUpdateDelay.ValueInt64(), 10)) + } return body } @@ -142,6 +154,20 @@ func (data *BGP) updateFromBody(ctx context.Context, res gjson.Result) { } else { data.RouterIdIp = types.StringNull() } + if value := res.Get(prefix + "bgp.gr-options.graceful-restart"); !data.BgpGracefulRestart.IsNull() { + if value.Exists() { + data.BgpGracefulRestart = types.BoolValue(true) + } else { + data.BgpGracefulRestart = types.BoolValue(false) + } + } else { + data.BgpGracefulRestart = types.BoolNull() + } + if value := res.Get(prefix + "bgp.update-delay"); value.Exists() && !data.BgpUpdateDelay.IsNull() { + data.BgpUpdateDelay = types.Int64Value(value.Int()) + } else { + data.BgpUpdateDelay = types.Int64Null() + } } // End of section. //template:end updateFromBody @@ -169,6 +195,14 @@ func (data *BGP) fromBody(ctx context.Context, res gjson.Result) { if value := res.Get(prefix + "bgp.router-id.ip-id"); value.Exists() { data.RouterIdIp = types.StringValue(value.String()) } + if value := res.Get(prefix + "bgp.gr-options.graceful-restart"); value.Exists() { + data.BgpGracefulRestart = types.BoolValue(true) + } else { + data.BgpGracefulRestart = types.BoolValue(false) + } + if value := res.Get(prefix + "bgp.update-delay"); value.Exists() { + data.BgpUpdateDelay = types.Int64Value(value.Int()) + } } // End of section. //template:end fromBody @@ -196,6 +230,14 @@ func (data *BGPData) fromBody(ctx context.Context, res gjson.Result) { if value := res.Get(prefix + "bgp.router-id.ip-id"); value.Exists() { data.RouterIdIp = types.StringValue(value.String()) } + if value := res.Get(prefix + "bgp.gr-options.graceful-restart"); value.Exists() { + data.BgpGracefulRestart = types.BoolValue(true) + } else { + data.BgpGracefulRestart = types.BoolValue(false) + } + if value := res.Get(prefix + "bgp.update-delay"); value.Exists() { + data.BgpUpdateDelay = types.Int64Value(value.Int()) + } } // End of section. //template:end fromBodyData @@ -204,6 +246,12 @@ func (data *BGPData) fromBody(ctx context.Context, res gjson.Result) { func (data *BGP) getDeletedItems(ctx context.Context, state BGP) []string { deletedItems := make([]string, 0) + if !state.BgpUpdateDelay.IsNull() && data.BgpUpdateDelay.IsNull() { + deletedItems = append(deletedItems, fmt.Sprintf("%v/bgp/update-delay", state.getPath())) + } + if !state.BgpGracefulRestart.IsNull() && data.BgpGracefulRestart.IsNull() { + deletedItems = append(deletedItems, fmt.Sprintf("%v/bgp/gr-options/graceful-restart", state.getPath())) + } if !state.RouterIdIp.IsNull() && data.RouterIdIp.IsNull() { deletedItems = append(deletedItems, fmt.Sprintf("%v/bgp/router-id/ip-id", state.getPath())) } @@ -226,6 +274,9 @@ func (data *BGP) getDeletedItems(ctx context.Context, state BGP) []string { func (data *BGP) getEmptyLeafsDelete(ctx context.Context) []string { emptyLeafsDelete := make([]string, 0) + if !data.BgpGracefulRestart.IsNull() && !data.BgpGracefulRestart.ValueBool() { + emptyLeafsDelete = append(emptyLeafsDelete, fmt.Sprintf("%v/bgp/gr-options/graceful-restart", data.getPath())) + } return emptyLeafsDelete } @@ -236,6 +287,12 @@ func (data *BGP) getEmptyLeafsDelete(ctx context.Context) []string { func (data *BGP) getDeletePaths(ctx context.Context) []string { var deletePaths []string + if !data.BgpUpdateDelay.IsNull() { + deletePaths = append(deletePaths, fmt.Sprintf("%v/bgp/update-delay", data.getPath())) + } + if !data.BgpGracefulRestart.IsNull() { + deletePaths = append(deletePaths, fmt.Sprintf("%v/bgp/gr-options/graceful-restart", data.getPath())) + } if !data.RouterIdIp.IsNull() { deletePaths = append(deletePaths, fmt.Sprintf("%v/bgp/router-id/ip-id", data.getPath())) } diff --git a/internal/provider/resource_iosxe_bgp.go b/internal/provider/resource_iosxe_bgp.go index e55feeced..c2de3f869 100644 --- a/internal/provider/resource_iosxe_bgp.go +++ b/internal/provider/resource_iosxe_bgp.go @@ -115,6 +115,17 @@ func (r *BGPResource) Schema(ctx context.Context, req resource.SchemaRequest, re stringvalidator.RegexMatches(regexp.MustCompile(`(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(%[\p{N}\p{L}]+)?`), ""), }, }, + "bgp_graceful_restart": schema.BoolAttribute{ + MarkdownDescription: helpers.NewAttributeDescription("Graceful restart capability parameters").String, + Optional: true, + }, + "bgp_update_delay": schema.Int64Attribute{ + MarkdownDescription: helpers.NewAttributeDescription("Set the max initial delay for sending update").AddIntegerRangeDescription(1, 3600).String, + Optional: true, + Validators: []validator.Int64{ + int64validator.Between(1, 3600), + }, + }, }, } } diff --git a/internal/provider/resource_iosxe_bgp_test.go b/internal/provider/resource_iosxe_bgp_test.go index 6940535d8..1b8df3890 100644 --- a/internal/provider/resource_iosxe_bgp_test.go +++ b/internal/provider/resource_iosxe_bgp_test.go @@ -37,6 +37,9 @@ func TestAccIosxeBGP(t *testing.T) { checks = append(checks, resource.TestCheckResourceAttr("iosxe_bgp.test", "asn", "65000")) checks = append(checks, resource.TestCheckResourceAttr("iosxe_bgp.test", "default_ipv4_unicast", "false")) checks = append(checks, resource.TestCheckResourceAttr("iosxe_bgp.test", "log_neighbor_changes", "true")) + checks = append(checks, resource.TestCheckResourceAttr("iosxe_bgp.test", "router_id_ip", "172.16.255.1")) + checks = append(checks, resource.TestCheckResourceAttr("iosxe_bgp.test", "bgp_graceful_restart", "true")) + checks = append(checks, resource.TestCheckResourceAttr("iosxe_bgp.test", "bgp_update_delay", "200")) checks = append(checks, resource.TestCheckResourceAttr("iosxe_bgp.test", "router_id_loopback", "100")) resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -110,6 +113,9 @@ func testAccIosxeBGPConfig_all() string { config += ` asn = "65000"` + "\n" config += ` default_ipv4_unicast = false` + "\n" config += ` log_neighbor_changes = true` + "\n" + config += ` router_id_ip = "172.16.255.1"` + "\n" + config += ` bgp_graceful_restart = true` + "\n" + config += ` bgp_update_delay = 200` + "\n" config += ` router_id_loopback = 100` + "\n" config += ` depends_on = [iosxe_restconf.PreReq0, ]` + "\n" config += `}` + "\n"