diff --git a/CHANGELOG.md b/CHANGELOG.md index 07b10179..107be01c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,10 @@ - Add `iosxr_rd_set` resource and data source - Add `contact` and `location` attributes to `iosxr_snmp_server` resource and data source - Add `police_conform_action_transmit`, `police_conform_action_drop`, `police_exceed_action_transmit`, `police_exceed_action_drop`, `police_violate_action_transmit`, `police_violate_action_drop` attributes to `iosxr_policy_map_qos` resource and data source +- Add `iosxr_bfd` resource and data source +- Add `iosxr_flow_exporter_map` resource and data source + + ## 0.2.1 diff --git a/docs/data-sources/bfd.md b/docs/data-sources/bfd.md new file mode 100644 index 00000000..b7ce37e8 --- /dev/null +++ b/docs/data-sources/bfd.md @@ -0,0 +1,75 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "iosxr_bfd Data Source - terraform-provider-iosxr" +subcategory: "System" +description: |- + This data source can read the BFD configuration. +--- + +# iosxr_bfd (Data Source) + +This data source can read the BFD configuration. + +## Example Usage + +```terraform +data "iosxr_bfd" "example" { +} +``` + + +## Schema + +### Optional + +- `device` (String) A device name from the provider configuration. + +### Read-Only + +- `bundle_coexistence_bob_blb_inherit` (Boolean) Use inheritence mechanism +- `bundle_coexistence_bob_blb_logical` (Boolean) Use BFD logical Bundle natively +- `dampening_bundle_member_initial_wait` (Number) Initial delay before bringing up session +- `dampening_bundle_member_l3_only_mode` (Boolean) Apply immediate dampening and only when failure is L3 specific +- `dampening_bundle_member_maximum_wait` (Number) Maximum delay before bringing up session +- `dampening_bundle_member_secondary_wait` (Number) Secondary delay before bringing up session +- `dampening_disable` (Boolean) Disable BFD dampening +- `dampening_extensions_down_monitoring` (Boolean) Enable DOWN state session monitoring extensions +- `dampening_initial_wait` (Number) Initial delay before bringing up session +- `dampening_maximum_wait` (Number) Maximum delay before bringing up session +- `dampening_secondary_wait` (Number) Secondary delay before bringing up session +- `dampening_threshold` (Number) Stability threshold to enable dampening +- `echo_disable` (Boolean) Disable BFD echo mode +- `echo_ipv4_bundle_per_member_minimum_interval_preferred_minimum_interval` (Number) The preferred minimum interval (in ms) for the BFD session +- `echo_ipv4_source` (String) BFD echo source IP address +- `echo_latency_detect_count` (Number) Count of consecutive bad latency packets to take session down +- `echo_latency_detect_percentage` (Number) Percentage of detection time to consider as bad latency +- `echo_startup_validate_force` (Boolean) Ignore remote 'Required Min Echo RX Interval' setting +- `id` (String) The path of the retrieved object. +- `interfaces` (Attributes List) Configure BFD on an interface (see [below for nested schema](#nestedatt--interfaces)) +- `ipv6_checksum_disable` (Boolean) Disable BFD checksum +- `multihop_ttl_drop_threshold` (Number) TTL Drop Threshold +- `multipath_locations` (Attributes List) Specify a location (see [below for nested schema](#nestedatt--multipath_locations)) +- `trap_singlehop_pre_mapped` (Boolean) Configure BFD trap pre-mapped + + +### Nested Schema for `interfaces` + +Read-Only: + +- `disable` (Boolean) Disable BFD for this interface +- `echo_disable` (Boolean) Disable BFD echo mode for this interface +- `echo_ipv4_source` (String) BFD echo source IP address +- `interface_name` (String) Configure BFD on an interface +- `ipv6_checksum_disable` (Boolean) Disable BFD ipv6 checksum mode for this interface +- `local_address` (String) Local address to be used by BFD for this interface +- `multiplier` (Number) BFD multiplier for this interface +- `rx_interval` (Number) BFD RX Interval for this interface in microseconds +- `tx_interval` (Number) BFD TX Interval for this interface in microseconds + + + +### Nested Schema for `multipath_locations` + +Read-Only: + +- `location_name` (String) Specify a location diff --git a/docs/data-sources/flow_exporter_map.md b/docs/data-sources/flow_exporter_map.md new file mode 100644 index 00000000..255b9f1c --- /dev/null +++ b/docs/data-sources/flow_exporter_map.md @@ -0,0 +1,53 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "iosxr_flow_exporter_map Data Source - terraform-provider-iosxr" +subcategory: "Flow" +description: |- + This data source can read the Flow Exporter Map configuration. +--- + +# iosxr_flow_exporter_map (Data Source) + +This data source can read the Flow Exporter Map configuration. + +## Example Usage + +```terraform +data "iosxr_flow_exporter_map" "example" { +} +``` + + +## Schema + +### Optional + +- `device` (String) A device name from the provider configuration. + +### Read-Only + +- `exporter_maps` (Attributes List) Exporter map name - maximum 32 characters (see [below for nested schema](#nestedatt--exporter_maps)) +- `id` (String) The path of the retrieved object. + + +### Nested Schema for `exporter_maps` + +Read-Only: + +- `destination_ipv4_address` (String) Destination IPv4 address +- `destination_ipv6_address` (String) Destination IPv6 address +- `destination_vrf` (String) Configure VRF to be used for reaching export destination +- `dfbit_set` (Boolean) Set Export Packet Do Not Fragment Flag +- `dscp` (Number) Specify DSCP value for ipv4 export packets or traffic-class for ipv6 export packets +- `exporter_map_name` (String) Exporter map name - maximum 32 characters +- `packet_length` (Number) Export Packet maximum L3 length, should conform to outgoing interface mtu +- `source` (String) Source interface +- `transport_udp` (Number) Use UDP as transport protocol +- `version_export_format` (String) Specify export format +- `version_options_class_table_timeout` (Number) Specify export timeout +- `version_options_interface_table_timeout` (Number) Specify export timeout +- `version_options_sampler_table_timeout` (Number) Specify export timeout +- `version_options_vrf_table_timeout` (Number) Specify export timeout +- `version_template_data_timeout` (Number) Specify custom timeout for the template +- `version_template_options_timeout` (Number) Specify custom timeout for the template +- `version_template_timeout` (Number) Specify custom timeout for the template diff --git a/docs/guides/changelog.md b/docs/guides/changelog.md index ee1469d4..34f4a7f8 100644 --- a/docs/guides/changelog.md +++ b/docs/guides/changelog.md @@ -33,6 +33,10 @@ description: |- - Add `iosxr_rd_set` resource and data source - Add `contact` and `location` attributes to `iosxr_snmp_server` resource and data source - Add `police_conform_action_transmit`, `police_conform_action_drop`, `police_exceed_action_transmit`, `police_exceed_action_drop`, `police_violate_action_transmit`, `police_violate_action_drop` attributes to `iosxr_policy_map_qos` resource and data source +- Add `iosxr_bfd` resource and data source +- Add `iosxr_flow_exporter_map` resource and data source + + ## 0.2.1 diff --git a/docs/resources/bfd.md b/docs/resources/bfd.md new file mode 100644 index 00000000..9dd7c444 --- /dev/null +++ b/docs/resources/bfd.md @@ -0,0 +1,141 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "iosxr_bfd Resource - terraform-provider-iosxr" +subcategory: "System" +description: |- + This resource can manage the BFD configuration. +--- + +# iosxr_bfd (Resource) + +This resource can manage the BFD configuration. + +## Example Usage + +```terraform +resource "iosxr_bfd" "example" { + echo_disable = true + echo_latency_detect_percentage = 200 + echo_latency_detect_count = 10 + echo_startup_validate_force = true + echo_ipv4_source = "10.1.1.1" + echo_ipv4_bundle_per_member_minimum_interval_preferred_minimum_interval = 200 + trap_singlehop_pre_mapped = true + multipath_locations = [ + { + location_name = "0/0/CPU0" + } + ] + multihop_ttl_drop_threshold = 200 + dampening_initial_wait = 3600 + dampening_secondary_wait = 3200 + dampening_maximum_wait = 3100 + dampening_threshold = 60000 + dampening_extensions_down_monitoring = true + dampening_disable = true + dampening_bundle_member_l3_only_mode = true + dampening_bundle_member_initial_wait = 5184 + dampening_bundle_member_secondary_wait = 6184 + dampening_bundle_member_maximum_wait = 7184 + bundle_coexistence_bob_blb_inherit = false + bundle_coexistence_bob_blb_logical = true + interfaces = [ + { + interface_name = "GigabitEthernet0/0/0/0" + echo_disable = true + echo_ipv4_source = "12.1.1.1" + ipv6_checksum_disable = true + disable = true + local_address = "33.33.31.1" + tx_interval = 3200 + rx_interval = 4200 + multiplier = 40 + } + ] + ipv6_checksum_disable = true +} +``` + + +## Schema + +### Optional + +- `bundle_coexistence_bob_blb_inherit` (Boolean) Use inheritence mechanism +- `bundle_coexistence_bob_blb_logical` (Boolean) Use BFD logical Bundle natively +- `dampening_bundle_member_initial_wait` (Number) Initial delay before bringing up session + - Range: `1`-`518400000` +- `dampening_bundle_member_l3_only_mode` (Boolean) Apply immediate dampening and only when failure is L3 specific +- `dampening_bundle_member_maximum_wait` (Number) Maximum delay before bringing up session + - Range: `1`-`518400000` +- `dampening_bundle_member_secondary_wait` (Number) Secondary delay before bringing up session + - Range: `1`-`518400000` +- `dampening_disable` (Boolean) Disable BFD dampening +- `dampening_extensions_down_monitoring` (Boolean) Enable DOWN state session monitoring extensions +- `dampening_initial_wait` (Number) Initial delay before bringing up session + - Range: `1`-`3600000` +- `dampening_maximum_wait` (Number) Maximum delay before bringing up session + - Range: `1`-`3600000` +- `dampening_secondary_wait` (Number) Secondary delay before bringing up session + - Range: `1`-`3600000` +- `dampening_threshold` (Number) Stability threshold to enable dampening + - Range: `60000`-`3600000` +- `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. +- `echo_disable` (Boolean) Disable BFD echo mode +- `echo_ipv4_bundle_per_member_minimum_interval_preferred_minimum_interval` (Number) The preferred minimum interval (in ms) for the BFD session + - Range: `15`-`2000` +- `echo_ipv4_source` (String) BFD echo source IP address +- `echo_latency_detect_count` (Number) Count of consecutive bad latency packets to take session down + - Range: `1`-`10` +- `echo_latency_detect_percentage` (Number) Percentage of detection time to consider as bad latency + - Range: `100`-`250` +- `echo_startup_validate_force` (Boolean) Ignore remote 'Required Min Echo RX Interval' setting +- `interfaces` (Attributes List) Configure BFD on an interface (see [below for nested schema](#nestedatt--interfaces)) +- `ipv6_checksum_disable` (Boolean) Disable BFD checksum +- `multihop_ttl_drop_threshold` (Number) TTL Drop Threshold + - Range: `0`-`254` +- `multipath_locations` (Attributes List) Specify a location (see [below for nested schema](#nestedatt--multipath_locations)) +- `trap_singlehop_pre_mapped` (Boolean) Configure BFD trap pre-mapped + +### Read-Only + +- `id` (String) The path of the object. + + +### Nested Schema for `interfaces` + +Required: + +- `interface_name` (String) Configure BFD on an interface + +Optional: + +- `disable` (Boolean) Disable BFD for this interface +- `echo_disable` (Boolean) Disable BFD echo mode for this interface +- `echo_ipv4_source` (String) BFD echo source IP address +- `ipv6_checksum_disable` (Boolean) Disable BFD ipv6 checksum mode for this interface +- `local_address` (String) Local address to be used by BFD for this interface +- `multiplier` (Number) BFD multiplier for this interface + - Range: `2`-`50` +- `rx_interval` (Number) BFD RX Interval for this interface in microseconds + - Range: `3000`-`30000000` +- `tx_interval` (Number) BFD TX Interval for this interface in microseconds + - Range: `3000`-`30000000` + + + +### Nested Schema for `multipath_locations` + +Required: + +- `location_name` (String) Specify a location + +## Import + +Import is supported using the following syntax: + +```shell +terraform import iosxr_bfd.example "Cisco-IOS-XR-um-bfd-sbfd-cfg:/bfd" +``` diff --git a/docs/resources/flow_exporter_map.md b/docs/resources/flow_exporter_map.md new file mode 100644 index 00000000..87fad12c --- /dev/null +++ b/docs/resources/flow_exporter_map.md @@ -0,0 +1,96 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "iosxr_flow_exporter_map Resource - terraform-provider-iosxr" +subcategory: "Flow" +description: |- + This resource can manage the Flow Exporter Map configuration. +--- + +# iosxr_flow_exporter_map (Resource) + +This resource can manage the Flow Exporter Map configuration. + +## Example Usage + +```terraform +resource "iosxr_flow_exporter_map" "example" { + exporter_maps = [ + { + exporter_map_name = "TEST" + destination_ipv4_address = "10.1.1.1" + destination_ipv6_address = "1::1" + destination_vrf = "28" + source = "10.1.1.4" + dscp = 62 + packet_length = 512 + transport_udp = 1033 + dfbit_set = true + version_export_format = "true" + version_template_data_timeout = 1024 + version_template_options_timeout = 3033 + version_template_timeout = 2222 + version_options_interface_table_timeout = 6048 + version_options_sampler_table_timeout = 4096 + version_options_class_table_timeout = 255 + version_options_vrf_table_timeout = 122 + } + ] +} +``` + + +## Schema + +### Optional + +- `device` (String) A device name from the provider configuration. +- `exporter_maps` (Attributes List) Exporter map name - maximum 32 characters (see [below for nested schema](#nestedatt--exporter_maps)) + +### Read-Only + +- `id` (String) The path of the object. + + +### Nested Schema for `exporter_maps` + +Required: + +- `exporter_map_name` (String) Exporter map name - maximum 32 characters +- `version_export_format` (String) Specify export format + - Choices: `ipfix`, `protobuf`, `sflow`, `v9` + +Optional: + +- `destination_ipv4_address` (String) Destination IPv4 address +- `destination_ipv6_address` (String) Destination IPv6 address +- `destination_vrf` (String) Configure VRF to be used for reaching export destination +- `dfbit_set` (Boolean) Set Export Packet Do Not Fragment Flag +- `dscp` (Number) Specify DSCP value for ipv4 export packets or traffic-class for ipv6 export packets + - Range: `0`-`63` +- `packet_length` (Number) Export Packet maximum L3 length, should conform to outgoing interface mtu + - Range: `512`-`9000` +- `source` (String) Source interface +- `transport_udp` (Number) Use UDP as transport protocol + - Range: `1024`-`65535` +- `version_options_class_table_timeout` (Number) Specify export timeout + - Range: `1`-`604800` +- `version_options_interface_table_timeout` (Number) Specify export timeout + - Range: `1`-`604800` +- `version_options_sampler_table_timeout` (Number) Specify export timeout + - Range: `1`-`604800` +- `version_options_vrf_table_timeout` (Number) Specify export timeout + - Range: `1`-`604800` +- `version_template_data_timeout` (Number) Specify custom timeout for the template + - Range: `1`-`604800` +- `version_template_options_timeout` (Number) Specify custom timeout for the template + - Range: `1`-`604800` +- `version_template_timeout` (Number) Specify custom timeout for the template + - Range: `1`-`604800` + +## Import + +Import is supported using the following syntax: + +```shell +terraform import iosxr_flow_exporter_map.example "Cisco-IOS-XR-um-flow-cfg:/flow/exporter-maps" +``` diff --git a/examples/data-sources/iosxr_bfd/data-source.tf b/examples/data-sources/iosxr_bfd/data-source.tf new file mode 100644 index 00000000..283a36f4 --- /dev/null +++ b/examples/data-sources/iosxr_bfd/data-source.tf @@ -0,0 +1,2 @@ +data "iosxr_bfd" "example" { +} diff --git a/examples/data-sources/iosxr_flow_exporter_map/data-source.tf b/examples/data-sources/iosxr_flow_exporter_map/data-source.tf new file mode 100644 index 00000000..cb42cec4 --- /dev/null +++ b/examples/data-sources/iosxr_flow_exporter_map/data-source.tf @@ -0,0 +1,2 @@ +data "iosxr_flow_exporter_map" "example" { +} diff --git a/examples/resources/iosxr_bfd/import.sh b/examples/resources/iosxr_bfd/import.sh new file mode 100644 index 00000000..b3d7c030 --- /dev/null +++ b/examples/resources/iosxr_bfd/import.sh @@ -0,0 +1 @@ +terraform import iosxr_bfd.example "Cisco-IOS-XR-um-bfd-sbfd-cfg:/bfd" diff --git a/examples/resources/iosxr_bfd/resource.tf b/examples/resources/iosxr_bfd/resource.tf new file mode 100644 index 00000000..cd8a8fa1 --- /dev/null +++ b/examples/resources/iosxr_bfd/resource.tf @@ -0,0 +1,41 @@ +resource "iosxr_bfd" "example" { + echo_disable = true + echo_latency_detect_percentage = 200 + echo_latency_detect_count = 10 + echo_startup_validate_force = true + echo_ipv4_source = "10.1.1.1" + echo_ipv4_bundle_per_member_minimum_interval_preferred_minimum_interval = 200 + trap_singlehop_pre_mapped = true + multipath_locations = [ + { + location_name = "0/0/CPU0" + } + ] + multihop_ttl_drop_threshold = 200 + dampening_initial_wait = 3600 + dampening_secondary_wait = 3200 + dampening_maximum_wait = 3100 + dampening_threshold = 60000 + dampening_extensions_down_monitoring = true + dampening_disable = true + dampening_bundle_member_l3_only_mode = true + dampening_bundle_member_initial_wait = 5184 + dampening_bundle_member_secondary_wait = 6184 + dampening_bundle_member_maximum_wait = 7184 + bundle_coexistence_bob_blb_inherit = false + bundle_coexistence_bob_blb_logical = true + interfaces = [ + { + interface_name = "GigabitEthernet0/0/0/0" + echo_disable = true + echo_ipv4_source = "12.1.1.1" + ipv6_checksum_disable = true + disable = true + local_address = "33.33.31.1" + tx_interval = 3200 + rx_interval = 4200 + multiplier = 40 + } + ] + ipv6_checksum_disable = true +} diff --git a/examples/resources/iosxr_flow_exporter_map/import.sh b/examples/resources/iosxr_flow_exporter_map/import.sh new file mode 100644 index 00000000..95a28347 --- /dev/null +++ b/examples/resources/iosxr_flow_exporter_map/import.sh @@ -0,0 +1 @@ +terraform import iosxr_flow_exporter_map.example "Cisco-IOS-XR-um-flow-cfg:/flow/exporter-maps" diff --git a/examples/resources/iosxr_flow_exporter_map/resource.tf b/examples/resources/iosxr_flow_exporter_map/resource.tf new file mode 100644 index 00000000..953cb32c --- /dev/null +++ b/examples/resources/iosxr_flow_exporter_map/resource.tf @@ -0,0 +1,23 @@ +resource "iosxr_flow_exporter_map" "example" { + exporter_maps = [ + { + exporter_map_name = "TEST" + destination_ipv4_address = "10.1.1.1" + destination_ipv6_address = "1::1" + destination_vrf = "28" + source = "10.1.1.4" + dscp = 62 + packet_length = 512 + transport_udp = 1033 + dfbit_set = true + version_export_format = "true" + version_template_data_timeout = 1024 + version_template_options_timeout = 3033 + version_template_timeout = 2222 + version_options_interface_table_timeout = 6048 + version_options_sampler_table_timeout = 4096 + version_options_class_table_timeout = 255 + version_options_vrf_table_timeout = 122 + } + ] +} diff --git a/gen/definitions/bfd.yaml b/gen/definitions/bfd.yaml new file mode 100644 index 00000000..400a4f6b --- /dev/null +++ b/gen/definitions/bfd.yaml @@ -0,0 +1,78 @@ +--- +name: BFD +path: Cisco-IOS-XR-um-bfd-sbfd-cfg:/bfd +doc_category: System +attributes: + - yang_name: echo/disable + example: true + - yang_name: echo/latency/detect/percentage + example: 200 + - yang_name: echo/latency/detect/count + example: 10 + - yang_name: echo/startup/validate/force + example: true + - yang_name: echo/ipv4/source + example: 10.1.1.1 + - yang_name: echo/ipv4/bundle-per-member/minimum-interval/preferred-minimum-interval + example: 200 + - yang_name: trap/singlehop/pre-mapped + example: true + - yang_name: multipath/include/locations/location + tf_name: multipath_locations + type: List + attributes: + - yang_name: location-name + id: true + example: 0/0/CPU0 + + - yang_name: multihop/ttl-drop-threshold + example: 200 + - yang_name: dampening/initial-wait + example: 3600 + - yang_name: dampening/secondary-wait + example: 3200 + - yang_name: dampening/maximum-wait + example: 3100 + - yang_name: dampening/threshold + example: 60000 + - yang_name: dampening/extensions/down-monitoring + example: true + - yang_name: dampening/disable + example: true + - yang_name: dampening/bundle-member/l3-only-mode + example: true + - yang_name: dampening/bundle-member/initial-wait + example: 5184 + - yang_name: dampening/bundle-member/secondary-wait + example: 6184 + - yang_name: dampening/bundle-member/maximum-wait + example: 7184 + - yang_name: bundle/coexistence/bob-blb/inherit + example: false + - yang_name: bundle/coexistence/bob-blb/logical + example: true + - yang_name: interfaces/interface + tf_name: interfaces + type: List + attributes: + - yang_name: interface-name + id: true + example: GigabitEthernet0/0/0/0 + - yang_name: echo/disable + example: true + - yang_name: echo/ipv4/source + example: 12.1.1.1 + - yang_name: ipv6/checksum/disable + example: true + - yang_name: disable + example: true + - yang_name: local-address + example: 33.33.31.1 + - yang_name: tx-interval + example: 3200 + - yang_name: rx-interval + example: 4200 + - yang_name: multiplier + example: 40 + - yang_name: ipv6/checksum/disable + example: true \ No newline at end of file diff --git a/gen/definitions/flow_exporter_map.yaml b/gen/definitions/flow_exporter_map.yaml new file mode 100644 index 00000000..015036fa --- /dev/null +++ b/gen/definitions/flow_exporter_map.yaml @@ -0,0 +1,50 @@ +--- +name: Flow Exporter Map +path: Cisco-IOS-XR-um-flow-cfg:/flow/exporter-maps +doc_category: Flow +no_delete_attributes: true +attributes: + - yang_name: exporter-map + tf_name: exporter_maps + type: List + attributes: + - yang_name: exporter-map-name + id: true + example: TEST + - yang_name: destination/ipv4-address + example: 10.1.1.1 + - yang_name: destination/ipv6-address + example: 1::1 + - yang_name: destination/vrf + example: 28 + - yang_name: source + example: 10.1.1.4 + - yang_name: dscp + example: 62 + - yang_name: packet-length + example: 512 + # - yang_name: source-address/ipv4-address + # example: 20.1.1.1 + # - yang_name: source-address/ipv6-address + # example: 2::2 + # exclude_test: true + - yang_name: transport/udp + example: 1033 + - yang_name: dfbit/set + example: true + - yang_name: version/export-format + example: true + - yang_name: version/template/data/timeout + example: 1024 + - yang_name: version/template/options/timeout + example: 3033 + - yang_name: version/template/timeout + example: 2222 + - yang_name: version/options/interface-table/timeout + example: 6048 + - yang_name: version/options/sampler-table/timeout + example: 4096 + - yang_name: version/options/class-table/timeout + example: 255 + - yang_name: version/options/vrf-table/timeout + example: 122 \ No newline at end of file diff --git a/gen/load_models.go b/gen/load_models.go index 3533cbec..42de1644 100644 --- a/gen/load_models.go +++ b/gen/load_models.go @@ -56,6 +56,7 @@ var models = []string{ "https://raw.githubusercontent.com/YangModels/yang/main/vendor/cisco/xr/761/Cisco-IOS-XR-um-traps-entity-state-cfg.yang", "https://raw.githubusercontent.com/YangModels/yang/main/vendor/cisco/xr/761/Cisco-IOS-XR-um-traps-entity-redundancy-cfg.yang", "https://raw.githubusercontent.com/YangModels/yang/main/vendor/cisco/xr/761/Cisco-IOS-XR-um-l2vpn-cfg.yang", + "https://raw.githubusercontent.com/YangModels/yang/main/vendor/cisco/xr/761/Cisco-IOS-XR-um-flow-cfg.yang", "https://raw.githubusercontent.com/YangModels/yang/main/vendor/cisco/xr/761/Cisco-IOS-XR-um-mibs-ifmib-cfg.yang", "https://raw.githubusercontent.com/YangModels/yang/main/vendor/cisco/xr/761/Cisco-IOS-XR-um-traps-mpls-ldp-cfg.yang", "https://raw.githubusercontent.com/YangModels/yang/main/vendor/cisco/xr/761/Cisco-IOS-XR-um-ipv4-access-list-cfg.yang", diff --git a/internal/provider/data_source_iosxr_bfd.go b/internal/provider/data_source_iosxr_bfd.go new file mode 100644 index 00000000..2025237a --- /dev/null +++ b/internal/provider/data_source_iosxr_bfd.go @@ -0,0 +1,242 @@ +// 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 + +import ( + "context" + "fmt" + + "github.com/CiscoDevNet/terraform-provider-iosxr/internal/provider/client" + "github.com/hashicorp/terraform-plugin-framework/datasource" + "github.com/hashicorp/terraform-plugin-framework/datasource/schema" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-log/tflog" +) + +// Ensure the implementation satisfies the expected interfaces. +var ( + _ datasource.DataSource = &BFDDataSource{} + _ datasource.DataSourceWithConfigure = &BFDDataSource{} +) + +func NewBFDDataSource() datasource.DataSource { + return &BFDDataSource{} +} + +type BFDDataSource struct { + client *client.Client +} + +func (d *BFDDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_bfd" +} + +func (d *BFDDataSource) 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 BFD 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, + }, + "echo_disable": schema.BoolAttribute{ + MarkdownDescription: "Disable BFD echo mode", + Computed: true, + }, + "echo_latency_detect_percentage": schema.Int64Attribute{ + MarkdownDescription: "Percentage of detection time to consider as bad latency", + Computed: true, + }, + "echo_latency_detect_count": schema.Int64Attribute{ + MarkdownDescription: "Count of consecutive bad latency packets to take session down", + Computed: true, + }, + "echo_startup_validate_force": schema.BoolAttribute{ + MarkdownDescription: "Ignore remote 'Required Min Echo RX Interval' setting", + Computed: true, + }, + "echo_ipv4_source": schema.StringAttribute{ + MarkdownDescription: "BFD echo source IP address", + Computed: true, + }, + "echo_ipv4_bundle_per_member_minimum_interval_preferred_minimum_interval": schema.Int64Attribute{ + MarkdownDescription: "The preferred minimum interval (in ms) for the BFD session", + Computed: true, + }, + "trap_singlehop_pre_mapped": schema.BoolAttribute{ + MarkdownDescription: "Configure BFD trap pre-mapped", + Computed: true, + }, + "multipath_locations": schema.ListNestedAttribute{ + MarkdownDescription: "Specify a location", + Computed: true, + NestedObject: schema.NestedAttributeObject{ + Attributes: map[string]schema.Attribute{ + "location_name": schema.StringAttribute{ + MarkdownDescription: "Specify a location", + Computed: true, + }, + }, + }, + }, + "multihop_ttl_drop_threshold": schema.Int64Attribute{ + MarkdownDescription: "TTL Drop Threshold", + Computed: true, + }, + "dampening_initial_wait": schema.Int64Attribute{ + MarkdownDescription: "Initial delay before bringing up session", + Computed: true, + }, + "dampening_secondary_wait": schema.Int64Attribute{ + MarkdownDescription: "Secondary delay before bringing up session", + Computed: true, + }, + "dampening_maximum_wait": schema.Int64Attribute{ + MarkdownDescription: "Maximum delay before bringing up session", + Computed: true, + }, + "dampening_threshold": schema.Int64Attribute{ + MarkdownDescription: "Stability threshold to enable dampening", + Computed: true, + }, + "dampening_extensions_down_monitoring": schema.BoolAttribute{ + MarkdownDescription: "Enable DOWN state session monitoring extensions", + Computed: true, + }, + "dampening_disable": schema.BoolAttribute{ + MarkdownDescription: "Disable BFD dampening", + Computed: true, + }, + "dampening_bundle_member_l3_only_mode": schema.BoolAttribute{ + MarkdownDescription: "Apply immediate dampening and only when failure is L3 specific", + Computed: true, + }, + "dampening_bundle_member_initial_wait": schema.Int64Attribute{ + MarkdownDescription: "Initial delay before bringing up session", + Computed: true, + }, + "dampening_bundle_member_secondary_wait": schema.Int64Attribute{ + MarkdownDescription: "Secondary delay before bringing up session", + Computed: true, + }, + "dampening_bundle_member_maximum_wait": schema.Int64Attribute{ + MarkdownDescription: "Maximum delay before bringing up session", + Computed: true, + }, + "bundle_coexistence_bob_blb_inherit": schema.BoolAttribute{ + MarkdownDescription: "Use inheritence mechanism", + Computed: true, + }, + "bundle_coexistence_bob_blb_logical": schema.BoolAttribute{ + MarkdownDescription: "Use BFD logical Bundle natively", + Computed: true, + }, + "interfaces": schema.ListNestedAttribute{ + MarkdownDescription: "Configure BFD on an interface", + Computed: true, + NestedObject: schema.NestedAttributeObject{ + Attributes: map[string]schema.Attribute{ + "interface_name": schema.StringAttribute{ + MarkdownDescription: "Configure BFD on an interface", + Computed: true, + }, + "echo_disable": schema.BoolAttribute{ + MarkdownDescription: "Disable BFD echo mode for this interface", + Computed: true, + }, + "echo_ipv4_source": schema.StringAttribute{ + MarkdownDescription: "BFD echo source IP address", + Computed: true, + }, + "ipv6_checksum_disable": schema.BoolAttribute{ + MarkdownDescription: "Disable BFD ipv6 checksum mode for this interface", + Computed: true, + }, + "disable": schema.BoolAttribute{ + MarkdownDescription: "Disable BFD for this interface", + Computed: true, + }, + "local_address": schema.StringAttribute{ + MarkdownDescription: "Local address to be used by BFD for this interface", + Computed: true, + }, + "tx_interval": schema.Int64Attribute{ + MarkdownDescription: "BFD TX Interval for this interface in microseconds", + Computed: true, + }, + "rx_interval": schema.Int64Attribute{ + MarkdownDescription: "BFD RX Interval for this interface in microseconds", + Computed: true, + }, + "multiplier": schema.Int64Attribute{ + MarkdownDescription: "BFD multiplier for this interface", + Computed: true, + }, + }, + }, + }, + "ipv6_checksum_disable": schema.BoolAttribute{ + MarkdownDescription: "Disable BFD checksum", + Computed: true, + }, + }, + } +} + +func (d *BFDDataSource) Configure(_ context.Context, req datasource.ConfigureRequest, _ *datasource.ConfigureResponse) { + if req.ProviderData == nil { + return + } + + d.client = req.ProviderData.(*client.Client) +} + +func (d *BFDDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { + var config BFDData + + // 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())) + + getResp, diags := d.client.Get(ctx, config.Device.ValueString(), config.getPath()) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + config.fromBody(ctx, getResp.Notification[0].Update[0].Val.GetJsonIetfVal()) + 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...) +} diff --git a/internal/provider/data_source_iosxr_bfd_test.go b/internal/provider/data_source_iosxr_bfd_test.go new file mode 100644 index 00000000..3e340b77 --- /dev/null +++ b/internal/provider/data_source_iosxr_bfd_test.go @@ -0,0 +1,119 @@ +// 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 + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" +) + +func TestAccDataSourceIosxrBFD(t *testing.T) { + var checks []resource.TestCheckFunc + checks = append(checks, resource.TestCheckResourceAttr("data.iosxr_bfd.test", "echo_disable", "true")) + checks = append(checks, resource.TestCheckResourceAttr("data.iosxr_bfd.test", "echo_latency_detect_percentage", "200")) + checks = append(checks, resource.TestCheckResourceAttr("data.iosxr_bfd.test", "echo_latency_detect_count", "10")) + checks = append(checks, resource.TestCheckResourceAttr("data.iosxr_bfd.test", "echo_startup_validate_force", "true")) + checks = append(checks, resource.TestCheckResourceAttr("data.iosxr_bfd.test", "echo_ipv4_source", "10.1.1.1")) + checks = append(checks, resource.TestCheckResourceAttr("data.iosxr_bfd.test", "echo_ipv4_bundle_per_member_minimum_interval_preferred_minimum_interval", "200")) + checks = append(checks, resource.TestCheckResourceAttr("data.iosxr_bfd.test", "trap_singlehop_pre_mapped", "true")) + checks = append(checks, resource.TestCheckResourceAttr("data.iosxr_bfd.test", "multipath_locations.0.location_name", "0/0/CPU0")) + checks = append(checks, resource.TestCheckResourceAttr("data.iosxr_bfd.test", "multihop_ttl_drop_threshold", "200")) + checks = append(checks, resource.TestCheckResourceAttr("data.iosxr_bfd.test", "dampening_initial_wait", "3600")) + checks = append(checks, resource.TestCheckResourceAttr("data.iosxr_bfd.test", "dampening_secondary_wait", "3200")) + checks = append(checks, resource.TestCheckResourceAttr("data.iosxr_bfd.test", "dampening_maximum_wait", "3100")) + checks = append(checks, resource.TestCheckResourceAttr("data.iosxr_bfd.test", "dampening_threshold", "60000")) + checks = append(checks, resource.TestCheckResourceAttr("data.iosxr_bfd.test", "dampening_extensions_down_monitoring", "true")) + checks = append(checks, resource.TestCheckResourceAttr("data.iosxr_bfd.test", "dampening_disable", "true")) + checks = append(checks, resource.TestCheckResourceAttr("data.iosxr_bfd.test", "dampening_bundle_member_l3_only_mode", "true")) + checks = append(checks, resource.TestCheckResourceAttr("data.iosxr_bfd.test", "dampening_bundle_member_initial_wait", "5184")) + checks = append(checks, resource.TestCheckResourceAttr("data.iosxr_bfd.test", "dampening_bundle_member_secondary_wait", "6184")) + checks = append(checks, resource.TestCheckResourceAttr("data.iosxr_bfd.test", "dampening_bundle_member_maximum_wait", "7184")) + checks = append(checks, resource.TestCheckResourceAttr("data.iosxr_bfd.test", "bundle_coexistence_bob_blb_inherit", "false")) + checks = append(checks, resource.TestCheckResourceAttr("data.iosxr_bfd.test", "bundle_coexistence_bob_blb_logical", "true")) + checks = append(checks, resource.TestCheckResourceAttr("data.iosxr_bfd.test", "interfaces.0.interface_name", "GigabitEthernet0/0/0/0")) + checks = append(checks, resource.TestCheckResourceAttr("data.iosxr_bfd.test", "interfaces.0.echo_disable", "true")) + checks = append(checks, resource.TestCheckResourceAttr("data.iosxr_bfd.test", "interfaces.0.echo_ipv4_source", "12.1.1.1")) + checks = append(checks, resource.TestCheckResourceAttr("data.iosxr_bfd.test", "interfaces.0.ipv6_checksum_disable", "true")) + checks = append(checks, resource.TestCheckResourceAttr("data.iosxr_bfd.test", "interfaces.0.disable", "true")) + checks = append(checks, resource.TestCheckResourceAttr("data.iosxr_bfd.test", "interfaces.0.local_address", "33.33.31.1")) + checks = append(checks, resource.TestCheckResourceAttr("data.iosxr_bfd.test", "interfaces.0.tx_interval", "3200")) + checks = append(checks, resource.TestCheckResourceAttr("data.iosxr_bfd.test", "interfaces.0.rx_interval", "4200")) + checks = append(checks, resource.TestCheckResourceAttr("data.iosxr_bfd.test", "interfaces.0.multiplier", "40")) + checks = append(checks, resource.TestCheckResourceAttr("data.iosxr_bfd.test", "ipv6_checksum_disable", "true")) + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testAccDataSourceIosxrBFDConfig(), + Check: resource.ComposeTestCheckFunc(checks...), + }, + }, + }) +} + +func testAccDataSourceIosxrBFDConfig() string { + config := `resource "iosxr_bfd" "test" {` + "\n" + config += ` delete_mode = "attributes"` + "\n" + config += ` echo_disable = true` + "\n" + config += ` echo_latency_detect_percentage = 200` + "\n" + config += ` echo_latency_detect_count = 10` + "\n" + config += ` echo_startup_validate_force = true` + "\n" + config += ` echo_ipv4_source = "10.1.1.1"` + "\n" + config += ` echo_ipv4_bundle_per_member_minimum_interval_preferred_minimum_interval = 200` + "\n" + config += ` trap_singlehop_pre_mapped = true` + "\n" + config += ` multipath_locations = [{` + "\n" + config += ` location_name = "0/0/CPU0"` + "\n" + config += ` }]` + "\n" + config += ` multihop_ttl_drop_threshold = 200` + "\n" + config += ` dampening_initial_wait = 3600` + "\n" + config += ` dampening_secondary_wait = 3200` + "\n" + config += ` dampening_maximum_wait = 3100` + "\n" + config += ` dampening_threshold = 60000` + "\n" + config += ` dampening_extensions_down_monitoring = true` + "\n" + config += ` dampening_disable = true` + "\n" + config += ` dampening_bundle_member_l3_only_mode = true` + "\n" + config += ` dampening_bundle_member_initial_wait = 5184` + "\n" + config += ` dampening_bundle_member_secondary_wait = 6184` + "\n" + config += ` dampening_bundle_member_maximum_wait = 7184` + "\n" + config += ` bundle_coexistence_bob_blb_inherit = false` + "\n" + config += ` bundle_coexistence_bob_blb_logical = true` + "\n" + config += ` interfaces = [{` + "\n" + config += ` interface_name = "GigabitEthernet0/0/0/0"` + "\n" + config += ` echo_disable = true` + "\n" + config += ` echo_ipv4_source = "12.1.1.1"` + "\n" + config += ` ipv6_checksum_disable = true` + "\n" + config += ` disable = true` + "\n" + config += ` local_address = "33.33.31.1"` + "\n" + config += ` tx_interval = 3200` + "\n" + config += ` rx_interval = 4200` + "\n" + config += ` multiplier = 40` + "\n" + config += ` }]` + "\n" + config += ` ipv6_checksum_disable = true` + "\n" + config += `}` + "\n" + + config += ` + data "iosxr_bfd" "test" { + depends_on = [iosxr_bfd.test] + } + ` + return config +} diff --git a/internal/provider/data_source_iosxr_flow_exporter_map.go b/internal/provider/data_source_iosxr_flow_exporter_map.go new file mode 100644 index 00000000..ee61255c --- /dev/null +++ b/internal/provider/data_source_iosxr_flow_exporter_map.go @@ -0,0 +1,178 @@ +// 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 + +import ( + "context" + "fmt" + + "github.com/CiscoDevNet/terraform-provider-iosxr/internal/provider/client" + "github.com/hashicorp/terraform-plugin-framework/datasource" + "github.com/hashicorp/terraform-plugin-framework/datasource/schema" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-log/tflog" +) + +// Ensure the implementation satisfies the expected interfaces. +var ( + _ datasource.DataSource = &FlowExporterMapDataSource{} + _ datasource.DataSourceWithConfigure = &FlowExporterMapDataSource{} +) + +func NewFlowExporterMapDataSource() datasource.DataSource { + return &FlowExporterMapDataSource{} +} + +type FlowExporterMapDataSource struct { + client *client.Client +} + +func (d *FlowExporterMapDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_flow_exporter_map" +} + +func (d *FlowExporterMapDataSource) 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 Flow Exporter Map 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, + }, + "exporter_maps": schema.ListNestedAttribute{ + MarkdownDescription: "Exporter map name - maximum 32 characters", + Computed: true, + NestedObject: schema.NestedAttributeObject{ + Attributes: map[string]schema.Attribute{ + "exporter_map_name": schema.StringAttribute{ + MarkdownDescription: "Exporter map name - maximum 32 characters", + Computed: true, + }, + "destination_ipv4_address": schema.StringAttribute{ + MarkdownDescription: "Destination IPv4 address", + Computed: true, + }, + "destination_ipv6_address": schema.StringAttribute{ + MarkdownDescription: "Destination IPv6 address", + Computed: true, + }, + "destination_vrf": schema.StringAttribute{ + MarkdownDescription: "Configure VRF to be used for reaching export destination", + Computed: true, + }, + "source": schema.StringAttribute{ + MarkdownDescription: "Source interface", + Computed: true, + }, + "dscp": schema.Int64Attribute{ + MarkdownDescription: "Specify DSCP value for ipv4 export packets or traffic-class for ipv6 export packets", + Computed: true, + }, + "packet_length": schema.Int64Attribute{ + MarkdownDescription: "Export Packet maximum L3 length, should conform to outgoing interface mtu", + Computed: true, + }, + "transport_udp": schema.Int64Attribute{ + MarkdownDescription: "Use UDP as transport protocol", + Computed: true, + }, + "dfbit_set": schema.BoolAttribute{ + MarkdownDescription: "Set Export Packet Do Not Fragment Flag", + Computed: true, + }, + "version_export_format": schema.StringAttribute{ + MarkdownDescription: "Specify export format", + Computed: true, + }, + "version_template_data_timeout": schema.Int64Attribute{ + MarkdownDescription: "Specify custom timeout for the template", + Computed: true, + }, + "version_template_options_timeout": schema.Int64Attribute{ + MarkdownDescription: "Specify custom timeout for the template", + Computed: true, + }, + "version_template_timeout": schema.Int64Attribute{ + MarkdownDescription: "Specify custom timeout for the template", + Computed: true, + }, + "version_options_interface_table_timeout": schema.Int64Attribute{ + MarkdownDescription: "Specify export timeout", + Computed: true, + }, + "version_options_sampler_table_timeout": schema.Int64Attribute{ + MarkdownDescription: "Specify export timeout", + Computed: true, + }, + "version_options_class_table_timeout": schema.Int64Attribute{ + MarkdownDescription: "Specify export timeout", + Computed: true, + }, + "version_options_vrf_table_timeout": schema.Int64Attribute{ + MarkdownDescription: "Specify export timeout", + Computed: true, + }, + }, + }, + }, + }, + } +} + +func (d *FlowExporterMapDataSource) Configure(_ context.Context, req datasource.ConfigureRequest, _ *datasource.ConfigureResponse) { + if req.ProviderData == nil { + return + } + + d.client = req.ProviderData.(*client.Client) +} + +func (d *FlowExporterMapDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { + var config FlowExporterMapData + + // 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())) + + getResp, diags := d.client.Get(ctx, config.Device.ValueString(), config.getPath()) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + config.fromBody(ctx, getResp.Notification[0].Update[0].Val.GetJsonIetfVal()) + 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...) +} diff --git a/internal/provider/data_source_iosxr_flow_exporter_map_test.go b/internal/provider/data_source_iosxr_flow_exporter_map_test.go new file mode 100644 index 00000000..aa66346e --- /dev/null +++ b/internal/provider/data_source_iosxr_flow_exporter_map_test.go @@ -0,0 +1,88 @@ +// 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 + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" +) + +func TestAccDataSourceIosxrFlowExporterMap(t *testing.T) { + var checks []resource.TestCheckFunc + checks = append(checks, resource.TestCheckResourceAttr("data.iosxr_flow_exporter_map.test", "exporter_maps.0.exporter_map_name", "TEST")) + checks = append(checks, resource.TestCheckResourceAttr("data.iosxr_flow_exporter_map.test", "exporter_maps.0.destination_ipv4_address", "10.1.1.1")) + checks = append(checks, resource.TestCheckResourceAttr("data.iosxr_flow_exporter_map.test", "exporter_maps.0.destination_ipv6_address", "1::1")) + checks = append(checks, resource.TestCheckResourceAttr("data.iosxr_flow_exporter_map.test", "exporter_maps.0.destination_vrf", "28")) + checks = append(checks, resource.TestCheckResourceAttr("data.iosxr_flow_exporter_map.test", "exporter_maps.0.source", "10.1.1.4")) + checks = append(checks, resource.TestCheckResourceAttr("data.iosxr_flow_exporter_map.test", "exporter_maps.0.dscp", "62")) + checks = append(checks, resource.TestCheckResourceAttr("data.iosxr_flow_exporter_map.test", "exporter_maps.0.packet_length", "512")) + checks = append(checks, resource.TestCheckResourceAttr("data.iosxr_flow_exporter_map.test", "exporter_maps.0.transport_udp", "1033")) + checks = append(checks, resource.TestCheckResourceAttr("data.iosxr_flow_exporter_map.test", "exporter_maps.0.dfbit_set", "true")) + checks = append(checks, resource.TestCheckResourceAttr("data.iosxr_flow_exporter_map.test", "exporter_maps.0.version_export_format", "true")) + checks = append(checks, resource.TestCheckResourceAttr("data.iosxr_flow_exporter_map.test", "exporter_maps.0.version_template_data_timeout", "1024")) + checks = append(checks, resource.TestCheckResourceAttr("data.iosxr_flow_exporter_map.test", "exporter_maps.0.version_template_options_timeout", "3033")) + checks = append(checks, resource.TestCheckResourceAttr("data.iosxr_flow_exporter_map.test", "exporter_maps.0.version_template_timeout", "2222")) + checks = append(checks, resource.TestCheckResourceAttr("data.iosxr_flow_exporter_map.test", "exporter_maps.0.version_options_interface_table_timeout", "6048")) + checks = append(checks, resource.TestCheckResourceAttr("data.iosxr_flow_exporter_map.test", "exporter_maps.0.version_options_sampler_table_timeout", "4096")) + checks = append(checks, resource.TestCheckResourceAttr("data.iosxr_flow_exporter_map.test", "exporter_maps.0.version_options_class_table_timeout", "255")) + checks = append(checks, resource.TestCheckResourceAttr("data.iosxr_flow_exporter_map.test", "exporter_maps.0.version_options_vrf_table_timeout", "122")) + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testAccDataSourceIosxrFlowExporterMapConfig(), + Check: resource.ComposeTestCheckFunc(checks...), + }, + }, + }) +} + +func testAccDataSourceIosxrFlowExporterMapConfig() string { + config := `resource "iosxr_flow_exporter_map" "test" {` + "\n" + config += ` exporter_maps = [{` + "\n" + config += ` exporter_map_name = "TEST"` + "\n" + config += ` destination_ipv4_address = "10.1.1.1"` + "\n" + config += ` destination_ipv6_address = "1::1"` + "\n" + config += ` destination_vrf = "28"` + "\n" + config += ` source = "10.1.1.4"` + "\n" + config += ` dscp = 62` + "\n" + config += ` packet_length = 512` + "\n" + config += ` transport_udp = 1033` + "\n" + config += ` dfbit_set = true` + "\n" + config += ` version_export_format = "true"` + "\n" + config += ` version_template_data_timeout = 1024` + "\n" + config += ` version_template_options_timeout = 3033` + "\n" + config += ` version_template_timeout = 2222` + "\n" + config += ` version_options_interface_table_timeout = 6048` + "\n" + config += ` version_options_sampler_table_timeout = 4096` + "\n" + config += ` version_options_class_table_timeout = 255` + "\n" + config += ` version_options_vrf_table_timeout = 122` + "\n" + config += ` }]` + "\n" + config += `}` + "\n" + + config += ` + data "iosxr_flow_exporter_map" "test" { + depends_on = [iosxr_flow_exporter_map.test] + } + ` + return config +} diff --git a/internal/provider/model_iosxr_bfd.go b/internal/provider/model_iosxr_bfd.go new file mode 100644 index 00000000..ceb93dba --- /dev/null +++ b/internal/provider/model_iosxr_bfd.go @@ -0,0 +1,842 @@ +// 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 + +import ( + "context" + "fmt" + "reflect" + "strconv" + + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/tidwall/gjson" + "github.com/tidwall/sjson" +) + +type BFD struct { + Device types.String `tfsdk:"device"` + Id types.String `tfsdk:"id"` + DeleteMode types.String `tfsdk:"delete_mode"` + EchoDisable types.Bool `tfsdk:"echo_disable"` + EchoLatencyDetectPercentage types.Int64 `tfsdk:"echo_latency_detect_percentage"` + EchoLatencyDetectCount types.Int64 `tfsdk:"echo_latency_detect_count"` + EchoStartupValidateForce types.Bool `tfsdk:"echo_startup_validate_force"` + EchoIpv4Source types.String `tfsdk:"echo_ipv4_source"` + EchoIpv4BundlePerMemberMinimumIntervalPreferredMinimumInterval types.Int64 `tfsdk:"echo_ipv4_bundle_per_member_minimum_interval_preferred_minimum_interval"` + TrapSinglehopPreMapped types.Bool `tfsdk:"trap_singlehop_pre_mapped"` + MultipathLocations []BFDMultipathLocations `tfsdk:"multipath_locations"` + MultihopTtlDropThreshold types.Int64 `tfsdk:"multihop_ttl_drop_threshold"` + DampeningInitialWait types.Int64 `tfsdk:"dampening_initial_wait"` + DampeningSecondaryWait types.Int64 `tfsdk:"dampening_secondary_wait"` + DampeningMaximumWait types.Int64 `tfsdk:"dampening_maximum_wait"` + DampeningThreshold types.Int64 `tfsdk:"dampening_threshold"` + DampeningExtensionsDownMonitoring types.Bool `tfsdk:"dampening_extensions_down_monitoring"` + DampeningDisable types.Bool `tfsdk:"dampening_disable"` + DampeningBundleMemberL3OnlyMode types.Bool `tfsdk:"dampening_bundle_member_l3_only_mode"` + DampeningBundleMemberInitialWait types.Int64 `tfsdk:"dampening_bundle_member_initial_wait"` + DampeningBundleMemberSecondaryWait types.Int64 `tfsdk:"dampening_bundle_member_secondary_wait"` + DampeningBundleMemberMaximumWait types.Int64 `tfsdk:"dampening_bundle_member_maximum_wait"` + BundleCoexistenceBobBlbInherit types.Bool `tfsdk:"bundle_coexistence_bob_blb_inherit"` + BundleCoexistenceBobBlbLogical types.Bool `tfsdk:"bundle_coexistence_bob_blb_logical"` + Interfaces []BFDInterfaces `tfsdk:"interfaces"` + Ipv6ChecksumDisable types.Bool `tfsdk:"ipv6_checksum_disable"` +} + +type BFDData struct { + Device types.String `tfsdk:"device"` + Id types.String `tfsdk:"id"` + EchoDisable types.Bool `tfsdk:"echo_disable"` + EchoLatencyDetectPercentage types.Int64 `tfsdk:"echo_latency_detect_percentage"` + EchoLatencyDetectCount types.Int64 `tfsdk:"echo_latency_detect_count"` + EchoStartupValidateForce types.Bool `tfsdk:"echo_startup_validate_force"` + EchoIpv4Source types.String `tfsdk:"echo_ipv4_source"` + EchoIpv4BundlePerMemberMinimumIntervalPreferredMinimumInterval types.Int64 `tfsdk:"echo_ipv4_bundle_per_member_minimum_interval_preferred_minimum_interval"` + TrapSinglehopPreMapped types.Bool `tfsdk:"trap_singlehop_pre_mapped"` + MultipathLocations []BFDMultipathLocations `tfsdk:"multipath_locations"` + MultihopTtlDropThreshold types.Int64 `tfsdk:"multihop_ttl_drop_threshold"` + DampeningInitialWait types.Int64 `tfsdk:"dampening_initial_wait"` + DampeningSecondaryWait types.Int64 `tfsdk:"dampening_secondary_wait"` + DampeningMaximumWait types.Int64 `tfsdk:"dampening_maximum_wait"` + DampeningThreshold types.Int64 `tfsdk:"dampening_threshold"` + DampeningExtensionsDownMonitoring types.Bool `tfsdk:"dampening_extensions_down_monitoring"` + DampeningDisable types.Bool `tfsdk:"dampening_disable"` + DampeningBundleMemberL3OnlyMode types.Bool `tfsdk:"dampening_bundle_member_l3_only_mode"` + DampeningBundleMemberInitialWait types.Int64 `tfsdk:"dampening_bundle_member_initial_wait"` + DampeningBundleMemberSecondaryWait types.Int64 `tfsdk:"dampening_bundle_member_secondary_wait"` + DampeningBundleMemberMaximumWait types.Int64 `tfsdk:"dampening_bundle_member_maximum_wait"` + BundleCoexistenceBobBlbInherit types.Bool `tfsdk:"bundle_coexistence_bob_blb_inherit"` + BundleCoexistenceBobBlbLogical types.Bool `tfsdk:"bundle_coexistence_bob_blb_logical"` + Interfaces []BFDInterfaces `tfsdk:"interfaces"` + Ipv6ChecksumDisable types.Bool `tfsdk:"ipv6_checksum_disable"` +} +type BFDMultipathLocations struct { + LocationName types.String `tfsdk:"location_name"` +} +type BFDInterfaces struct { + InterfaceName types.String `tfsdk:"interface_name"` + EchoDisable types.Bool `tfsdk:"echo_disable"` + EchoIpv4Source types.String `tfsdk:"echo_ipv4_source"` + Ipv6ChecksumDisable types.Bool `tfsdk:"ipv6_checksum_disable"` + Disable types.Bool `tfsdk:"disable"` + LocalAddress types.String `tfsdk:"local_address"` + TxInterval types.Int64 `tfsdk:"tx_interval"` + RxInterval types.Int64 `tfsdk:"rx_interval"` + Multiplier types.Int64 `tfsdk:"multiplier"` +} + +func (data BFD) getPath() string { + return "Cisco-IOS-XR-um-bfd-sbfd-cfg:/bfd" +} + +func (data BFDData) getPath() string { + return "Cisco-IOS-XR-um-bfd-sbfd-cfg:/bfd" +} + +func (data BFD) toBody(ctx context.Context) string { + body := "{}" + if !data.EchoDisable.IsNull() && !data.EchoDisable.IsUnknown() { + if data.EchoDisable.ValueBool() { + body, _ = sjson.Set(body, "echo.disable", map[string]string{}) + } + } + if !data.EchoLatencyDetectPercentage.IsNull() && !data.EchoLatencyDetectPercentage.IsUnknown() { + body, _ = sjson.Set(body, "echo.latency.detect.percentage", strconv.FormatInt(data.EchoLatencyDetectPercentage.ValueInt64(), 10)) + } + if !data.EchoLatencyDetectCount.IsNull() && !data.EchoLatencyDetectCount.IsUnknown() { + body, _ = sjson.Set(body, "echo.latency.detect.count", strconv.FormatInt(data.EchoLatencyDetectCount.ValueInt64(), 10)) + } + if !data.EchoStartupValidateForce.IsNull() && !data.EchoStartupValidateForce.IsUnknown() { + if data.EchoStartupValidateForce.ValueBool() { + body, _ = sjson.Set(body, "echo.startup.validate.force", map[string]string{}) + } + } + if !data.EchoIpv4Source.IsNull() && !data.EchoIpv4Source.IsUnknown() { + body, _ = sjson.Set(body, "echo.ipv4.source", data.EchoIpv4Source.ValueString()) + } + if !data.EchoIpv4BundlePerMemberMinimumIntervalPreferredMinimumInterval.IsNull() && !data.EchoIpv4BundlePerMemberMinimumIntervalPreferredMinimumInterval.IsUnknown() { + body, _ = sjson.Set(body, "echo.ipv4.bundle-per-member.minimum-interval.preferred-minimum-interval", strconv.FormatInt(data.EchoIpv4BundlePerMemberMinimumIntervalPreferredMinimumInterval.ValueInt64(), 10)) + } + if !data.TrapSinglehopPreMapped.IsNull() && !data.TrapSinglehopPreMapped.IsUnknown() { + if data.TrapSinglehopPreMapped.ValueBool() { + body, _ = sjson.Set(body, "trap.singlehop.pre-mapped", map[string]string{}) + } + } + if !data.MultihopTtlDropThreshold.IsNull() && !data.MultihopTtlDropThreshold.IsUnknown() { + body, _ = sjson.Set(body, "multihop.ttl-drop-threshold", strconv.FormatInt(data.MultihopTtlDropThreshold.ValueInt64(), 10)) + } + if !data.DampeningInitialWait.IsNull() && !data.DampeningInitialWait.IsUnknown() { + body, _ = sjson.Set(body, "dampening.initial-wait", strconv.FormatInt(data.DampeningInitialWait.ValueInt64(), 10)) + } + if !data.DampeningSecondaryWait.IsNull() && !data.DampeningSecondaryWait.IsUnknown() { + body, _ = sjson.Set(body, "dampening.secondary-wait", strconv.FormatInt(data.DampeningSecondaryWait.ValueInt64(), 10)) + } + if !data.DampeningMaximumWait.IsNull() && !data.DampeningMaximumWait.IsUnknown() { + body, _ = sjson.Set(body, "dampening.maximum-wait", strconv.FormatInt(data.DampeningMaximumWait.ValueInt64(), 10)) + } + if !data.DampeningThreshold.IsNull() && !data.DampeningThreshold.IsUnknown() { + body, _ = sjson.Set(body, "dampening.threshold", strconv.FormatInt(data.DampeningThreshold.ValueInt64(), 10)) + } + if !data.DampeningExtensionsDownMonitoring.IsNull() && !data.DampeningExtensionsDownMonitoring.IsUnknown() { + if data.DampeningExtensionsDownMonitoring.ValueBool() { + body, _ = sjson.Set(body, "dampening.extensions.down-monitoring", map[string]string{}) + } + } + if !data.DampeningDisable.IsNull() && !data.DampeningDisable.IsUnknown() { + if data.DampeningDisable.ValueBool() { + body, _ = sjson.Set(body, "dampening.disable", map[string]string{}) + } + } + if !data.DampeningBundleMemberL3OnlyMode.IsNull() && !data.DampeningBundleMemberL3OnlyMode.IsUnknown() { + if data.DampeningBundleMemberL3OnlyMode.ValueBool() { + body, _ = sjson.Set(body, "dampening.bundle-member.l3-only-mode", map[string]string{}) + } + } + if !data.DampeningBundleMemberInitialWait.IsNull() && !data.DampeningBundleMemberInitialWait.IsUnknown() { + body, _ = sjson.Set(body, "dampening.bundle-member.initial-wait", strconv.FormatInt(data.DampeningBundleMemberInitialWait.ValueInt64(), 10)) + } + if !data.DampeningBundleMemberSecondaryWait.IsNull() && !data.DampeningBundleMemberSecondaryWait.IsUnknown() { + body, _ = sjson.Set(body, "dampening.bundle-member.secondary-wait", strconv.FormatInt(data.DampeningBundleMemberSecondaryWait.ValueInt64(), 10)) + } + if !data.DampeningBundleMemberMaximumWait.IsNull() && !data.DampeningBundleMemberMaximumWait.IsUnknown() { + body, _ = sjson.Set(body, "dampening.bundle-member.maximum-wait", strconv.FormatInt(data.DampeningBundleMemberMaximumWait.ValueInt64(), 10)) + } + if !data.BundleCoexistenceBobBlbInherit.IsNull() && !data.BundleCoexistenceBobBlbInherit.IsUnknown() { + if data.BundleCoexistenceBobBlbInherit.ValueBool() { + body, _ = sjson.Set(body, "bundle.coexistence.bob-blb.inherit", map[string]string{}) + } + } + if !data.BundleCoexistenceBobBlbLogical.IsNull() && !data.BundleCoexistenceBobBlbLogical.IsUnknown() { + if data.BundleCoexistenceBobBlbLogical.ValueBool() { + body, _ = sjson.Set(body, "bundle.coexistence.bob-blb.logical", map[string]string{}) + } + } + if !data.Ipv6ChecksumDisable.IsNull() && !data.Ipv6ChecksumDisable.IsUnknown() { + if data.Ipv6ChecksumDisable.ValueBool() { + body, _ = sjson.Set(body, "ipv6.checksum.disable", map[string]string{}) + } + } + if len(data.MultipathLocations) > 0 { + body, _ = sjson.Set(body, "multipath.include.locations.location", []interface{}{}) + for index, item := range data.MultipathLocations { + if !item.LocationName.IsNull() && !item.LocationName.IsUnknown() { + body, _ = sjson.Set(body, "multipath.include.locations.location"+"."+strconv.Itoa(index)+"."+"location-name", item.LocationName.ValueString()) + } + } + } + if len(data.Interfaces) > 0 { + body, _ = sjson.Set(body, "interfaces.interface", []interface{}{}) + for index, item := range data.Interfaces { + if !item.InterfaceName.IsNull() && !item.InterfaceName.IsUnknown() { + body, _ = sjson.Set(body, "interfaces.interface"+"."+strconv.Itoa(index)+"."+"interface-name", item.InterfaceName.ValueString()) + } + if !item.EchoDisable.IsNull() && !item.EchoDisable.IsUnknown() { + if item.EchoDisable.ValueBool() { + body, _ = sjson.Set(body, "interfaces.interface"+"."+strconv.Itoa(index)+"."+"echo.disable", map[string]string{}) + } + } + if !item.EchoIpv4Source.IsNull() && !item.EchoIpv4Source.IsUnknown() { + body, _ = sjson.Set(body, "interfaces.interface"+"."+strconv.Itoa(index)+"."+"echo.ipv4.source", item.EchoIpv4Source.ValueString()) + } + if !item.Ipv6ChecksumDisable.IsNull() && !item.Ipv6ChecksumDisable.IsUnknown() { + if item.Ipv6ChecksumDisable.ValueBool() { + body, _ = sjson.Set(body, "interfaces.interface"+"."+strconv.Itoa(index)+"."+"ipv6.checksum.disable", map[string]string{}) + } + } + if !item.Disable.IsNull() && !item.Disable.IsUnknown() { + if item.Disable.ValueBool() { + body, _ = sjson.Set(body, "interfaces.interface"+"."+strconv.Itoa(index)+"."+"disable", map[string]string{}) + } + } + if !item.LocalAddress.IsNull() && !item.LocalAddress.IsUnknown() { + body, _ = sjson.Set(body, "interfaces.interface"+"."+strconv.Itoa(index)+"."+"local-address", item.LocalAddress.ValueString()) + } + if !item.TxInterval.IsNull() && !item.TxInterval.IsUnknown() { + body, _ = sjson.Set(body, "interfaces.interface"+"."+strconv.Itoa(index)+"."+"tx-interval", strconv.FormatInt(item.TxInterval.ValueInt64(), 10)) + } + if !item.RxInterval.IsNull() && !item.RxInterval.IsUnknown() { + body, _ = sjson.Set(body, "interfaces.interface"+"."+strconv.Itoa(index)+"."+"rx-interval", strconv.FormatInt(item.RxInterval.ValueInt64(), 10)) + } + if !item.Multiplier.IsNull() && !item.Multiplier.IsUnknown() { + body, _ = sjson.Set(body, "interfaces.interface"+"."+strconv.Itoa(index)+"."+"multiplier", strconv.FormatInt(item.Multiplier.ValueInt64(), 10)) + } + } + } + return body +} + +func (data *BFD) updateFromBody(ctx context.Context, res []byte) { + if value := gjson.GetBytes(res, "echo.disable"); !data.EchoDisable.IsNull() { + if value.Exists() { + data.EchoDisable = types.BoolValue(true) + } else { + data.EchoDisable = types.BoolValue(false) + } + } else { + data.EchoDisable = types.BoolNull() + } + if value := gjson.GetBytes(res, "echo.latency.detect.percentage"); value.Exists() && !data.EchoLatencyDetectPercentage.IsNull() { + data.EchoLatencyDetectPercentage = types.Int64Value(value.Int()) + } else { + data.EchoLatencyDetectPercentage = types.Int64Null() + } + if value := gjson.GetBytes(res, "echo.latency.detect.count"); value.Exists() && !data.EchoLatencyDetectCount.IsNull() { + data.EchoLatencyDetectCount = types.Int64Value(value.Int()) + } else { + data.EchoLatencyDetectCount = types.Int64Null() + } + if value := gjson.GetBytes(res, "echo.startup.validate.force"); !data.EchoStartupValidateForce.IsNull() { + if value.Exists() { + data.EchoStartupValidateForce = types.BoolValue(true) + } else { + data.EchoStartupValidateForce = types.BoolValue(false) + } + } else { + data.EchoStartupValidateForce = types.BoolNull() + } + if value := gjson.GetBytes(res, "echo.ipv4.source"); value.Exists() && !data.EchoIpv4Source.IsNull() { + data.EchoIpv4Source = types.StringValue(value.String()) + } else { + data.EchoIpv4Source = types.StringNull() + } + if value := gjson.GetBytes(res, "echo.ipv4.bundle-per-member.minimum-interval.preferred-minimum-interval"); value.Exists() && !data.EchoIpv4BundlePerMemberMinimumIntervalPreferredMinimumInterval.IsNull() { + data.EchoIpv4BundlePerMemberMinimumIntervalPreferredMinimumInterval = types.Int64Value(value.Int()) + } else { + data.EchoIpv4BundlePerMemberMinimumIntervalPreferredMinimumInterval = types.Int64Null() + } + if value := gjson.GetBytes(res, "trap.singlehop.pre-mapped"); !data.TrapSinglehopPreMapped.IsNull() { + if value.Exists() { + data.TrapSinglehopPreMapped = types.BoolValue(true) + } else { + data.TrapSinglehopPreMapped = types.BoolValue(false) + } + } else { + data.TrapSinglehopPreMapped = types.BoolNull() + } + for i := range data.MultipathLocations { + keys := [...]string{"location-name"} + keyValues := [...]string{data.MultipathLocations[i].LocationName.ValueString()} + + var r gjson.Result + gjson.GetBytes(res, "multipath.include.locations.location").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("location-name"); value.Exists() && !data.MultipathLocations[i].LocationName.IsNull() { + data.MultipathLocations[i].LocationName = types.StringValue(value.String()) + } else { + data.MultipathLocations[i].LocationName = types.StringNull() + } + } + if value := gjson.GetBytes(res, "multihop.ttl-drop-threshold"); value.Exists() && !data.MultihopTtlDropThreshold.IsNull() { + data.MultihopTtlDropThreshold = types.Int64Value(value.Int()) + } else { + data.MultihopTtlDropThreshold = types.Int64Null() + } + if value := gjson.GetBytes(res, "dampening.initial-wait"); value.Exists() && !data.DampeningInitialWait.IsNull() { + data.DampeningInitialWait = types.Int64Value(value.Int()) + } else { + data.DampeningInitialWait = types.Int64Null() + } + if value := gjson.GetBytes(res, "dampening.secondary-wait"); value.Exists() && !data.DampeningSecondaryWait.IsNull() { + data.DampeningSecondaryWait = types.Int64Value(value.Int()) + } else { + data.DampeningSecondaryWait = types.Int64Null() + } + if value := gjson.GetBytes(res, "dampening.maximum-wait"); value.Exists() && !data.DampeningMaximumWait.IsNull() { + data.DampeningMaximumWait = types.Int64Value(value.Int()) + } else { + data.DampeningMaximumWait = types.Int64Null() + } + if value := gjson.GetBytes(res, "dampening.threshold"); value.Exists() && !data.DampeningThreshold.IsNull() { + data.DampeningThreshold = types.Int64Value(value.Int()) + } else { + data.DampeningThreshold = types.Int64Null() + } + if value := gjson.GetBytes(res, "dampening.extensions.down-monitoring"); !data.DampeningExtensionsDownMonitoring.IsNull() { + if value.Exists() { + data.DampeningExtensionsDownMonitoring = types.BoolValue(true) + } else { + data.DampeningExtensionsDownMonitoring = types.BoolValue(false) + } + } else { + data.DampeningExtensionsDownMonitoring = types.BoolNull() + } + if value := gjson.GetBytes(res, "dampening.disable"); !data.DampeningDisable.IsNull() { + if value.Exists() { + data.DampeningDisable = types.BoolValue(true) + } else { + data.DampeningDisable = types.BoolValue(false) + } + } else { + data.DampeningDisable = types.BoolNull() + } + if value := gjson.GetBytes(res, "dampening.bundle-member.l3-only-mode"); !data.DampeningBundleMemberL3OnlyMode.IsNull() { + if value.Exists() { + data.DampeningBundleMemberL3OnlyMode = types.BoolValue(true) + } else { + data.DampeningBundleMemberL3OnlyMode = types.BoolValue(false) + } + } else { + data.DampeningBundleMemberL3OnlyMode = types.BoolNull() + } + if value := gjson.GetBytes(res, "dampening.bundle-member.initial-wait"); value.Exists() && !data.DampeningBundleMemberInitialWait.IsNull() { + data.DampeningBundleMemberInitialWait = types.Int64Value(value.Int()) + } else { + data.DampeningBundleMemberInitialWait = types.Int64Null() + } + if value := gjson.GetBytes(res, "dampening.bundle-member.secondary-wait"); value.Exists() && !data.DampeningBundleMemberSecondaryWait.IsNull() { + data.DampeningBundleMemberSecondaryWait = types.Int64Value(value.Int()) + } else { + data.DampeningBundleMemberSecondaryWait = types.Int64Null() + } + if value := gjson.GetBytes(res, "dampening.bundle-member.maximum-wait"); value.Exists() && !data.DampeningBundleMemberMaximumWait.IsNull() { + data.DampeningBundleMemberMaximumWait = types.Int64Value(value.Int()) + } else { + data.DampeningBundleMemberMaximumWait = types.Int64Null() + } + if value := gjson.GetBytes(res, "bundle.coexistence.bob-blb.inherit"); !data.BundleCoexistenceBobBlbInherit.IsNull() { + if value.Exists() { + data.BundleCoexistenceBobBlbInherit = types.BoolValue(true) + } else { + data.BundleCoexistenceBobBlbInherit = types.BoolValue(false) + } + } else { + data.BundleCoexistenceBobBlbInherit = types.BoolNull() + } + if value := gjson.GetBytes(res, "bundle.coexistence.bob-blb.logical"); !data.BundleCoexistenceBobBlbLogical.IsNull() { + if value.Exists() { + data.BundleCoexistenceBobBlbLogical = types.BoolValue(true) + } else { + data.BundleCoexistenceBobBlbLogical = types.BoolValue(false) + } + } else { + data.BundleCoexistenceBobBlbLogical = types.BoolNull() + } + for i := range data.Interfaces { + keys := [...]string{"interface-name"} + keyValues := [...]string{data.Interfaces[i].InterfaceName.ValueString()} + + var r gjson.Result + gjson.GetBytes(res, "interfaces.interface").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("interface-name"); value.Exists() && !data.Interfaces[i].InterfaceName.IsNull() { + data.Interfaces[i].InterfaceName = types.StringValue(value.String()) + } else { + data.Interfaces[i].InterfaceName = types.StringNull() + } + if value := r.Get("echo.disable"); !data.Interfaces[i].EchoDisable.IsNull() { + if value.Exists() { + data.Interfaces[i].EchoDisable = types.BoolValue(true) + } else { + data.Interfaces[i].EchoDisable = types.BoolValue(false) + } + } else { + data.Interfaces[i].EchoDisable = types.BoolNull() + } + if value := r.Get("echo.ipv4.source"); value.Exists() && !data.Interfaces[i].EchoIpv4Source.IsNull() { + data.Interfaces[i].EchoIpv4Source = types.StringValue(value.String()) + } else { + data.Interfaces[i].EchoIpv4Source = types.StringNull() + } + if value := r.Get("ipv6.checksum.disable"); !data.Interfaces[i].Ipv6ChecksumDisable.IsNull() { + if value.Exists() { + data.Interfaces[i].Ipv6ChecksumDisable = types.BoolValue(true) + } else { + data.Interfaces[i].Ipv6ChecksumDisable = types.BoolValue(false) + } + } else { + data.Interfaces[i].Ipv6ChecksumDisable = types.BoolNull() + } + if value := r.Get("disable"); !data.Interfaces[i].Disable.IsNull() { + if value.Exists() { + data.Interfaces[i].Disable = types.BoolValue(true) + } else { + data.Interfaces[i].Disable = types.BoolValue(false) + } + } else { + data.Interfaces[i].Disable = types.BoolNull() + } + if value := r.Get("local-address"); value.Exists() && !data.Interfaces[i].LocalAddress.IsNull() { + data.Interfaces[i].LocalAddress = types.StringValue(value.String()) + } else { + data.Interfaces[i].LocalAddress = types.StringNull() + } + if value := r.Get("tx-interval"); value.Exists() && !data.Interfaces[i].TxInterval.IsNull() { + data.Interfaces[i].TxInterval = types.Int64Value(value.Int()) + } else { + data.Interfaces[i].TxInterval = types.Int64Null() + } + if value := r.Get("rx-interval"); value.Exists() && !data.Interfaces[i].RxInterval.IsNull() { + data.Interfaces[i].RxInterval = types.Int64Value(value.Int()) + } else { + data.Interfaces[i].RxInterval = types.Int64Null() + } + if value := r.Get("multiplier"); value.Exists() && !data.Interfaces[i].Multiplier.IsNull() { + data.Interfaces[i].Multiplier = types.Int64Value(value.Int()) + } else { + data.Interfaces[i].Multiplier = types.Int64Null() + } + } + if value := gjson.GetBytes(res, "ipv6.checksum.disable"); !data.Ipv6ChecksumDisable.IsNull() { + if value.Exists() { + data.Ipv6ChecksumDisable = types.BoolValue(true) + } else { + data.Ipv6ChecksumDisable = types.BoolValue(false) + } + } else { + data.Ipv6ChecksumDisable = types.BoolNull() + } +} + +func (data *BFDData) fromBody(ctx context.Context, res []byte) { + if value := gjson.GetBytes(res, "echo.disable"); value.Exists() { + data.EchoDisable = types.BoolValue(true) + } else { + data.EchoDisable = types.BoolValue(false) + } + if value := gjson.GetBytes(res, "echo.latency.detect.percentage"); value.Exists() { + data.EchoLatencyDetectPercentage = types.Int64Value(value.Int()) + } + if value := gjson.GetBytes(res, "echo.latency.detect.count"); value.Exists() { + data.EchoLatencyDetectCount = types.Int64Value(value.Int()) + } + if value := gjson.GetBytes(res, "echo.startup.validate.force"); value.Exists() { + data.EchoStartupValidateForce = types.BoolValue(true) + } else { + data.EchoStartupValidateForce = types.BoolValue(false) + } + if value := gjson.GetBytes(res, "echo.ipv4.source"); value.Exists() { + data.EchoIpv4Source = types.StringValue(value.String()) + } + if value := gjson.GetBytes(res, "echo.ipv4.bundle-per-member.minimum-interval.preferred-minimum-interval"); value.Exists() { + data.EchoIpv4BundlePerMemberMinimumIntervalPreferredMinimumInterval = types.Int64Value(value.Int()) + } + if value := gjson.GetBytes(res, "trap.singlehop.pre-mapped"); value.Exists() { + data.TrapSinglehopPreMapped = types.BoolValue(true) + } else { + data.TrapSinglehopPreMapped = types.BoolValue(false) + } + if value := gjson.GetBytes(res, "multipath.include.locations.location"); value.Exists() { + data.MultipathLocations = make([]BFDMultipathLocations, 0) + value.ForEach(func(k, v gjson.Result) bool { + item := BFDMultipathLocations{} + if cValue := v.Get("location-name"); cValue.Exists() { + item.LocationName = types.StringValue(cValue.String()) + } + data.MultipathLocations = append(data.MultipathLocations, item) + return true + }) + } + if value := gjson.GetBytes(res, "multihop.ttl-drop-threshold"); value.Exists() { + data.MultihopTtlDropThreshold = types.Int64Value(value.Int()) + } + if value := gjson.GetBytes(res, "dampening.initial-wait"); value.Exists() { + data.DampeningInitialWait = types.Int64Value(value.Int()) + } + if value := gjson.GetBytes(res, "dampening.secondary-wait"); value.Exists() { + data.DampeningSecondaryWait = types.Int64Value(value.Int()) + } + if value := gjson.GetBytes(res, "dampening.maximum-wait"); value.Exists() { + data.DampeningMaximumWait = types.Int64Value(value.Int()) + } + if value := gjson.GetBytes(res, "dampening.threshold"); value.Exists() { + data.DampeningThreshold = types.Int64Value(value.Int()) + } + if value := gjson.GetBytes(res, "dampening.extensions.down-monitoring"); value.Exists() { + data.DampeningExtensionsDownMonitoring = types.BoolValue(true) + } else { + data.DampeningExtensionsDownMonitoring = types.BoolValue(false) + } + if value := gjson.GetBytes(res, "dampening.disable"); value.Exists() { + data.DampeningDisable = types.BoolValue(true) + } else { + data.DampeningDisable = types.BoolValue(false) + } + if value := gjson.GetBytes(res, "dampening.bundle-member.l3-only-mode"); value.Exists() { + data.DampeningBundleMemberL3OnlyMode = types.BoolValue(true) + } else { + data.DampeningBundleMemberL3OnlyMode = types.BoolValue(false) + } + if value := gjson.GetBytes(res, "dampening.bundle-member.initial-wait"); value.Exists() { + data.DampeningBundleMemberInitialWait = types.Int64Value(value.Int()) + } + if value := gjson.GetBytes(res, "dampening.bundle-member.secondary-wait"); value.Exists() { + data.DampeningBundleMemberSecondaryWait = types.Int64Value(value.Int()) + } + if value := gjson.GetBytes(res, "dampening.bundle-member.maximum-wait"); value.Exists() { + data.DampeningBundleMemberMaximumWait = types.Int64Value(value.Int()) + } + if value := gjson.GetBytes(res, "bundle.coexistence.bob-blb.inherit"); value.Exists() { + data.BundleCoexistenceBobBlbInherit = types.BoolValue(true) + } else { + data.BundleCoexistenceBobBlbInherit = types.BoolValue(false) + } + if value := gjson.GetBytes(res, "bundle.coexistence.bob-blb.logical"); value.Exists() { + data.BundleCoexistenceBobBlbLogical = types.BoolValue(true) + } else { + data.BundleCoexistenceBobBlbLogical = types.BoolValue(false) + } + if value := gjson.GetBytes(res, "interfaces.interface"); value.Exists() { + data.Interfaces = make([]BFDInterfaces, 0) + value.ForEach(func(k, v gjson.Result) bool { + item := BFDInterfaces{} + if cValue := v.Get("interface-name"); cValue.Exists() { + item.InterfaceName = types.StringValue(cValue.String()) + } + if cValue := v.Get("echo.disable"); cValue.Exists() { + item.EchoDisable = types.BoolValue(true) + } else { + item.EchoDisable = types.BoolValue(false) + } + if cValue := v.Get("echo.ipv4.source"); cValue.Exists() { + item.EchoIpv4Source = types.StringValue(cValue.String()) + } + if cValue := v.Get("ipv6.checksum.disable"); cValue.Exists() { + item.Ipv6ChecksumDisable = types.BoolValue(true) + } else { + item.Ipv6ChecksumDisable = types.BoolValue(false) + } + if cValue := v.Get("disable"); cValue.Exists() { + item.Disable = types.BoolValue(true) + } else { + item.Disable = types.BoolValue(false) + } + if cValue := v.Get("local-address"); cValue.Exists() { + item.LocalAddress = types.StringValue(cValue.String()) + } + if cValue := v.Get("tx-interval"); cValue.Exists() { + item.TxInterval = types.Int64Value(cValue.Int()) + } + if cValue := v.Get("rx-interval"); cValue.Exists() { + item.RxInterval = types.Int64Value(cValue.Int()) + } + if cValue := v.Get("multiplier"); cValue.Exists() { + item.Multiplier = types.Int64Value(cValue.Int()) + } + data.Interfaces = append(data.Interfaces, item) + return true + }) + } + if value := gjson.GetBytes(res, "ipv6.checksum.disable"); value.Exists() { + data.Ipv6ChecksumDisable = types.BoolValue(true) + } else { + data.Ipv6ChecksumDisable = types.BoolValue(false) + } +} + +func (data *BFD) getDeletedListItems(ctx context.Context, state BFD) []string { + deletedListItems := make([]string, 0) + for i := range state.MultipathLocations { + keys := [...]string{"location-name"} + stateKeyValues := [...]string{state.MultipathLocations[i].LocationName.ValueString()} + + emptyKeys := true + if !reflect.ValueOf(state.MultipathLocations[i].LocationName.ValueString()).IsZero() { + emptyKeys = false + } + if emptyKeys { + continue + } + + found := false + for j := range data.MultipathLocations { + found = true + if state.MultipathLocations[i].LocationName.ValueString() != data.MultipathLocations[j].LocationName.ValueString() { + found = false + } + if found { + break + } + } + if !found { + keyString := "" + for ki := range keys { + keyString += "[" + keys[ki] + "=" + stateKeyValues[ki] + "]" + } + deletedListItems = append(deletedListItems, fmt.Sprintf("%v/multipath/include/locations/location%v", state.getPath(), keyString)) + } + } + for i := range state.Interfaces { + keys := [...]string{"interface-name"} + stateKeyValues := [...]string{state.Interfaces[i].InterfaceName.ValueString()} + + emptyKeys := true + if !reflect.ValueOf(state.Interfaces[i].InterfaceName.ValueString()).IsZero() { + emptyKeys = false + } + if emptyKeys { + continue + } + + found := false + for j := range data.Interfaces { + found = true + if state.Interfaces[i].InterfaceName.ValueString() != data.Interfaces[j].InterfaceName.ValueString() { + found = false + } + if found { + break + } + } + if !found { + keyString := "" + for ki := range keys { + keyString += "[" + keys[ki] + "=" + stateKeyValues[ki] + "]" + } + deletedListItems = append(deletedListItems, fmt.Sprintf("%v/interfaces/interface%v", state.getPath(), keyString)) + } + } + return deletedListItems +} + +func (data *BFD) getEmptyLeafsDelete(ctx context.Context) []string { + emptyLeafsDelete := make([]string, 0) + if !data.EchoDisable.IsNull() && !data.EchoDisable.ValueBool() { + emptyLeafsDelete = append(emptyLeafsDelete, fmt.Sprintf("%v/echo/disable", data.getPath())) + } + if !data.EchoStartupValidateForce.IsNull() && !data.EchoStartupValidateForce.ValueBool() { + emptyLeafsDelete = append(emptyLeafsDelete, fmt.Sprintf("%v/echo/startup/validate/force", data.getPath())) + } + if !data.TrapSinglehopPreMapped.IsNull() && !data.TrapSinglehopPreMapped.ValueBool() { + emptyLeafsDelete = append(emptyLeafsDelete, fmt.Sprintf("%v/trap/singlehop/pre-mapped", data.getPath())) + } + for i := range data.MultipathLocations { + keys := [...]string{"location-name"} + keyValues := [...]string{data.MultipathLocations[i].LocationName.ValueString()} + keyString := "" + for ki := range keys { + keyString += "[" + keys[ki] + "=" + keyValues[ki] + "]" + } + } + if !data.DampeningExtensionsDownMonitoring.IsNull() && !data.DampeningExtensionsDownMonitoring.ValueBool() { + emptyLeafsDelete = append(emptyLeafsDelete, fmt.Sprintf("%v/dampening/extensions/down-monitoring", data.getPath())) + } + if !data.DampeningDisable.IsNull() && !data.DampeningDisable.ValueBool() { + emptyLeafsDelete = append(emptyLeafsDelete, fmt.Sprintf("%v/dampening/disable", data.getPath())) + } + if !data.DampeningBundleMemberL3OnlyMode.IsNull() && !data.DampeningBundleMemberL3OnlyMode.ValueBool() { + emptyLeafsDelete = append(emptyLeafsDelete, fmt.Sprintf("%v/dampening/bundle-member/l3-only-mode", data.getPath())) + } + if !data.BundleCoexistenceBobBlbInherit.IsNull() && !data.BundleCoexistenceBobBlbInherit.ValueBool() { + emptyLeafsDelete = append(emptyLeafsDelete, fmt.Sprintf("%v/bundle/coexistence/bob-blb/inherit", data.getPath())) + } + if !data.BundleCoexistenceBobBlbLogical.IsNull() && !data.BundleCoexistenceBobBlbLogical.ValueBool() { + emptyLeafsDelete = append(emptyLeafsDelete, fmt.Sprintf("%v/bundle/coexistence/bob-blb/logical", data.getPath())) + } + for i := range data.Interfaces { + keys := [...]string{"interface-name"} + keyValues := [...]string{data.Interfaces[i].InterfaceName.ValueString()} + keyString := "" + for ki := range keys { + keyString += "[" + keys[ki] + "=" + keyValues[ki] + "]" + } + if !data.Interfaces[i].EchoDisable.IsNull() && !data.Interfaces[i].EchoDisable.ValueBool() { + emptyLeafsDelete = append(emptyLeafsDelete, fmt.Sprintf("%v/interfaces/interface%v/echo/disable", data.getPath(), keyString)) + } + if !data.Interfaces[i].Ipv6ChecksumDisable.IsNull() && !data.Interfaces[i].Ipv6ChecksumDisable.ValueBool() { + emptyLeafsDelete = append(emptyLeafsDelete, fmt.Sprintf("%v/interfaces/interface%v/ipv6/checksum/disable", data.getPath(), keyString)) + } + if !data.Interfaces[i].Disable.IsNull() && !data.Interfaces[i].Disable.ValueBool() { + emptyLeafsDelete = append(emptyLeafsDelete, fmt.Sprintf("%v/interfaces/interface%v/disable", data.getPath(), keyString)) + } + } + if !data.Ipv6ChecksumDisable.IsNull() && !data.Ipv6ChecksumDisable.ValueBool() { + emptyLeafsDelete = append(emptyLeafsDelete, fmt.Sprintf("%v/ipv6/checksum/disable", data.getPath())) + } + return emptyLeafsDelete +} + +func (data *BFD) getDeletePaths(ctx context.Context) []string { + var deletePaths []string + if !data.EchoDisable.IsNull() { + deletePaths = append(deletePaths, fmt.Sprintf("%v/echo/disable", data.getPath())) + } + if !data.EchoLatencyDetectPercentage.IsNull() { + deletePaths = append(deletePaths, fmt.Sprintf("%v/echo/latency/detect/percentage", data.getPath())) + } + if !data.EchoLatencyDetectCount.IsNull() { + deletePaths = append(deletePaths, fmt.Sprintf("%v/echo/latency/detect/count", data.getPath())) + } + if !data.EchoStartupValidateForce.IsNull() { + deletePaths = append(deletePaths, fmt.Sprintf("%v/echo/startup/validate/force", data.getPath())) + } + if !data.EchoIpv4Source.IsNull() { + deletePaths = append(deletePaths, fmt.Sprintf("%v/echo/ipv4/source", data.getPath())) + } + if !data.EchoIpv4BundlePerMemberMinimumIntervalPreferredMinimumInterval.IsNull() { + deletePaths = append(deletePaths, fmt.Sprintf("%v/echo/ipv4/bundle-per-member/minimum-interval/preferred-minimum-interval", data.getPath())) + } + if !data.TrapSinglehopPreMapped.IsNull() { + deletePaths = append(deletePaths, fmt.Sprintf("%v/trap/singlehop/pre-mapped", data.getPath())) + } + for i := range data.MultipathLocations { + keys := [...]string{"location-name"} + keyValues := [...]string{data.MultipathLocations[i].LocationName.ValueString()} + + keyString := "" + for ki := range keys { + keyString += "[" + keys[ki] + "=" + keyValues[ki] + "]" + } + deletePaths = append(deletePaths, fmt.Sprintf("%v/multipath/include/locations/location%v", data.getPath(), keyString)) + } + if !data.MultihopTtlDropThreshold.IsNull() { + deletePaths = append(deletePaths, fmt.Sprintf("%v/multihop/ttl-drop-threshold", data.getPath())) + } + if !data.DampeningInitialWait.IsNull() { + deletePaths = append(deletePaths, fmt.Sprintf("%v/dampening/initial-wait", data.getPath())) + } + if !data.DampeningSecondaryWait.IsNull() { + deletePaths = append(deletePaths, fmt.Sprintf("%v/dampening/secondary-wait", data.getPath())) + } + if !data.DampeningMaximumWait.IsNull() { + deletePaths = append(deletePaths, fmt.Sprintf("%v/dampening/maximum-wait", data.getPath())) + } + if !data.DampeningThreshold.IsNull() { + deletePaths = append(deletePaths, fmt.Sprintf("%v/dampening/threshold", data.getPath())) + } + if !data.DampeningExtensionsDownMonitoring.IsNull() { + deletePaths = append(deletePaths, fmt.Sprintf("%v/dampening/extensions/down-monitoring", data.getPath())) + } + if !data.DampeningDisable.IsNull() { + deletePaths = append(deletePaths, fmt.Sprintf("%v/dampening/disable", data.getPath())) + } + if !data.DampeningBundleMemberL3OnlyMode.IsNull() { + deletePaths = append(deletePaths, fmt.Sprintf("%v/dampening/bundle-member/l3-only-mode", data.getPath())) + } + if !data.DampeningBundleMemberInitialWait.IsNull() { + deletePaths = append(deletePaths, fmt.Sprintf("%v/dampening/bundle-member/initial-wait", data.getPath())) + } + if !data.DampeningBundleMemberSecondaryWait.IsNull() { + deletePaths = append(deletePaths, fmt.Sprintf("%v/dampening/bundle-member/secondary-wait", data.getPath())) + } + if !data.DampeningBundleMemberMaximumWait.IsNull() { + deletePaths = append(deletePaths, fmt.Sprintf("%v/dampening/bundle-member/maximum-wait", data.getPath())) + } + if !data.BundleCoexistenceBobBlbInherit.IsNull() { + deletePaths = append(deletePaths, fmt.Sprintf("%v/bundle/coexistence/bob-blb/inherit", data.getPath())) + } + if !data.BundleCoexistenceBobBlbLogical.IsNull() { + deletePaths = append(deletePaths, fmt.Sprintf("%v/bundle/coexistence/bob-blb/logical", data.getPath())) + } + for i := range data.Interfaces { + keys := [...]string{"interface-name"} + keyValues := [...]string{data.Interfaces[i].InterfaceName.ValueString()} + + keyString := "" + for ki := range keys { + keyString += "[" + keys[ki] + "=" + keyValues[ki] + "]" + } + deletePaths = append(deletePaths, fmt.Sprintf("%v/interfaces/interface%v", data.getPath(), keyString)) + } + if !data.Ipv6ChecksumDisable.IsNull() { + deletePaths = append(deletePaths, fmt.Sprintf("%v/ipv6/checksum/disable", data.getPath())) + } + return deletePaths +} diff --git a/internal/provider/model_iosxr_flow_exporter_map.go b/internal/provider/model_iosxr_flow_exporter_map.go new file mode 100644 index 00000000..1afe9cca --- /dev/null +++ b/internal/provider/model_iosxr_flow_exporter_map.go @@ -0,0 +1,379 @@ +// 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 + +import ( + "context" + "fmt" + "reflect" + "strconv" + + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/tidwall/gjson" + "github.com/tidwall/sjson" +) + +type FlowExporterMap struct { + Device types.String `tfsdk:"device"` + Id types.String `tfsdk:"id"` + ExporterMaps []FlowExporterMapExporterMaps `tfsdk:"exporter_maps"` +} + +type FlowExporterMapData struct { + Device types.String `tfsdk:"device"` + Id types.String `tfsdk:"id"` + ExporterMaps []FlowExporterMapExporterMaps `tfsdk:"exporter_maps"` +} +type FlowExporterMapExporterMaps struct { + ExporterMapName types.String `tfsdk:"exporter_map_name"` + DestinationIpv4Address types.String `tfsdk:"destination_ipv4_address"` + DestinationIpv6Address types.String `tfsdk:"destination_ipv6_address"` + DestinationVrf types.String `tfsdk:"destination_vrf"` + Source types.String `tfsdk:"source"` + Dscp types.Int64 `tfsdk:"dscp"` + PacketLength types.Int64 `tfsdk:"packet_length"` + TransportUdp types.Int64 `tfsdk:"transport_udp"` + DfbitSet types.Bool `tfsdk:"dfbit_set"` + VersionExportFormat types.String `tfsdk:"version_export_format"` + VersionTemplateDataTimeout types.Int64 `tfsdk:"version_template_data_timeout"` + VersionTemplateOptionsTimeout types.Int64 `tfsdk:"version_template_options_timeout"` + VersionTemplateTimeout types.Int64 `tfsdk:"version_template_timeout"` + VersionOptionsInterfaceTableTimeout types.Int64 `tfsdk:"version_options_interface_table_timeout"` + VersionOptionsSamplerTableTimeout types.Int64 `tfsdk:"version_options_sampler_table_timeout"` + VersionOptionsClassTableTimeout types.Int64 `tfsdk:"version_options_class_table_timeout"` + VersionOptionsVrfTableTimeout types.Int64 `tfsdk:"version_options_vrf_table_timeout"` +} + +func (data FlowExporterMap) getPath() string { + return "Cisco-IOS-XR-um-flow-cfg:/flow/exporter-maps" +} + +func (data FlowExporterMapData) getPath() string { + return "Cisco-IOS-XR-um-flow-cfg:/flow/exporter-maps" +} + +func (data FlowExporterMap) toBody(ctx context.Context) string { + body := "{}" + if len(data.ExporterMaps) > 0 { + body, _ = sjson.Set(body, "exporter-map", []interface{}{}) + for index, item := range data.ExporterMaps { + if !item.ExporterMapName.IsNull() && !item.ExporterMapName.IsUnknown() { + body, _ = sjson.Set(body, "exporter-map"+"."+strconv.Itoa(index)+"."+"exporter-map-name", item.ExporterMapName.ValueString()) + } + if !item.DestinationIpv4Address.IsNull() && !item.DestinationIpv4Address.IsUnknown() { + body, _ = sjson.Set(body, "exporter-map"+"."+strconv.Itoa(index)+"."+"destination.ipv4-address", item.DestinationIpv4Address.ValueString()) + } + if !item.DestinationIpv6Address.IsNull() && !item.DestinationIpv6Address.IsUnknown() { + body, _ = sjson.Set(body, "exporter-map"+"."+strconv.Itoa(index)+"."+"destination.ipv6-address", item.DestinationIpv6Address.ValueString()) + } + if !item.DestinationVrf.IsNull() && !item.DestinationVrf.IsUnknown() { + body, _ = sjson.Set(body, "exporter-map"+"."+strconv.Itoa(index)+"."+"destination.vrf", item.DestinationVrf.ValueString()) + } + if !item.Source.IsNull() && !item.Source.IsUnknown() { + body, _ = sjson.Set(body, "exporter-map"+"."+strconv.Itoa(index)+"."+"source", item.Source.ValueString()) + } + if !item.Dscp.IsNull() && !item.Dscp.IsUnknown() { + body, _ = sjson.Set(body, "exporter-map"+"."+strconv.Itoa(index)+"."+"dscp", strconv.FormatInt(item.Dscp.ValueInt64(), 10)) + } + if !item.PacketLength.IsNull() && !item.PacketLength.IsUnknown() { + body, _ = sjson.Set(body, "exporter-map"+"."+strconv.Itoa(index)+"."+"packet-length", strconv.FormatInt(item.PacketLength.ValueInt64(), 10)) + } + if !item.TransportUdp.IsNull() && !item.TransportUdp.IsUnknown() { + body, _ = sjson.Set(body, "exporter-map"+"."+strconv.Itoa(index)+"."+"transport.udp", strconv.FormatInt(item.TransportUdp.ValueInt64(), 10)) + } + if !item.DfbitSet.IsNull() && !item.DfbitSet.IsUnknown() { + if item.DfbitSet.ValueBool() { + body, _ = sjson.Set(body, "exporter-map"+"."+strconv.Itoa(index)+"."+"dfbit.set", map[string]string{}) + } + } + if !item.VersionExportFormat.IsNull() && !item.VersionExportFormat.IsUnknown() { + body, _ = sjson.Set(body, "exporter-map"+"."+strconv.Itoa(index)+"."+"version.export-format", item.VersionExportFormat.ValueString()) + } + if !item.VersionTemplateDataTimeout.IsNull() && !item.VersionTemplateDataTimeout.IsUnknown() { + body, _ = sjson.Set(body, "exporter-map"+"."+strconv.Itoa(index)+"."+"version.template.data.timeout", strconv.FormatInt(item.VersionTemplateDataTimeout.ValueInt64(), 10)) + } + if !item.VersionTemplateOptionsTimeout.IsNull() && !item.VersionTemplateOptionsTimeout.IsUnknown() { + body, _ = sjson.Set(body, "exporter-map"+"."+strconv.Itoa(index)+"."+"version.template.options.timeout", strconv.FormatInt(item.VersionTemplateOptionsTimeout.ValueInt64(), 10)) + } + if !item.VersionTemplateTimeout.IsNull() && !item.VersionTemplateTimeout.IsUnknown() { + body, _ = sjson.Set(body, "exporter-map"+"."+strconv.Itoa(index)+"."+"version.template.timeout", strconv.FormatInt(item.VersionTemplateTimeout.ValueInt64(), 10)) + } + if !item.VersionOptionsInterfaceTableTimeout.IsNull() && !item.VersionOptionsInterfaceTableTimeout.IsUnknown() { + body, _ = sjson.Set(body, "exporter-map"+"."+strconv.Itoa(index)+"."+"version.options.interface-table.timeout", strconv.FormatInt(item.VersionOptionsInterfaceTableTimeout.ValueInt64(), 10)) + } + if !item.VersionOptionsSamplerTableTimeout.IsNull() && !item.VersionOptionsSamplerTableTimeout.IsUnknown() { + body, _ = sjson.Set(body, "exporter-map"+"."+strconv.Itoa(index)+"."+"version.options.sampler-table.timeout", strconv.FormatInt(item.VersionOptionsSamplerTableTimeout.ValueInt64(), 10)) + } + if !item.VersionOptionsClassTableTimeout.IsNull() && !item.VersionOptionsClassTableTimeout.IsUnknown() { + body, _ = sjson.Set(body, "exporter-map"+"."+strconv.Itoa(index)+"."+"version.options.class-table.timeout", strconv.FormatInt(item.VersionOptionsClassTableTimeout.ValueInt64(), 10)) + } + if !item.VersionOptionsVrfTableTimeout.IsNull() && !item.VersionOptionsVrfTableTimeout.IsUnknown() { + body, _ = sjson.Set(body, "exporter-map"+"."+strconv.Itoa(index)+"."+"version.options.vrf-table.timeout", strconv.FormatInt(item.VersionOptionsVrfTableTimeout.ValueInt64(), 10)) + } + } + } + return body +} + +func (data *FlowExporterMap) updateFromBody(ctx context.Context, res []byte) { + for i := range data.ExporterMaps { + keys := [...]string{"exporter-map-name"} + keyValues := [...]string{data.ExporterMaps[i].ExporterMapName.ValueString()} + + var r gjson.Result + gjson.GetBytes(res, "exporter-map").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("exporter-map-name"); value.Exists() && !data.ExporterMaps[i].ExporterMapName.IsNull() { + data.ExporterMaps[i].ExporterMapName = types.StringValue(value.String()) + } else { + data.ExporterMaps[i].ExporterMapName = types.StringNull() + } + if value := r.Get("destination.ipv4-address"); value.Exists() && !data.ExporterMaps[i].DestinationIpv4Address.IsNull() { + data.ExporterMaps[i].DestinationIpv4Address = types.StringValue(value.String()) + } else { + data.ExporterMaps[i].DestinationIpv4Address = types.StringNull() + } + if value := r.Get("destination.ipv6-address"); value.Exists() && !data.ExporterMaps[i].DestinationIpv6Address.IsNull() { + data.ExporterMaps[i].DestinationIpv6Address = types.StringValue(value.String()) + } else { + data.ExporterMaps[i].DestinationIpv6Address = types.StringNull() + } + if value := r.Get("destination.vrf"); value.Exists() && !data.ExporterMaps[i].DestinationVrf.IsNull() { + data.ExporterMaps[i].DestinationVrf = types.StringValue(value.String()) + } else { + data.ExporterMaps[i].DestinationVrf = types.StringNull() + } + if value := r.Get("source"); value.Exists() && !data.ExporterMaps[i].Source.IsNull() { + data.ExporterMaps[i].Source = types.StringValue(value.String()) + } else { + data.ExporterMaps[i].Source = types.StringNull() + } + if value := r.Get("dscp"); value.Exists() && !data.ExporterMaps[i].Dscp.IsNull() { + data.ExporterMaps[i].Dscp = types.Int64Value(value.Int()) + } else { + data.ExporterMaps[i].Dscp = types.Int64Null() + } + if value := r.Get("packet-length"); value.Exists() && !data.ExporterMaps[i].PacketLength.IsNull() { + data.ExporterMaps[i].PacketLength = types.Int64Value(value.Int()) + } else { + data.ExporterMaps[i].PacketLength = types.Int64Null() + } + if value := r.Get("transport.udp"); value.Exists() && !data.ExporterMaps[i].TransportUdp.IsNull() { + data.ExporterMaps[i].TransportUdp = types.Int64Value(value.Int()) + } else { + data.ExporterMaps[i].TransportUdp = types.Int64Null() + } + if value := r.Get("dfbit.set"); !data.ExporterMaps[i].DfbitSet.IsNull() { + if value.Exists() { + data.ExporterMaps[i].DfbitSet = types.BoolValue(true) + } else { + data.ExporterMaps[i].DfbitSet = types.BoolValue(false) + } + } else { + data.ExporterMaps[i].DfbitSet = types.BoolNull() + } + if value := r.Get("version.export-format"); value.Exists() && !data.ExporterMaps[i].VersionExportFormat.IsNull() { + data.ExporterMaps[i].VersionExportFormat = types.StringValue(value.String()) + } else { + data.ExporterMaps[i].VersionExportFormat = types.StringNull() + } + if value := r.Get("version.template.data.timeout"); value.Exists() && !data.ExporterMaps[i].VersionTemplateDataTimeout.IsNull() { + data.ExporterMaps[i].VersionTemplateDataTimeout = types.Int64Value(value.Int()) + } else { + data.ExporterMaps[i].VersionTemplateDataTimeout = types.Int64Null() + } + if value := r.Get("version.template.options.timeout"); value.Exists() && !data.ExporterMaps[i].VersionTemplateOptionsTimeout.IsNull() { + data.ExporterMaps[i].VersionTemplateOptionsTimeout = types.Int64Value(value.Int()) + } else { + data.ExporterMaps[i].VersionTemplateOptionsTimeout = types.Int64Null() + } + if value := r.Get("version.template.timeout"); value.Exists() && !data.ExporterMaps[i].VersionTemplateTimeout.IsNull() { + data.ExporterMaps[i].VersionTemplateTimeout = types.Int64Value(value.Int()) + } else { + data.ExporterMaps[i].VersionTemplateTimeout = types.Int64Null() + } + if value := r.Get("version.options.interface-table.timeout"); value.Exists() && !data.ExporterMaps[i].VersionOptionsInterfaceTableTimeout.IsNull() { + data.ExporterMaps[i].VersionOptionsInterfaceTableTimeout = types.Int64Value(value.Int()) + } else { + data.ExporterMaps[i].VersionOptionsInterfaceTableTimeout = types.Int64Null() + } + if value := r.Get("version.options.sampler-table.timeout"); value.Exists() && !data.ExporterMaps[i].VersionOptionsSamplerTableTimeout.IsNull() { + data.ExporterMaps[i].VersionOptionsSamplerTableTimeout = types.Int64Value(value.Int()) + } else { + data.ExporterMaps[i].VersionOptionsSamplerTableTimeout = types.Int64Null() + } + if value := r.Get("version.options.class-table.timeout"); value.Exists() && !data.ExporterMaps[i].VersionOptionsClassTableTimeout.IsNull() { + data.ExporterMaps[i].VersionOptionsClassTableTimeout = types.Int64Value(value.Int()) + } else { + data.ExporterMaps[i].VersionOptionsClassTableTimeout = types.Int64Null() + } + if value := r.Get("version.options.vrf-table.timeout"); value.Exists() && !data.ExporterMaps[i].VersionOptionsVrfTableTimeout.IsNull() { + data.ExporterMaps[i].VersionOptionsVrfTableTimeout = types.Int64Value(value.Int()) + } else { + data.ExporterMaps[i].VersionOptionsVrfTableTimeout = types.Int64Null() + } + } +} + +func (data *FlowExporterMapData) fromBody(ctx context.Context, res []byte) { + if value := gjson.GetBytes(res, "exporter-map"); value.Exists() { + data.ExporterMaps = make([]FlowExporterMapExporterMaps, 0) + value.ForEach(func(k, v gjson.Result) bool { + item := FlowExporterMapExporterMaps{} + if cValue := v.Get("exporter-map-name"); cValue.Exists() { + item.ExporterMapName = types.StringValue(cValue.String()) + } + if cValue := v.Get("destination.ipv4-address"); cValue.Exists() { + item.DestinationIpv4Address = types.StringValue(cValue.String()) + } + if cValue := v.Get("destination.ipv6-address"); cValue.Exists() { + item.DestinationIpv6Address = types.StringValue(cValue.String()) + } + if cValue := v.Get("destination.vrf"); cValue.Exists() { + item.DestinationVrf = types.StringValue(cValue.String()) + } + if cValue := v.Get("source"); cValue.Exists() { + item.Source = types.StringValue(cValue.String()) + } + if cValue := v.Get("dscp"); cValue.Exists() { + item.Dscp = types.Int64Value(cValue.Int()) + } + if cValue := v.Get("packet-length"); cValue.Exists() { + item.PacketLength = types.Int64Value(cValue.Int()) + } + if cValue := v.Get("transport.udp"); cValue.Exists() { + item.TransportUdp = types.Int64Value(cValue.Int()) + } + if cValue := v.Get("dfbit.set"); cValue.Exists() { + item.DfbitSet = types.BoolValue(true) + } else { + item.DfbitSet = types.BoolValue(false) + } + if cValue := v.Get("version.export-format"); cValue.Exists() { + item.VersionExportFormat = types.StringValue(cValue.String()) + } + if cValue := v.Get("version.template.data.timeout"); cValue.Exists() { + item.VersionTemplateDataTimeout = types.Int64Value(cValue.Int()) + } + if cValue := v.Get("version.template.options.timeout"); cValue.Exists() { + item.VersionTemplateOptionsTimeout = types.Int64Value(cValue.Int()) + } + if cValue := v.Get("version.template.timeout"); cValue.Exists() { + item.VersionTemplateTimeout = types.Int64Value(cValue.Int()) + } + if cValue := v.Get("version.options.interface-table.timeout"); cValue.Exists() { + item.VersionOptionsInterfaceTableTimeout = types.Int64Value(cValue.Int()) + } + if cValue := v.Get("version.options.sampler-table.timeout"); cValue.Exists() { + item.VersionOptionsSamplerTableTimeout = types.Int64Value(cValue.Int()) + } + if cValue := v.Get("version.options.class-table.timeout"); cValue.Exists() { + item.VersionOptionsClassTableTimeout = types.Int64Value(cValue.Int()) + } + if cValue := v.Get("version.options.vrf-table.timeout"); cValue.Exists() { + item.VersionOptionsVrfTableTimeout = types.Int64Value(cValue.Int()) + } + data.ExporterMaps = append(data.ExporterMaps, item) + return true + }) + } +} + +func (data *FlowExporterMap) getDeletedListItems(ctx context.Context, state FlowExporterMap) []string { + deletedListItems := make([]string, 0) + for i := range state.ExporterMaps { + keys := [...]string{"exporter-map-name"} + stateKeyValues := [...]string{state.ExporterMaps[i].ExporterMapName.ValueString()} + + emptyKeys := true + if !reflect.ValueOf(state.ExporterMaps[i].ExporterMapName.ValueString()).IsZero() { + emptyKeys = false + } + if emptyKeys { + continue + } + + found := false + for j := range data.ExporterMaps { + found = true + if state.ExporterMaps[i].ExporterMapName.ValueString() != data.ExporterMaps[j].ExporterMapName.ValueString() { + found = false + } + if found { + break + } + } + if !found { + keyString := "" + for ki := range keys { + keyString += "[" + keys[ki] + "=" + stateKeyValues[ki] + "]" + } + deletedListItems = append(deletedListItems, fmt.Sprintf("%v/exporter-map%v", state.getPath(), keyString)) + } + } + return deletedListItems +} + +func (data *FlowExporterMap) getEmptyLeafsDelete(ctx context.Context) []string { + emptyLeafsDelete := make([]string, 0) + for i := range data.ExporterMaps { + keys := [...]string{"exporter-map-name"} + keyValues := [...]string{data.ExporterMaps[i].ExporterMapName.ValueString()} + keyString := "" + for ki := range keys { + keyString += "[" + keys[ki] + "=" + keyValues[ki] + "]" + } + if !data.ExporterMaps[i].DfbitSet.IsNull() && !data.ExporterMaps[i].DfbitSet.ValueBool() { + emptyLeafsDelete = append(emptyLeafsDelete, fmt.Sprintf("%v/exporter-map%v/dfbit/set", data.getPath(), keyString)) + } + } + return emptyLeafsDelete +} + +func (data *FlowExporterMap) getDeletePaths(ctx context.Context) []string { + var deletePaths []string + for i := range data.ExporterMaps { + keys := [...]string{"exporter-map-name"} + keyValues := [...]string{data.ExporterMaps[i].ExporterMapName.ValueString()} + + keyString := "" + for ki := range keys { + keyString += "[" + keys[ki] + "=" + keyValues[ki] + "]" + } + deletePaths = append(deletePaths, fmt.Sprintf("%v/exporter-map%v", data.getPath(), keyString)) + } + return deletePaths +} diff --git a/internal/provider/provider.go b/internal/provider/provider.go index 1441209c..389fbc68 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -318,6 +318,7 @@ func (p *iosxrProvider) Resources(ctx context.Context) []func() resource.Resourc NewGnmiResource, NewASPathSetResource, NewBannerResource, + NewBFDResource, NewBGPASFormatResource, NewCDPResource, NewClassMapQoSResource, @@ -335,6 +336,7 @@ func (p *iosxrProvider) Resources(ctx context.Context) []func() resource.Resourc NewExtcommunityOpaqueSetResource, NewExtcommunityRTSetResource, NewExtcommunitySOOSetResource, + NewFlowExporterMapResource, NewFlowMonitorMapResource, NewFlowSamplerMapResource, NewFPDResource, @@ -409,6 +411,7 @@ func (p *iosxrProvider) DataSources(ctx context.Context) []func() datasource.Dat NewGnmiDataSource, NewASPathSetDataSource, NewBannerDataSource, + NewBFDDataSource, NewBGPASFormatDataSource, NewCDPDataSource, NewClassMapQoSDataSource, @@ -426,6 +429,7 @@ func (p *iosxrProvider) DataSources(ctx context.Context) []func() datasource.Dat NewExtcommunityOpaqueSetDataSource, NewExtcommunityRTSetDataSource, NewExtcommunitySOOSetDataSource, + NewFlowExporterMapDataSource, NewFlowMonitorMapDataSource, NewFlowSamplerMapDataSource, NewFPDDataSource, diff --git a/internal/provider/resource_iosxr_bfd.go b/internal/provider/resource_iosxr_bfd.go new file mode 100644 index 00000000..2a73c473 --- /dev/null +++ b/internal/provider/resource_iosxr_bfd.go @@ -0,0 +1,444 @@ +// 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 + +import ( + "context" + "fmt" + "regexp" + + "github.com/CiscoDevNet/terraform-provider-iosxr/internal/provider/client" + "github.com/CiscoDevNet/terraform-provider-iosxr/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" +) + +func NewBFDResource() resource.Resource { + return &BFDResource{} +} + +type BFDResource struct { + client *client.Client +} + +func (r *BFDResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_bfd" +} + +func (r *BFDResource) 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 BFD 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"), + }, + }, + "echo_disable": schema.BoolAttribute{ + MarkdownDescription: helpers.NewAttributeDescription("Disable BFD echo mode").String, + Optional: true, + }, + "echo_latency_detect_percentage": schema.Int64Attribute{ + MarkdownDescription: helpers.NewAttributeDescription("Percentage of detection time to consider as bad latency").AddIntegerRangeDescription(100, 250).String, + Optional: true, + Validators: []validator.Int64{ + int64validator.Between(100, 250), + }, + }, + "echo_latency_detect_count": schema.Int64Attribute{ + MarkdownDescription: helpers.NewAttributeDescription("Count of consecutive bad latency packets to take session down").AddIntegerRangeDescription(1, 10).String, + Optional: true, + Validators: []validator.Int64{ + int64validator.Between(1, 10), + }, + }, + "echo_startup_validate_force": schema.BoolAttribute{ + MarkdownDescription: helpers.NewAttributeDescription("Ignore remote 'Required Min Echo RX Interval' setting").String, + Optional: true, + }, + "echo_ipv4_source": schema.StringAttribute{ + MarkdownDescription: helpers.NewAttributeDescription("BFD echo source IP address").String, + Optional: true, + Validators: []validator.String{ + 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}]+)?`), ""), + stringvalidator.RegexMatches(regexp.MustCompile(`[0-9\.]*`), ""), + }, + }, + "echo_ipv4_bundle_per_member_minimum_interval_preferred_minimum_interval": schema.Int64Attribute{ + MarkdownDescription: helpers.NewAttributeDescription("The preferred minimum interval (in ms) for the BFD session").AddIntegerRangeDescription(15, 2000).String, + Optional: true, + Validators: []validator.Int64{ + int64validator.Between(15, 2000), + }, + }, + "trap_singlehop_pre_mapped": schema.BoolAttribute{ + MarkdownDescription: helpers.NewAttributeDescription("Configure BFD trap pre-mapped").String, + Optional: true, + }, + "multipath_locations": schema.ListNestedAttribute{ + MarkdownDescription: helpers.NewAttributeDescription("Specify a location").String, + Optional: true, + NestedObject: schema.NestedAttributeObject{ + Attributes: map[string]schema.Attribute{ + "location_name": schema.StringAttribute{ + MarkdownDescription: helpers.NewAttributeDescription("Specify a location").String, + Required: true, + Validators: []validator.String{ + stringvalidator.RegexMatches(regexp.MustCompile(`([a-zA-Z0-9_]*\d+/){1,2}([a-zA-Z0-9_]*\d+)`), ""), + }, + }, + }, + }, + }, + "multihop_ttl_drop_threshold": schema.Int64Attribute{ + MarkdownDescription: helpers.NewAttributeDescription("TTL Drop Threshold").AddIntegerRangeDescription(0, 254).String, + Optional: true, + Validators: []validator.Int64{ + int64validator.Between(0, 254), + }, + }, + "dampening_initial_wait": schema.Int64Attribute{ + MarkdownDescription: helpers.NewAttributeDescription("Initial delay before bringing up session").AddIntegerRangeDescription(1, 3600000).String, + Optional: true, + Validators: []validator.Int64{ + int64validator.Between(1, 3600000), + }, + }, + "dampening_secondary_wait": schema.Int64Attribute{ + MarkdownDescription: helpers.NewAttributeDescription("Secondary delay before bringing up session").AddIntegerRangeDescription(1, 3600000).String, + Optional: true, + Validators: []validator.Int64{ + int64validator.Between(1, 3600000), + }, + }, + "dampening_maximum_wait": schema.Int64Attribute{ + MarkdownDescription: helpers.NewAttributeDescription("Maximum delay before bringing up session").AddIntegerRangeDescription(1, 3600000).String, + Optional: true, + Validators: []validator.Int64{ + int64validator.Between(1, 3600000), + }, + }, + "dampening_threshold": schema.Int64Attribute{ + MarkdownDescription: helpers.NewAttributeDescription("Stability threshold to enable dampening").AddIntegerRangeDescription(60000, 3600000).String, + Optional: true, + Validators: []validator.Int64{ + int64validator.Between(60000, 3600000), + }, + }, + "dampening_extensions_down_monitoring": schema.BoolAttribute{ + MarkdownDescription: helpers.NewAttributeDescription("Enable DOWN state session monitoring extensions").String, + Optional: true, + }, + "dampening_disable": schema.BoolAttribute{ + MarkdownDescription: helpers.NewAttributeDescription("Disable BFD dampening").String, + Optional: true, + }, + "dampening_bundle_member_l3_only_mode": schema.BoolAttribute{ + MarkdownDescription: helpers.NewAttributeDescription("Apply immediate dampening and only when failure is L3 specific").String, + Optional: true, + }, + "dampening_bundle_member_initial_wait": schema.Int64Attribute{ + MarkdownDescription: helpers.NewAttributeDescription("Initial delay before bringing up session").AddIntegerRangeDescription(1, 518400000).String, + Optional: true, + Validators: []validator.Int64{ + int64validator.Between(1, 518400000), + }, + }, + "dampening_bundle_member_secondary_wait": schema.Int64Attribute{ + MarkdownDescription: helpers.NewAttributeDescription("Secondary delay before bringing up session").AddIntegerRangeDescription(1, 518400000).String, + Optional: true, + Validators: []validator.Int64{ + int64validator.Between(1, 518400000), + }, + }, + "dampening_bundle_member_maximum_wait": schema.Int64Attribute{ + MarkdownDescription: helpers.NewAttributeDescription("Maximum delay before bringing up session").AddIntegerRangeDescription(1, 518400000).String, + Optional: true, + Validators: []validator.Int64{ + int64validator.Between(1, 518400000), + }, + }, + "bundle_coexistence_bob_blb_inherit": schema.BoolAttribute{ + MarkdownDescription: helpers.NewAttributeDescription("Use inheritence mechanism").String, + Optional: true, + }, + "bundle_coexistence_bob_blb_logical": schema.BoolAttribute{ + MarkdownDescription: helpers.NewAttributeDescription("Use BFD logical Bundle natively").String, + Optional: true, + }, + "interfaces": schema.ListNestedAttribute{ + MarkdownDescription: helpers.NewAttributeDescription("Configure BFD on an interface").String, + Optional: true, + NestedObject: schema.NestedAttributeObject{ + Attributes: map[string]schema.Attribute{ + "interface_name": schema.StringAttribute{ + MarkdownDescription: helpers.NewAttributeDescription("Configure BFD on an interface").String, + Required: true, + Validators: []validator.String{ + stringvalidator.RegexMatches(regexp.MustCompile(`[a-zA-Z0-9.:_/-]+`), ""), + }, + }, + "echo_disable": schema.BoolAttribute{ + MarkdownDescription: helpers.NewAttributeDescription("Disable BFD echo mode for this interface").String, + Optional: true, + }, + "echo_ipv4_source": schema.StringAttribute{ + MarkdownDescription: helpers.NewAttributeDescription("BFD echo source IP address").String, + Optional: true, + Validators: []validator.String{ + 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}]+)?`), ""), + stringvalidator.RegexMatches(regexp.MustCompile(`[0-9\.]*`), ""), + }, + }, + "ipv6_checksum_disable": schema.BoolAttribute{ + MarkdownDescription: helpers.NewAttributeDescription("Disable BFD ipv6 checksum mode for this interface").String, + Optional: true, + }, + "disable": schema.BoolAttribute{ + MarkdownDescription: helpers.NewAttributeDescription("Disable BFD for this interface").String, + Optional: true, + }, + "local_address": schema.StringAttribute{ + MarkdownDescription: helpers.NewAttributeDescription("Local address to be used by BFD for this interface").String, + Optional: true, + }, + "tx_interval": schema.Int64Attribute{ + MarkdownDescription: helpers.NewAttributeDescription("BFD TX Interval for this interface in microseconds").AddIntegerRangeDescription(3000, 30000000).String, + Optional: true, + Validators: []validator.Int64{ + int64validator.Between(3000, 30000000), + }, + }, + "rx_interval": schema.Int64Attribute{ + MarkdownDescription: helpers.NewAttributeDescription("BFD RX Interval for this interface in microseconds").AddIntegerRangeDescription(3000, 30000000).String, + Optional: true, + Validators: []validator.Int64{ + int64validator.Between(3000, 30000000), + }, + }, + "multiplier": schema.Int64Attribute{ + MarkdownDescription: helpers.NewAttributeDescription("BFD multiplier for this interface").AddIntegerRangeDescription(2, 50).String, + Optional: true, + Validators: []validator.Int64{ + int64validator.Between(2, 50), + }, + }, + }, + }, + }, + "ipv6_checksum_disable": schema.BoolAttribute{ + MarkdownDescription: helpers.NewAttributeDescription("Disable BFD checksum").String, + Optional: true, + }, + }, + } +} + +func (r *BFDResource) Configure(_ context.Context, req resource.ConfigureRequest, _ *resource.ConfigureResponse) { + if req.ProviderData == nil { + return + } + + r.client = req.ProviderData.(*client.Client) +} + +func (r *BFDResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { + var plan BFD + + // Read plan + diags := req.Plan.Get(ctx, &plan) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + var ops []client.SetOperation + + tflog.Debug(ctx, fmt.Sprintf("%s: Beginning Create", plan.getPath())) + + // Create object + body := plan.toBody(ctx) + ops = append(ops, client.SetOperation{Path: plan.getPath(), Body: body, Operation: client.Update}) + + emptyLeafsDelete := plan.getEmptyLeafsDelete(ctx) + tflog.Debug(ctx, fmt.Sprintf("List of empty leafs to delete: %+v", emptyLeafsDelete)) + + for _, i := range emptyLeafsDelete { + ops = append(ops, client.SetOperation{Path: i, Body: "", Operation: client.Delete}) + } + + _, diags = r.client.Set(ctx, plan.Device.ValueString(), ops...) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + 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...) +} + +func (r *BFDResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { + var state BFD + + // 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())) + + getResp, diags := r.client.Get(ctx, state.Device.ValueString(), state.Id.ValueString()) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + state.updateFromBody(ctx, getResp.Notification[0].Update[0].Val.GetJsonIetfVal()) + + tflog.Debug(ctx, fmt.Sprintf("%s: Read finished successfully", state.Id.ValueString())) + + diags = resp.State.Set(ctx, &state) + resp.Diagnostics.Append(diags...) +} + +func (r *BFDResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { + var plan, state BFD + + // 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 + } + + var ops []client.SetOperation + + tflog.Debug(ctx, fmt.Sprintf("%s: Beginning Update", plan.Id.ValueString())) + + // Update object + body := plan.toBody(ctx) + ops = append(ops, client.SetOperation{Path: plan.getPath(), Body: body, Operation: client.Update}) + + deletedListItems := plan.getDeletedListItems(ctx, state) + tflog.Debug(ctx, fmt.Sprintf("List items to delete: %+v", deletedListItems)) + + for _, i := range deletedListItems { + ops = append(ops, client.SetOperation{Path: i, Body: "", Operation: client.Delete}) + } + + emptyLeafsDelete := plan.getEmptyLeafsDelete(ctx) + tflog.Debug(ctx, fmt.Sprintf("List of empty leafs to delete: %+v", emptyLeafsDelete)) + + for _, i := range emptyLeafsDelete { + ops = append(ops, client.SetOperation{Path: i, Body: "", Operation: client.Delete}) + } + + _, diags = r.client.Set(ctx, plan.Device.ValueString(), ops...) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + tflog.Debug(ctx, fmt.Sprintf("%s: Update finished successfully", plan.Id.ValueString())) + + diags = resp.State.Set(ctx, &plan) + resp.Diagnostics.Append(diags...) +} + +func (r *BFDResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { + var state BFD + + // 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())) + var ops []client.SetOperation + deleteMode := "all" + if state.DeleteMode.ValueString() == "all" { + deleteMode = "all" + } else if state.DeleteMode.ValueString() == "attributes" { + deleteMode = "attributes" + } + + if deleteMode == "all" { + ops = append(ops, client.SetOperation{Path: state.Id.ValueString(), Body: "", Operation: client.Delete}) + } else { + deletePaths := state.getDeletePaths(ctx) + tflog.Debug(ctx, fmt.Sprintf("Paths to delete: %+v", deletePaths)) + + for _, i := range deletePaths { + ops = append(ops, client.SetOperation{Path: i, Body: "", Operation: client.Delete}) + } + } + + _, diags = r.client.Set(ctx, state.Device.ValueString(), ops...) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + tflog.Debug(ctx, fmt.Sprintf("%s: Delete finished successfully", state.Id.ValueString())) + + resp.State.RemoveResource(ctx) +} + +func (r *BFDResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { + resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp) +} diff --git a/internal/provider/resource_iosxr_bfd_test.go b/internal/provider/resource_iosxr_bfd_test.go new file mode 100644 index 00000000..98f2ca19 --- /dev/null +++ b/internal/provider/resource_iosxr_bfd_test.go @@ -0,0 +1,129 @@ +// 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 + +import ( + "os" + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" +) + +func TestAccIosxrBFD(t *testing.T) { + var checks []resource.TestCheckFunc + checks = append(checks, resource.TestCheckResourceAttr("iosxr_bfd.test", "echo_disable", "true")) + checks = append(checks, resource.TestCheckResourceAttr("iosxr_bfd.test", "echo_latency_detect_percentage", "200")) + checks = append(checks, resource.TestCheckResourceAttr("iosxr_bfd.test", "echo_latency_detect_count", "10")) + checks = append(checks, resource.TestCheckResourceAttr("iosxr_bfd.test", "echo_startup_validate_force", "true")) + checks = append(checks, resource.TestCheckResourceAttr("iosxr_bfd.test", "echo_ipv4_source", "10.1.1.1")) + checks = append(checks, resource.TestCheckResourceAttr("iosxr_bfd.test", "echo_ipv4_bundle_per_member_minimum_interval_preferred_minimum_interval", "200")) + checks = append(checks, resource.TestCheckResourceAttr("iosxr_bfd.test", "trap_singlehop_pre_mapped", "true")) + checks = append(checks, resource.TestCheckResourceAttr("iosxr_bfd.test", "multipath_locations.0.location_name", "0/0/CPU0")) + checks = append(checks, resource.TestCheckResourceAttr("iosxr_bfd.test", "multihop_ttl_drop_threshold", "200")) + checks = append(checks, resource.TestCheckResourceAttr("iosxr_bfd.test", "dampening_initial_wait", "3600")) + checks = append(checks, resource.TestCheckResourceAttr("iosxr_bfd.test", "dampening_secondary_wait", "3200")) + checks = append(checks, resource.TestCheckResourceAttr("iosxr_bfd.test", "dampening_maximum_wait", "3100")) + checks = append(checks, resource.TestCheckResourceAttr("iosxr_bfd.test", "dampening_threshold", "60000")) + checks = append(checks, resource.TestCheckResourceAttr("iosxr_bfd.test", "dampening_extensions_down_monitoring", "true")) + checks = append(checks, resource.TestCheckResourceAttr("iosxr_bfd.test", "dampening_disable", "true")) + checks = append(checks, resource.TestCheckResourceAttr("iosxr_bfd.test", "dampening_bundle_member_l3_only_mode", "true")) + checks = append(checks, resource.TestCheckResourceAttr("iosxr_bfd.test", "dampening_bundle_member_initial_wait", "5184")) + checks = append(checks, resource.TestCheckResourceAttr("iosxr_bfd.test", "dampening_bundle_member_secondary_wait", "6184")) + checks = append(checks, resource.TestCheckResourceAttr("iosxr_bfd.test", "dampening_bundle_member_maximum_wait", "7184")) + checks = append(checks, resource.TestCheckResourceAttr("iosxr_bfd.test", "bundle_coexistence_bob_blb_inherit", "false")) + checks = append(checks, resource.TestCheckResourceAttr("iosxr_bfd.test", "bundle_coexistence_bob_blb_logical", "true")) + checks = append(checks, resource.TestCheckResourceAttr("iosxr_bfd.test", "interfaces.0.interface_name", "GigabitEthernet0/0/0/0")) + checks = append(checks, resource.TestCheckResourceAttr("iosxr_bfd.test", "interfaces.0.echo_disable", "true")) + checks = append(checks, resource.TestCheckResourceAttr("iosxr_bfd.test", "interfaces.0.echo_ipv4_source", "12.1.1.1")) + checks = append(checks, resource.TestCheckResourceAttr("iosxr_bfd.test", "interfaces.0.ipv6_checksum_disable", "true")) + checks = append(checks, resource.TestCheckResourceAttr("iosxr_bfd.test", "interfaces.0.disable", "true")) + checks = append(checks, resource.TestCheckResourceAttr("iosxr_bfd.test", "interfaces.0.local_address", "33.33.31.1")) + checks = append(checks, resource.TestCheckResourceAttr("iosxr_bfd.test", "interfaces.0.tx_interval", "3200")) + checks = append(checks, resource.TestCheckResourceAttr("iosxr_bfd.test", "interfaces.0.rx_interval", "4200")) + checks = append(checks, resource.TestCheckResourceAttr("iosxr_bfd.test", "interfaces.0.multiplier", "40")) + checks = append(checks, resource.TestCheckResourceAttr("iosxr_bfd.test", "ipv6_checksum_disable", "true")) + var steps []resource.TestStep + if os.Getenv("SKIP_MINIMUM_TEST") == "" { + steps = append(steps, resource.TestStep{ + Config: testAccIosxrBFDConfig_minimum(), + }) + } + steps = append(steps, resource.TestStep{ + Config: testAccIosxrBFDConfig_all(), + Check: resource.ComposeTestCheckFunc(checks...), + }) + steps = append(steps, resource.TestStep{ + ResourceName: "iosxr_bfd.test", + ImportState: true, + ImportStateId: "Cisco-IOS-XR-um-bfd-sbfd-cfg:/bfd", + }) + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, + Steps: steps, + }) +} + +func testAccIosxrBFDConfig_minimum() string { + config := `resource "iosxr_bfd" "test" {` + "\n" + config += `}` + "\n" + return config +} + +func testAccIosxrBFDConfig_all() string { + config := `resource "iosxr_bfd" "test" {` + "\n" + config += ` echo_disable = true` + "\n" + config += ` echo_latency_detect_percentage = 200` + "\n" + config += ` echo_latency_detect_count = 10` + "\n" + config += ` echo_startup_validate_force = true` + "\n" + config += ` echo_ipv4_source = "10.1.1.1"` + "\n" + config += ` echo_ipv4_bundle_per_member_minimum_interval_preferred_minimum_interval = 200` + "\n" + config += ` trap_singlehop_pre_mapped = true` + "\n" + config += ` multipath_locations = [{` + "\n" + config += ` location_name = "0/0/CPU0"` + "\n" + config += ` }]` + "\n" + config += ` multihop_ttl_drop_threshold = 200` + "\n" + config += ` dampening_initial_wait = 3600` + "\n" + config += ` dampening_secondary_wait = 3200` + "\n" + config += ` dampening_maximum_wait = 3100` + "\n" + config += ` dampening_threshold = 60000` + "\n" + config += ` dampening_extensions_down_monitoring = true` + "\n" + config += ` dampening_disable = true` + "\n" + config += ` dampening_bundle_member_l3_only_mode = true` + "\n" + config += ` dampening_bundle_member_initial_wait = 5184` + "\n" + config += ` dampening_bundle_member_secondary_wait = 6184` + "\n" + config += ` dampening_bundle_member_maximum_wait = 7184` + "\n" + config += ` bundle_coexistence_bob_blb_inherit = false` + "\n" + config += ` bundle_coexistence_bob_blb_logical = true` + "\n" + config += ` interfaces = [{` + "\n" + config += ` interface_name = "GigabitEthernet0/0/0/0"` + "\n" + config += ` echo_disable = true` + "\n" + config += ` echo_ipv4_source = "12.1.1.1"` + "\n" + config += ` ipv6_checksum_disable = true` + "\n" + config += ` disable = true` + "\n" + config += ` local_address = "33.33.31.1"` + "\n" + config += ` tx_interval = 3200` + "\n" + config += ` rx_interval = 4200` + "\n" + config += ` multiplier = 40` + "\n" + config += ` }]` + "\n" + config += ` ipv6_checksum_disable = true` + "\n" + config += `}` + "\n" + return config +} diff --git a/internal/provider/resource_iosxr_flow_exporter_map.go b/internal/provider/resource_iosxr_flow_exporter_map.go new file mode 100644 index 00000000..8005adf5 --- /dev/null +++ b/internal/provider/resource_iosxr_flow_exporter_map.go @@ -0,0 +1,365 @@ +// 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 + +import ( + "context" + "fmt" + "regexp" + + "github.com/CiscoDevNet/terraform-provider-iosxr/internal/provider/client" + "github.com/CiscoDevNet/terraform-provider-iosxr/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" +) + +func NewFlowExporterMapResource() resource.Resource { + return &FlowExporterMapResource{} +} + +type FlowExporterMapResource struct { + client *client.Client +} + +func (r *FlowExporterMapResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_flow_exporter_map" +} + +func (r *FlowExporterMapResource) 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 Flow Exporter Map 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(), + }, + }, + "exporter_maps": schema.ListNestedAttribute{ + MarkdownDescription: helpers.NewAttributeDescription("Exporter map name - maximum 32 characters").String, + Optional: true, + NestedObject: schema.NestedAttributeObject{ + Attributes: map[string]schema.Attribute{ + "exporter_map_name": schema.StringAttribute{ + MarkdownDescription: helpers.NewAttributeDescription("Exporter map name - maximum 32 characters").String, + Required: true, + Validators: []validator.String{ + stringvalidator.LengthBetween(1, 32), + stringvalidator.RegexMatches(regexp.MustCompile(`[\w\-\.:,_@#%$\+=\|;]+`), ""), + }, + }, + "destination_ipv4_address": schema.StringAttribute{ + MarkdownDescription: helpers.NewAttributeDescription("Destination IPv4 address").String, + Optional: true, + Validators: []validator.String{ + 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}]+)?`), ""), + stringvalidator.RegexMatches(regexp.MustCompile(`[0-9\.]*`), ""), + }, + }, + "destination_ipv6_address": schema.StringAttribute{ + MarkdownDescription: helpers.NewAttributeDescription("Destination IPv6 address").String, + Optional: true, + Validators: []validator.String{ + stringvalidator.RegexMatches(regexp.MustCompile(`((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))(%[\p{N}\p{L}]+)?`), ""), + stringvalidator.RegexMatches(regexp.MustCompile(`(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)(%.+)?`), ""), + stringvalidator.RegexMatches(regexp.MustCompile(`[0-9a-fA-F:\.]*`), ""), + }, + }, + "destination_vrf": schema.StringAttribute{ + MarkdownDescription: helpers.NewAttributeDescription("Configure VRF to be used for reaching export destination").String, + Optional: true, + Validators: []validator.String{ + stringvalidator.LengthBetween(1, 32), + stringvalidator.RegexMatches(regexp.MustCompile(`[\w\-\.:,_@#%$\+=\|;]+`), ""), + }, + }, + "source": schema.StringAttribute{ + MarkdownDescription: helpers.NewAttributeDescription("Source interface").String, + Optional: true, + Validators: []validator.String{ + stringvalidator.RegexMatches(regexp.MustCompile(`[a-zA-Z0-9.:_/-]+`), ""), + }, + }, + "dscp": schema.Int64Attribute{ + MarkdownDescription: helpers.NewAttributeDescription("Specify DSCP value for ipv4 export packets or traffic-class for ipv6 export packets").AddIntegerRangeDescription(0, 63).String, + Optional: true, + Validators: []validator.Int64{ + int64validator.Between(0, 63), + }, + }, + "packet_length": schema.Int64Attribute{ + MarkdownDescription: helpers.NewAttributeDescription("Export Packet maximum L3 length, should conform to outgoing interface mtu").AddIntegerRangeDescription(512, 9000).String, + Optional: true, + Validators: []validator.Int64{ + int64validator.Between(512, 9000), + }, + }, + "transport_udp": schema.Int64Attribute{ + MarkdownDescription: helpers.NewAttributeDescription("Use UDP as transport protocol").AddIntegerRangeDescription(1024, 65535).String, + Optional: true, + Validators: []validator.Int64{ + int64validator.Between(1024, 65535), + }, + }, + "dfbit_set": schema.BoolAttribute{ + MarkdownDescription: helpers.NewAttributeDescription("Set Export Packet Do Not Fragment Flag").String, + Optional: true, + }, + "version_export_format": schema.StringAttribute{ + MarkdownDescription: helpers.NewAttributeDescription("Specify export format").AddStringEnumDescription("ipfix", "protobuf", "sflow", "v9").String, + Required: true, + Validators: []validator.String{ + stringvalidator.OneOf("ipfix", "protobuf", "sflow", "v9"), + }, + }, + "version_template_data_timeout": schema.Int64Attribute{ + MarkdownDescription: helpers.NewAttributeDescription("Specify custom timeout for the template").AddIntegerRangeDescription(1, 604800).String, + Optional: true, + Validators: []validator.Int64{ + int64validator.Between(1, 604800), + }, + }, + "version_template_options_timeout": schema.Int64Attribute{ + MarkdownDescription: helpers.NewAttributeDescription("Specify custom timeout for the template").AddIntegerRangeDescription(1, 604800).String, + Optional: true, + Validators: []validator.Int64{ + int64validator.Between(1, 604800), + }, + }, + "version_template_timeout": schema.Int64Attribute{ + MarkdownDescription: helpers.NewAttributeDescription("Specify custom timeout for the template").AddIntegerRangeDescription(1, 604800).String, + Optional: true, + Validators: []validator.Int64{ + int64validator.Between(1, 604800), + }, + }, + "version_options_interface_table_timeout": schema.Int64Attribute{ + MarkdownDescription: helpers.NewAttributeDescription("Specify export timeout").AddIntegerRangeDescription(1, 604800).String, + Optional: true, + Validators: []validator.Int64{ + int64validator.Between(1, 604800), + }, + }, + "version_options_sampler_table_timeout": schema.Int64Attribute{ + MarkdownDescription: helpers.NewAttributeDescription("Specify export timeout").AddIntegerRangeDescription(1, 604800).String, + Optional: true, + Validators: []validator.Int64{ + int64validator.Between(1, 604800), + }, + }, + "version_options_class_table_timeout": schema.Int64Attribute{ + MarkdownDescription: helpers.NewAttributeDescription("Specify export timeout").AddIntegerRangeDescription(1, 604800).String, + Optional: true, + Validators: []validator.Int64{ + int64validator.Between(1, 604800), + }, + }, + "version_options_vrf_table_timeout": schema.Int64Attribute{ + MarkdownDescription: helpers.NewAttributeDescription("Specify export timeout").AddIntegerRangeDescription(1, 604800).String, + Optional: true, + Validators: []validator.Int64{ + int64validator.Between(1, 604800), + }, + }, + }, + }, + }, + }, + } +} + +func (r *FlowExporterMapResource) Configure(_ context.Context, req resource.ConfigureRequest, _ *resource.ConfigureResponse) { + if req.ProviderData == nil { + return + } + + r.client = req.ProviderData.(*client.Client) +} + +func (r *FlowExporterMapResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { + var plan FlowExporterMap + + // Read plan + diags := req.Plan.Get(ctx, &plan) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + var ops []client.SetOperation + + tflog.Debug(ctx, fmt.Sprintf("%s: Beginning Create", plan.getPath())) + + // Create object + body := plan.toBody(ctx) + ops = append(ops, client.SetOperation{Path: plan.getPath(), Body: body, Operation: client.Update}) + + emptyLeafsDelete := plan.getEmptyLeafsDelete(ctx) + tflog.Debug(ctx, fmt.Sprintf("List of empty leafs to delete: %+v", emptyLeafsDelete)) + + for _, i := range emptyLeafsDelete { + ops = append(ops, client.SetOperation{Path: i, Body: "", Operation: client.Delete}) + } + + _, diags = r.client.Set(ctx, plan.Device.ValueString(), ops...) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + 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...) +} + +func (r *FlowExporterMapResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { + var state FlowExporterMap + + // 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())) + + getResp, diags := r.client.Get(ctx, state.Device.ValueString(), state.Id.ValueString()) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + state.updateFromBody(ctx, getResp.Notification[0].Update[0].Val.GetJsonIetfVal()) + + tflog.Debug(ctx, fmt.Sprintf("%s: Read finished successfully", state.Id.ValueString())) + + diags = resp.State.Set(ctx, &state) + resp.Diagnostics.Append(diags...) +} + +func (r *FlowExporterMapResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { + var plan, state FlowExporterMap + + // 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 + } + + var ops []client.SetOperation + + tflog.Debug(ctx, fmt.Sprintf("%s: Beginning Update", plan.Id.ValueString())) + + // Update object + body := plan.toBody(ctx) + ops = append(ops, client.SetOperation{Path: plan.getPath(), Body: body, Operation: client.Update}) + + deletedListItems := plan.getDeletedListItems(ctx, state) + tflog.Debug(ctx, fmt.Sprintf("List items to delete: %+v", deletedListItems)) + + for _, i := range deletedListItems { + ops = append(ops, client.SetOperation{Path: i, Body: "", Operation: client.Delete}) + } + + emptyLeafsDelete := plan.getEmptyLeafsDelete(ctx) + tflog.Debug(ctx, fmt.Sprintf("List of empty leafs to delete: %+v", emptyLeafsDelete)) + + for _, i := range emptyLeafsDelete { + ops = append(ops, client.SetOperation{Path: i, Body: "", Operation: client.Delete}) + } + + _, diags = r.client.Set(ctx, plan.Device.ValueString(), ops...) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + tflog.Debug(ctx, fmt.Sprintf("%s: Update finished successfully", plan.Id.ValueString())) + + diags = resp.State.Set(ctx, &plan) + resp.Diagnostics.Append(diags...) +} + +func (r *FlowExporterMapResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { + var state FlowExporterMap + + // 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())) + var ops []client.SetOperation + deleteMode := "all" + + if deleteMode == "all" { + ops = append(ops, client.SetOperation{Path: state.Id.ValueString(), Body: "", Operation: client.Delete}) + } else { + deletePaths := state.getDeletePaths(ctx) + tflog.Debug(ctx, fmt.Sprintf("Paths to delete: %+v", deletePaths)) + + for _, i := range deletePaths { + ops = append(ops, client.SetOperation{Path: i, Body: "", Operation: client.Delete}) + } + } + + _, diags = r.client.Set(ctx, state.Device.ValueString(), ops...) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + tflog.Debug(ctx, fmt.Sprintf("%s: Delete finished successfully", state.Id.ValueString())) + + resp.State.RemoveResource(ctx) +} + +func (r *FlowExporterMapResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { + resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp) +} diff --git a/internal/provider/resource_iosxr_flow_exporter_map_test.go b/internal/provider/resource_iosxr_flow_exporter_map_test.go new file mode 100644 index 00000000..c57c85ed --- /dev/null +++ b/internal/provider/resource_iosxr_flow_exporter_map_test.go @@ -0,0 +1,99 @@ +// 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 + +import ( + "os" + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" +) + +func TestAccIosxrFlowExporterMap(t *testing.T) { + var checks []resource.TestCheckFunc + checks = append(checks, resource.TestCheckResourceAttr("iosxr_flow_exporter_map.test", "exporter_maps.0.exporter_map_name", "TEST")) + checks = append(checks, resource.TestCheckResourceAttr("iosxr_flow_exporter_map.test", "exporter_maps.0.destination_ipv4_address", "10.1.1.1")) + checks = append(checks, resource.TestCheckResourceAttr("iosxr_flow_exporter_map.test", "exporter_maps.0.destination_ipv6_address", "1::1")) + checks = append(checks, resource.TestCheckResourceAttr("iosxr_flow_exporter_map.test", "exporter_maps.0.destination_vrf", "28")) + checks = append(checks, resource.TestCheckResourceAttr("iosxr_flow_exporter_map.test", "exporter_maps.0.source", "10.1.1.4")) + checks = append(checks, resource.TestCheckResourceAttr("iosxr_flow_exporter_map.test", "exporter_maps.0.dscp", "62")) + checks = append(checks, resource.TestCheckResourceAttr("iosxr_flow_exporter_map.test", "exporter_maps.0.packet_length", "512")) + checks = append(checks, resource.TestCheckResourceAttr("iosxr_flow_exporter_map.test", "exporter_maps.0.transport_udp", "1033")) + checks = append(checks, resource.TestCheckResourceAttr("iosxr_flow_exporter_map.test", "exporter_maps.0.dfbit_set", "true")) + checks = append(checks, resource.TestCheckResourceAttr("iosxr_flow_exporter_map.test", "exporter_maps.0.version_export_format", "true")) + checks = append(checks, resource.TestCheckResourceAttr("iosxr_flow_exporter_map.test", "exporter_maps.0.version_template_data_timeout", "1024")) + checks = append(checks, resource.TestCheckResourceAttr("iosxr_flow_exporter_map.test", "exporter_maps.0.version_template_options_timeout", "3033")) + checks = append(checks, resource.TestCheckResourceAttr("iosxr_flow_exporter_map.test", "exporter_maps.0.version_template_timeout", "2222")) + checks = append(checks, resource.TestCheckResourceAttr("iosxr_flow_exporter_map.test", "exporter_maps.0.version_options_interface_table_timeout", "6048")) + checks = append(checks, resource.TestCheckResourceAttr("iosxr_flow_exporter_map.test", "exporter_maps.0.version_options_sampler_table_timeout", "4096")) + checks = append(checks, resource.TestCheckResourceAttr("iosxr_flow_exporter_map.test", "exporter_maps.0.version_options_class_table_timeout", "255")) + checks = append(checks, resource.TestCheckResourceAttr("iosxr_flow_exporter_map.test", "exporter_maps.0.version_options_vrf_table_timeout", "122")) + var steps []resource.TestStep + if os.Getenv("SKIP_MINIMUM_TEST") == "" { + steps = append(steps, resource.TestStep{ + Config: testAccIosxrFlowExporterMapConfig_minimum(), + }) + } + steps = append(steps, resource.TestStep{ + Config: testAccIosxrFlowExporterMapConfig_all(), + Check: resource.ComposeTestCheckFunc(checks...), + }) + steps = append(steps, resource.TestStep{ + ResourceName: "iosxr_flow_exporter_map.test", + ImportState: true, + ImportStateId: "Cisco-IOS-XR-um-flow-cfg:/flow/exporter-maps", + }) + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, + Steps: steps, + }) +} + +func testAccIosxrFlowExporterMapConfig_minimum() string { + config := `resource "iosxr_flow_exporter_map" "test" {` + "\n" + config += `}` + "\n" + return config +} + +func testAccIosxrFlowExporterMapConfig_all() string { + config := `resource "iosxr_flow_exporter_map" "test" {` + "\n" + config += ` exporter_maps = [{` + "\n" + config += ` exporter_map_name = "TEST"` + "\n" + config += ` destination_ipv4_address = "10.1.1.1"` + "\n" + config += ` destination_ipv6_address = "1::1"` + "\n" + config += ` destination_vrf = "28"` + "\n" + config += ` source = "10.1.1.4"` + "\n" + config += ` dscp = 62` + "\n" + config += ` packet_length = 512` + "\n" + config += ` transport_udp = 1033` + "\n" + config += ` dfbit_set = true` + "\n" + config += ` version_export_format = "true"` + "\n" + config += ` version_template_data_timeout = 1024` + "\n" + config += ` version_template_options_timeout = 3033` + "\n" + config += ` version_template_timeout = 2222` + "\n" + config += ` version_options_interface_table_timeout = 6048` + "\n" + config += ` version_options_sampler_table_timeout = 4096` + "\n" + config += ` version_options_class_table_timeout = 255` + "\n" + config += ` version_options_vrf_table_timeout = 122` + "\n" + config += ` }]` + "\n" + config += `}` + "\n" + return config +} diff --git a/templates/guides/changelog.md.tmpl b/templates/guides/changelog.md.tmpl index ee1469d4..34f4a7f8 100644 --- a/templates/guides/changelog.md.tmpl +++ b/templates/guides/changelog.md.tmpl @@ -33,6 +33,10 @@ description: |- - Add `iosxr_rd_set` resource and data source - Add `contact` and `location` attributes to `iosxr_snmp_server` resource and data source - Add `police_conform_action_transmit`, `police_conform_action_drop`, `police_exceed_action_transmit`, `police_exceed_action_drop`, `police_violate_action_transmit`, `police_violate_action_drop` attributes to `iosxr_policy_map_qos` resource and data source +- Add `iosxr_bfd` resource and data source +- Add `iosxr_flow_exporter_map` resource and data source + + ## 0.2.1