diff --git a/docs/data-sources/bfd_template.md b/docs/data-sources/bfd_template.md
new file mode 100644
index 00000000..70da72ae
--- /dev/null
+++ b/docs/data-sources/bfd_template.md
@@ -0,0 +1,41 @@
+---
+# generated by https://github.com/hashicorp/terraform-plugin-docs
+page_title: "fmc_bfd_template Data Source - terraform-provider-fmc"
+subcategory: "Objects"
+description: |-
+ This data source can read the BFD Template.
+---
+
+# fmc_bfd_template (Data Source)
+
+This data source can read the BFD Template.
+
+## Example Usage
+
+```terraform
+data "fmc_bfd_template" "example" {
+ id = "76d24097-41c4-4558-a4d0-a8c07ac08470"
+}
+```
+
+
+## Schema
+
+### Optional
+
+- `domain` (String) The name of the FMC domain
+- `id` (String) The id of the object
+- `name` (String) The name of the bfd template object.
+
+### Read-Only
+
+- `authentication_key_id` (Number) Authentication Key ID
+- `authentication_password` (String) Password for BFD Authentication (1-24 characters)
+- `authentication_type` (String) Authentication types
+- `echo` (String) Enables/disables BFD echo.
+- `hop_type` (String) The hop type.
+- `interval_time` (String) Interval unit of measurement of time.
+- `min_receive` (Number) BFD Minimum Receive unit value in ranges: 50-999 miliseconds, 50000-999000 microseconds
+- `min_transmit` (Number) BFD Minimum Transmit unit value.
+- `tx_rx_multiplier` (Number) BFD Multipler value.
+- `type` (String) Type of the object; this value is always 'BFDTemplate'.
diff --git a/docs/data-sources/device_bfd.md b/docs/data-sources/device_bfd.md
new file mode 100644
index 00000000..e0644773
--- /dev/null
+++ b/docs/data-sources/device_bfd.md
@@ -0,0 +1,43 @@
+---
+# generated by https://github.com/hashicorp/terraform-plugin-docs
+page_title: "fmc_device_bfd Data Source - terraform-provider-fmc"
+subcategory: "Device"
+description: |-
+ This data source can read the Device BFD.
+---
+
+# fmc_device_bfd (Data Source)
+
+This data source can read the Device BFD.
+
+## Example Usage
+
+```terraform
+data "fmc_device_bfd" "example" {
+ id = "76d24097-41c4-4558-a4d0-a8c07ac08470"
+ device_id = "76d24097-41c4-4558-a4d0-a8c07ac08470"
+}
+```
+
+
+## Schema
+
+### Required
+
+- `device_id` (String) UUID of the parent device (fmc_device.example.id).
+
+### Optional
+
+- `domain` (String) The name of the FMC domain
+- `id` (String) The id of the object
+- `interface_logical_name` (String) Logical Name of the interface of BFD assignment if SINGLE_HOP selected.
+
+### Read-Only
+
+- `bfd_template_id` (String) ID of the BFD Template
+- `destination_host_object_id` (String) The ID of the destination host object if MULTI_HOP selected.
+- `hop_type` (String) BFD Hop type.
+- `interface_id` (String) ID of the interface of BFD assignment if SINGLE_HOP selected.
+- `slow_timer` (Number) BFD Slow Timer value in range: 1000-30000, default: 1000
+- `source_host_object_id` (String) The ID of the source host object if MULTI_HOP selected.
+- `type` (String) Type of the object; this value is always 'BFDPolicy'
diff --git a/docs/data-sources/device_bgp.md b/docs/data-sources/device_bgp.md
new file mode 100644
index 00000000..3affb45e
--- /dev/null
+++ b/docs/data-sources/device_bgp.md
@@ -0,0 +1,193 @@
+---
+# generated by https://github.com/hashicorp/terraform-plugin-docs
+page_title: "fmc_device_bgp Data Source - terraform-provider-fmc"
+subcategory: "Devices"
+description: |-
+ This data source can read the Device BGP.
+---
+
+# fmc_device_bgp (Data Source)
+
+This data source can read the Device BGP.
+
+## Example Usage
+
+```terraform
+data "fmc_device_bgp" "example" {
+ id = "76d24097-41c4-4558-a4d0-a8c07ac08470"
+ device_id = "76d24097-41c4-4558-a4d0-a8c07ac08470"
+}
+```
+
+
+## Schema
+
+### Required
+
+- `device_id` (String) UUID of the parent device (fmc_device.example.id).
+
+### Optional
+
+- `as_number` (String) Autonomus System (AS) Number
+- `domain` (String) The name of the FMC domain
+- `id` (String) The id of the object
+
+### Read-Only
+
+- `ipv4_address_family_type` (String)
+- `ipv4_aggregate_addresses` (Attributes List) (see [below for nested schema](#nestedatt--ipv4_aggregate_addresses))
+- `ipv4_auto_aummary` (Boolean) Summarize subnet routes into network level routes
+- `ipv4_bgp_redistribute_internal` (Boolean) Redistribute IBGP into IGP. (Use filtering to limit the number of prefixes that are redistributed)
+- `ipv4_bgp_supress_inactive` (Boolean) Suppresing advertise inactive routes
+- `ipv4_default_information_orginate` (Boolean) Generate default routes
+- `ipv4_external_distance` (Number) Administrative route distance for external routes
+- `ipv4_filterings` (Attributes List) (see [below for nested schema](#nestedatt--ipv4_filterings))
+- `ipv4_forward_packets_over_multipath_ebgp` (Number) Number of paths to use for EBGP
+- `ipv4_forward_packets_over_multipath_ibgp` (Number) Number of paths to use for IBGP
+- `ipv4_internal_distance` (Number) Administrative route distance for internal routes
+- `ipv4_learned_route_map_id` (String) Learned Route Map ID
+- `ipv4_local_distance` (Number) Administrative route distance for local routes
+- `ipv4_neighbors` (Attributes List) (see [below for nested schema](#nestedatt--ipv4_neighbors))
+- `ipv4_networks` (Attributes List) (see [below for nested schema](#nestedatt--ipv4_networks))
+- `ipv4_redistributions` (Attributes List) (see [below for nested schema](#nestedatt--ipv4_redistributions))
+- `ipv4_route_injections` (Attributes List) (see [below for nested schema](#nestedatt--ipv4_route_injections))
+- `ipv4_synchronization` (Boolean) Synchronize between BGP and IGP systems
+- `name` (String) Name of the object; this is always 'bgp'
+- `type` (String) Type of the object; this is always 'bgp'
+
+
+### Nested Schema for `ipv4_aggregate_addresses`
+
+Read-Only:
+
+- `advertise_map_id` (String) Advertise Map ID
+- `attribute_map_id` (String) Attribute Map ID
+- `filter` (Boolean) Filter all routes from updates (summary only)
+- `generate_as` (Boolean) Generate AS set path information
+- `network_id` (String) Network ID
+- `suppress_map_id` (String) Suppress Map ID
+
+
+
+### Nested Schema for `ipv4_filterings`
+
+Read-Only:
+
+- `access_list_id` (String) Standard Access List ID
+- `network_direction` (String) Filtering directrion
+- `prorocol_process` (String) Process ID
+- `protocol` (String) Protocol
+
+
+
+### Nested Schema for `ipv4_neighbors`
+
+Read-Only:
+
+- `enable_address_family` (Boolean) Enable IPv4 address family
+- `neighbor_address` (String) IP address of the BGP neighbor
+- `neighbor_authentication_password` (String) Setting password enables authentication.
+- `neighbor_bfd` (String) BFD Fallover
+- `neighbor_customized_accept_both_as` (Boolean) Accept either real AS number or local AS number in routes experienced from neighbor
+- `neighbor_customized_local_as_number` (String) Customize the AS number for the routes received from neighbor
+- `neighbor_customized_no_prepend` (Boolean) Do not prepend local AS number to routes received from neighbor
+- `neighbor_customized_replace_as` (Boolean) Replace real AS number with local AS number in routes received from neighbor
+- `neighbor_description` (String) Description of the neighbor
+- `neighbor_disable_connection_verification` (Boolean) Disable Connection Verification
+- `neighbor_filter_access_lists` (Attributes List) (see [below for nested schema](#nestedatt--ipv4_neighbors--neighbor_filter_access_lists))
+- `neighbor_filter_as_path_lists` (Attributes List) (see [below for nested schema](#nestedatt--ipv4_neighbors--neighbor_filter_as_path_lists))
+- `neighbor_filter_max_prefix` (Number) Maximum number of prefixes allowed from the neighbor
+- `neighbor_filter_prefix_lists` (Attributes List) (see [below for nested schema](#nestedatt--ipv4_neighbors--neighbor_filter_prefix_lists))
+- `neighbor_filter_restart_interval` (Number) Time interval to restart the maximum prefix limit in Minutes
+- `neighbor_filter_route_map_lists` (Attributes List) (see [below for nested schema](#nestedatt--ipv4_neighbors--neighbor_filter_route_map_lists))
+- `neighbor_filter_threshold_value` (Number) Threshold value for the maximum number of prefixes allowed from the neighbor
+- `neighbor_filter_warning_only` (Boolean) Give only warning message when prefix limit exceeded or terminate peering when prefix limit is exceeded.
+- `neighbor_generate_default_route_map_id` (String) Generate default routes - Route Map
+- `neighbor_hold_time` (Number) Time interval to hold the neighbor in seconds
+- `neighbor_keepalive_interval` (Number) Time interval to send keepalive messages in seconds
+- `neighbor_max_hop_count` (Number) Maximum number of hops to reach the neighbor
+- `neighbor_min_hold_time` (Number) Minimum hold time in seconds
+- `neighbor_nexthop_self` (Boolean) Use itself as next hop for this neighbor
+- `neighbor_remote_as` (String) AS number of the BGP neighbor
+- `neighbor_routes_advertise_exist_nonexist_map_id` (String) Specified route maps are advertised when the prefix exists only in the Advertise Map.
+- `neighbor_routes_advertise_map_id` (String) Specified route maps are advertised when the prefix exists in the Advertise Map and Exist Map.
+- `neighbor_routes_advertise_map_use_exist` (Boolean) Use Exist Map or Non-Exist Map
+- `neighbor_routes_advertisement_interval` (Number) Time interval to advertise routes in seconds
+- `neighbor_routes_remove_private_as` (Boolean) Remove private AS numbers from outgoing routing updates
+- `neighbor_send_community_attribute` (Boolean) Send Community attribute to this neighbor
+- `neighbor_shutdown` (Boolean) Shutdown administratively
+- `neighbor_tcp_mtu_path_discovery` (Boolean) Use TCP path MTU discovery.
+- `neighbor_tcp_transport_mode` (Boolean) True set it to active, False to passive.
+- `neighbor_version` (String) Set BPG version: 0 - default, 4 - IPv4
+- `neighbor_weight` (Number) Weight of the neighbor
+- `update_source_interface_id` (String) Interface ID for the update source
+
+
+### Nested Schema for `ipv4_neighbors.neighbor_filter_access_lists`
+
+Read-Only:
+
+- `access_list_id` (String) Access List ID
+- `update_direction` (String) Filter direction
+
+
+
+### Nested Schema for `ipv4_neighbors.neighbor_filter_as_path_lists`
+
+Read-Only:
+
+- `as_path_id` (String) AS Path ID
+- `update_direction` (String) Filter direction
+
+
+
+### Nested Schema for `ipv4_neighbors.neighbor_filter_prefix_lists`
+
+Read-Only:
+
+- `prefix_list_id` (String) Route Map ID
+- `update_direction` (String) Filter direction
+
+
+
+### Nested Schema for `ipv4_neighbors.neighbor_filter_route_map_lists`
+
+Read-Only:
+
+- `route_map_id` (String) Route Map ID
+- `update_direction` (String) Filter direction
+
+
+
+
+### Nested Schema for `ipv4_networks`
+
+Read-Only:
+
+- `network_id` (String) Network object ID
+- `route_map_id` (String) Route Map ID
+
+
+
+### Nested Schema for `ipv4_redistributions`
+
+Read-Only:
+
+- `match_external1` (Boolean) Match OSPF External 1 metrics
+- `match_external2` (Boolean) Match OSPF External 2 metrics
+- `match_internal` (Boolean) Match OSPF Internal metrics
+- `match_nssa_external1` (Boolean) Match OSPF NSSA External 1 metrics
+- `match_nssa_external2` (Boolean) Match OSPF NSSA External 2 metrics
+- `metric` (Number) Metric value
+- `process_id` (String) process ID
+- `route_map_id` (String) Route Map ID
+- `source_protocol` (String) Protocol to redistribute
+
+
+
+### Nested Schema for `ipv4_route_injections`
+
+Read-Only:
+
+- `exist_route_map_id` (String) Exist Route Map ID
+- `inject_route_map_id` (String) Inject Route Map ID
diff --git a/docs/data-sources/device_bgp_general_settings.md b/docs/data-sources/device_bgp_general_settings.md
new file mode 100644
index 00000000..d990a8b4
--- /dev/null
+++ b/docs/data-sources/device_bgp_general_settings.md
@@ -0,0 +1,59 @@
+---
+# generated by https://github.com/hashicorp/terraform-plugin-docs
+page_title: "fmc_device_bgp_general_settings Data Source - terraform-provider-fmc"
+subcategory: "Devices"
+description: |-
+ This data source can read the Device BGP General Settings.
+---
+
+# fmc_device_bgp_general_settings (Data Source)
+
+This data source can read the Device BGP General Settings.
+
+## Example Usage
+
+```terraform
+data "fmc_device_bgp_general_settings" "example" {
+ id = "76d24097-41c4-4558-a4d0-a8c07ac08470"
+ device_id = "76d24097-41c4-4558-a4d0-a8c07ac08470"
+}
+```
+
+
+## Schema
+
+### Required
+
+- `device_id` (String) UUID of the parent device (fmc_device.example.id).
+
+### Optional
+
+- `as_number` (String) Autonomous System (AS) number in asplain or asdot format
+- `domain` (String) The name of the FMC domain
+- `id` (String) The id of the object
+
+### Read-Only
+
+- `aggregate_timer` (Number) Interval at which BGP routes will be aggregated or to disable timer-based router aggregation (in seconds).
+- `as_number_in_path_attribute` (Number) Range to discard routes that have as-path segments that exceed a specified value.
+- `compare_med_from_different_neighbors` (Boolean) Allow comparing MED from different neighbors
+- `compare_router_id_in_path` (Boolean) Compare Router ID for identical EBGP paths
+- `default_local_preference` (Number) Default local preference
+- `enforce_first_peer_as` (Boolean) Discard updates received from an external BGP (eBGP) peers that do not list their autonomous system (AS) number.
+- `graceful_restart` (Boolean) Enable graceful restart
+- `graceful_restart_restart_time` (Number) Graceful Restart Time in seconds
+- `graceful_restart_stale_path_time` (Number) Stalepath Time in seconds
+- `hold_time` (Number) Hold time in seconds
+- `keepalive_interval` (Number) Keepalive interval in seconds
+- `log_neighbor_changes` (Boolean) Enable logging of BGP neighbor status changes.
+- `min_hold_time` (Number) Minimum hold time (0 or 3-65535 seconds)
+- `missing_med_as_best` (Boolean) Treat missing MED as the best preferred path
+- `name` (String) Object name; Always set to 'AsaBGPGeneralTable'
+- `next_hop_address_tracking` (Boolean) Enable next hop address tracking
+- `next_hop_delay_interval` (Number) Next hop delay interval in seconds
+- `pick_best_med` (Boolean) Pick the best-MED path among paths advertised by neighbor AS
+- `reset_session_upon_failover` (Boolean) Reset session upon failover
+- `router_id` (String) String value for the routerID. Possible values can be 'AUTOMATIC' or valid ipv4 address
+- `scanning_interval` (Number) Scanning interval of BGP routers for next hop validation in Seconds.
+- `tcp_path_mtu_discovery` (Boolean) Use TCP path MTU discovery.
+- `use_dot_notation` (Boolean) Change format of BGP 4-byte autonomous system numbers from asplain (decimal values) to dot notation.
diff --git a/docs/data-sources/device_ha_pair_monitoring.md b/docs/data-sources/device_ha_pair_monitoring.md
new file mode 100644
index 00000000..618b03d2
--- /dev/null
+++ b/docs/data-sources/device_ha_pair_monitoring.md
@@ -0,0 +1,50 @@
+---
+# generated by https://github.com/hashicorp/terraform-plugin-docs
+page_title: "fmc_device_ha_pair_monitoring Data Source - terraform-provider-fmc"
+subcategory: "Device"
+description: |-
+ This data source can read the Device HA Pair Monitoring.
+---
+
+# fmc_device_ha_pair_monitoring (Data Source)
+
+This data source can read the Device HA Pair Monitoring.
+
+## Example Usage
+
+```terraform
+data "fmc_device_ha_pair_monitoring" "example" {
+ id = "76d24097-41c4-4558-a4d0-a8c07ac08470"
+ device_id = "76d24097-41c4-4558-a4d0-a8c07ac08470"
+}
+```
+
+
+## Schema
+
+### Required
+
+- `device_id` (String) UUID of the parent HA device (fmc_device.example.id).
+
+### Optional
+
+- `domain` (String) The name of the FMC domain
+- `id` (String) The id of the object
+- `logical_name` (String) Logical Name of the monitored interface.
+
+### Read-Only
+
+- `ipv4_active_address` (String) Active IPv4 address from the interface.
+- `ipv4_netmask` (String) IPv4 Network Mask assigned on the interface.
+- `ipv4_standby_address` (String) Standby IPv4 address. It has to be in the same subnet as primaty IP configured on this interface.
+- `ipv6_addresses` (Attributes List) (see [below for nested schema](#nestedatt--ipv6_addresses))
+- `monitor_interface` (Boolean) Monitor this interface for failures.
+- `type` (String) Type of the resource.
+
+
+### Nested Schema for `ipv6_addresses`
+
+Read-Only:
+
+- `active_address` (String) Active IPv6 address with prefix. Address has to be configured on the interface.
+- `standby_address` (String) Standby IPv6 address. Address has to be from the same subnet as active IPv6 address.
diff --git a/docs/data-sources/device_subinterface.md b/docs/data-sources/device_subinterface.md
index b8b0a6d0..a05760b5 100644
--- a/docs/data-sources/device_subinterface.md
+++ b/docs/data-sources/device_subinterface.md
@@ -30,7 +30,6 @@ data "fmc_device_subinterface" "example" {
- `domain` (String) The name of the FMC domain
- `id` (String) The id of the object
-- `interface_name` (String) Name of the parent interface (fmc_device_physical_interface.example.name).
- `name` (String) Name of the subinterface in format `interface_name.subinterface_id` (eg. GigabitEthernet0/1.7).
### Read-Only
@@ -42,6 +41,7 @@ data "fmc_device_subinterface" "example" {
- `enable_anti_spoofing` (Boolean) Enable Anti Spoofing
- `enable_sgt_propagate` (Boolean) Indicates whether to propagate SGT.
- `enabled` (Boolean) Indicates whether to enable the interface.
+- `interface_name` (String) Name of the parent interface (fmc_device_physical_interface.example.name).
- `ip_based_monitoring` (Boolean) Indicates whether to enable IP based Monitoring.
- `ip_based_monitoring_next_hop` (String) IP address to monitor.
- `ip_based_monitoring_type` (String) PPPoE Configuration - PPPoE route metric, [ AUTO, PEER_IPV4, PEER_IPV6, AUTO4, AUTO6 ]
diff --git a/docs/data-sources/security_zone.md b/docs/data-sources/security_zone.md
index fbbe47ef..e331faae 100644
--- a/docs/data-sources/security_zone.md
+++ b/docs/data-sources/security_zone.md
@@ -29,5 +29,5 @@ data "fmc_security_zone" "example" {
### Read-Only
-- `interface_mode` (String) The mode of the associated interfaces, with the exception of mode ROUTED that corresponds to mode NONE of associated interfaces.
+- `interface_type` (String) The mode of the associated interfaces, with the exception of mode ROUTED that corresponds to mode NONE of associated interfaces.
- `type` (String) Type of the object; this value is always 'SecurityZone'.
diff --git a/docs/data-sources/security_zones.md b/docs/data-sources/security_zones.md
index b7e832f5..3dbddd61 100644
--- a/docs/data-sources/security_zones.md
+++ b/docs/data-sources/security_zones.md
@@ -39,5 +39,5 @@ data "fmc_security_zones" "example" {
Read-Only:
- `id` (String) UUID of the managed Security Zone.
-- `interface_mode` (String) The mode of the associated interfaces, with the exception of mode ROUTED that corresponds to mode NONE of associated interfaces.
+- `interface_type` (String) The mode of the associated interfaces, with the exception of mode ROUTED that corresponds to mode NONE of associated interfaces.
- `type` (String) Type of the object; this value is always 'SecurityZone'.
diff --git a/docs/resources/bfd_template.md b/docs/resources/bfd_template.md
new file mode 100644
index 00000000..fed17a06
--- /dev/null
+++ b/docs/resources/bfd_template.md
@@ -0,0 +1,69 @@
+---
+# generated by https://github.com/hashicorp/terraform-plugin-docs
+page_title: "fmc_bfd_template Resource - terraform-provider-fmc"
+subcategory: "Objects"
+description: |-
+ This resource can manage a BFD Template.
+---
+
+# fmc_bfd_template (Resource)
+
+This resource can manage a BFD Template.
+
+## Example Usage
+
+```terraform
+resource "fmc_bfd_template" "example" {
+ name = "BFD_Template1"
+ hop_type = "SINGLE_HOP"
+ echo = "ENABLED"
+ interval_time = "MILLISECONDS"
+ min_transmit = 300
+ tx_rx_multiplier = 3
+ min_receive = 300
+ authentication_password = "Cisco123!"
+ authentication_key_id = 1
+ authentication_type = "MD5"
+}
+```
+
+
+## Schema
+
+### Required
+
+- `echo` (String) Enables/disables BFD echo.
+ - Choices: `ENABLED`, `DISABLED`
+- `hop_type` (String) The hop type.
+ - Choices: `SINGLE_HOP`, `MULTI_HOP`
+- `name` (String) The name of the bfd template object.
+
+### Optional
+
+- `authentication_key_id` (Number) Authentication Key ID
+ - Range: `0`-`255`
+- `authentication_password` (String) Password for BFD Authentication (1-24 characters)
+- `authentication_type` (String) Authentication types
+ - Choices: `MD5`, `METICULOUSMD5`, `METICULOUSSHA1`, `SHA1`, `NONE`
+- `domain` (String) The name of the FMC domain
+- `interval_time` (String) Interval unit of measurement of time.
+ - Choices: `MILLISECONDS`, `MICROSECONDS`, `NONE`
+- `min_receive` (Number) BFD Minimum Receive unit value in ranges: 50-999 miliseconds, 50000-999000 microseconds
+ - Range: `50`-`999000`
+- `min_transmit` (Number) BFD Minimum Transmit unit value.
+ - Range: `50`-`999000`
+- `tx_rx_multiplier` (Number) BFD Multipler value.
+ - Range: `3`-`50`
+
+### Read-Only
+
+- `id` (String) The id of the object
+- `type` (String) Type of the object; this value is always 'BFDTemplate'.
+
+## Import
+
+Import is supported using the following syntax:
+
+```shell
+terraform import fmc_bfd_template.example ""
+```
diff --git a/docs/resources/device_bfd.md b/docs/resources/device_bfd.md
new file mode 100644
index 00000000..cb38b8d8
--- /dev/null
+++ b/docs/resources/device_bfd.md
@@ -0,0 +1,59 @@
+---
+# generated by https://github.com/hashicorp/terraform-plugin-docs
+page_title: "fmc_device_bfd Resource - terraform-provider-fmc"
+subcategory: "Device"
+description: |-
+ This resource can manage a Device BFD.
+---
+
+# fmc_device_bfd (Resource)
+
+This resource can manage a Device BFD.
+
+## Example Usage
+
+```terraform
+resource "fmc_device_bfd" "example" {
+ device_id = "76d24097-41c4-4558-a4d0-a8c07ac08470"
+ hop_type = "SINGLE_HOP"
+ bfd_template_id = "76d24097-41c4-4558-a4d0-a8c07ac08470"
+ interface_logical_name = "outside"
+ destination_host_object_id = "76d24097-41c4-4558-a4d0-a8c07ac08470"
+ source_host_object_id = "76d24097-41c4-4558-a4d0-a8c07ac08470"
+ interface_id = "76d24097-41c4-4558-a4d0-a8c07ac08470"
+}
+```
+
+
+## Schema
+
+### Required
+
+- `bfd_template_id` (String) ID of the BFD Template
+- `device_id` (String) UUID of the parent device (fmc_device.example.id).
+- `hop_type` (String) BFD Hop type.
+ - Choices: `SINGLE_HOP`, `MULTI_HOP`
+
+### Optional
+
+- `destination_host_object_id` (String) The ID of the destination host object if MULTI_HOP selected.
+- `domain` (String) The name of the FMC domain
+- `interface_id` (String) ID of the interface of BFD assignment if SINGLE_HOP selected.
+- `interface_logical_name` (String) Logical Name of the interface of BFD assignment if SINGLE_HOP selected.
+- `slow_timer` (Number) BFD Slow Timer value in range: 1000-30000, default: 1000
+ - Range: `1000`-`30000`
+ - Default value: `1000`
+- `source_host_object_id` (String) The ID of the source host object if MULTI_HOP selected.
+
+### Read-Only
+
+- `id` (String) The id of the object
+- `type` (String) Type of the object; this value is always 'BFDPolicy'
+
+## Import
+
+Import is supported using the following syntax:
+
+```shell
+terraform import fmc_device_bfd.example ","
+```
diff --git a/docs/resources/device_bgp.md b/docs/resources/device_bgp.md
new file mode 100644
index 00000000..47bd92cc
--- /dev/null
+++ b/docs/resources/device_bgp.md
@@ -0,0 +1,260 @@
+---
+# generated by https://github.com/hashicorp/terraform-plugin-docs
+page_title: "fmc_device_bgp Resource - terraform-provider-fmc"
+subcategory: "Devices"
+description: |-
+ Under BGP General Settings, BGP has to be enabled and AS Number assigned first.
+---
+
+# fmc_device_bgp (Resource)
+
+Under BGP General Settings, BGP has to be enabled and AS Number assigned first.
+
+## Example Usage
+
+```terraform
+resource "fmc_device_bgp" "example" {
+ device_id = "76d24097-41c4-4558-a4d0-a8c07ac08470"
+ ipv4_default_information_orginate = false
+ ipv4_auto_aummary = false
+ ipv4_bgp_supress_inactive = false
+ ipv4_synchronization = false
+ ipv4_bgp_redistribute_internal = false
+ ipv4_external_distance = 20
+ ipv4_internal_distance = 200
+ ipv4_local_distance = 200
+ ipv4_forward_packets_over_multipath_ibgp = 1
+ ipv4_forward_packets_over_multipath_ebgp = 1
+ ipv4_neighbors = [
+ {
+ neighbor_address = "10.1.1.1"
+ neighbor_remote_as = "65534"
+ neighbor_bfd = "SINGLE_HOP"
+ enable_address_family = true
+ neighbor_description = "My BGP Peer"
+ }
+ ]
+}
+```
+
+
+## Schema
+
+### Required
+
+- `device_id` (String) UUID of the parent device (fmc_device.example.id).
+
+### Optional
+
+- `domain` (String) The name of the FMC domain
+- `ipv4_aggregate_addresses` (Attributes List) (see [below for nested schema](#nestedatt--ipv4_aggregate_addresses))
+- `ipv4_auto_aummary` (Boolean) Summarize subnet routes into network level routes
+- `ipv4_bgp_redistribute_internal` (Boolean) Redistribute IBGP into IGP. (Use filtering to limit the number of prefixes that are redistributed)
+- `ipv4_bgp_supress_inactive` (Boolean) Suppresing advertise inactive routes
+- `ipv4_default_information_orginate` (Boolean) Generate default routes
+- `ipv4_external_distance` (Number) Administrative route distance for external routes
+ - Range: `1`-`255`
+ - Default value: `20`
+- `ipv4_filterings` (Attributes List) (see [below for nested schema](#nestedatt--ipv4_filterings))
+- `ipv4_forward_packets_over_multipath_ebgp` (Number) Number of paths to use for EBGP
+ - Range: `1`-`8`
+ - Default value: `1`
+- `ipv4_forward_packets_over_multipath_ibgp` (Number) Number of paths to use for IBGP
+ - Range: `1`-`8`
+ - Default value: `1`
+- `ipv4_internal_distance` (Number) Administrative route distance for internal routes
+ - Range: `1`-`255`
+ - Default value: `200`
+- `ipv4_learned_route_map_id` (String) Learned Route Map ID
+- `ipv4_local_distance` (Number) Administrative route distance for local routes
+ - Range: `1`-`255`
+ - Default value: `200`
+- `ipv4_neighbors` (Attributes List) (see [below for nested schema](#nestedatt--ipv4_neighbors))
+- `ipv4_networks` (Attributes List) (see [below for nested schema](#nestedatt--ipv4_networks))
+- `ipv4_redistributions` (Attributes List) (see [below for nested schema](#nestedatt--ipv4_redistributions))
+- `ipv4_route_injections` (Attributes List) (see [below for nested schema](#nestedatt--ipv4_route_injections))
+- `ipv4_synchronization` (Boolean) Synchronize between BGP and IGP systems
+
+### Read-Only
+
+- `as_number` (String) Autonomus System (AS) Number
+- `id` (String) The id of the object
+- `ipv4_address_family_type` (String)
+- `name` (String) Name of the object; this is always 'bgp'
+- `type` (String) Type of the object; this is always 'bgp'
+
+
+### Nested Schema for `ipv4_aggregate_addresses`
+
+Optional:
+
+- `advertise_map_id` (String) Advertise Map ID
+- `attribute_map_id` (String) Attribute Map ID
+- `filter` (Boolean) Filter all routes from updates (summary only)
+- `generate_as` (Boolean) Generate AS set path information
+- `network_id` (String) Network ID
+- `suppress_map_id` (String) Suppress Map ID
+
+
+
+### Nested Schema for `ipv4_filterings`
+
+Optional:
+
+- `access_list_id` (String) Standard Access List ID
+- `network_direction` (String) Filtering directrion
+ - Choices: `incomingroutefilter`, `outgoingroutefilter`
+- `prorocol_process` (String) Process ID
+- `protocol` (String) Protocol
+
+
+
+### Nested Schema for `ipv4_neighbors`
+
+Optional:
+
+- `enable_address_family` (Boolean) Enable IPv4 address family
+ - Default value: `false`
+- `neighbor_address` (String) IP address of the BGP neighbor
+- `neighbor_authentication_password` (String) Setting password enables authentication.
+- `neighbor_bfd` (String) BFD Fallover
+ - Choices: `SINGLE_HOP`, `MULTI_HOP`, `AUTO_DETECT_HOP`, `NONE`
+ - Default value: `NONE`
+- `neighbor_customized_accept_both_as` (Boolean) Accept either real AS number or local AS number in routes experienced from neighbor
+- `neighbor_customized_local_as_number` (String) Customize the AS number for the routes received from neighbor
+- `neighbor_customized_no_prepend` (Boolean) Do not prepend local AS number to routes received from neighbor
+- `neighbor_customized_replace_as` (Boolean) Replace real AS number with local AS number in routes received from neighbor
+- `neighbor_description` (String) Description of the neighbor
+- `neighbor_disable_connection_verification` (Boolean) Disable Connection Verification
+ - Default value: `false`
+- `neighbor_filter_access_lists` (Attributes List) (see [below for nested schema](#nestedatt--ipv4_neighbors--neighbor_filter_access_lists))
+- `neighbor_filter_as_path_lists` (Attributes List) (see [below for nested schema](#nestedatt--ipv4_neighbors--neighbor_filter_as_path_lists))
+- `neighbor_filter_max_prefix` (Number) Maximum number of prefixes allowed from the neighbor
+ - Range: `1`-`2147483647`
+- `neighbor_filter_prefix_lists` (Attributes List) (see [below for nested schema](#nestedatt--ipv4_neighbors--neighbor_filter_prefix_lists))
+- `neighbor_filter_restart_interval` (Number) Time interval to restart the maximum prefix limit in Minutes
+ - Range: `1`-`65535`
+- `neighbor_filter_route_map_lists` (Attributes List) (see [below for nested schema](#nestedatt--ipv4_neighbors--neighbor_filter_route_map_lists))
+- `neighbor_filter_threshold_value` (Number) Threshold value for the maximum number of prefixes allowed from the neighbor
+ - Range: `1`-`100`
+- `neighbor_filter_warning_only` (Boolean) Give only warning message when prefix limit exceeded or terminate peering when prefix limit is exceeded.
+- `neighbor_generate_default_route_map_id` (String) Generate default routes - Route Map
+- `neighbor_hold_time` (Number) Time interval to hold the neighbor in seconds
+ - Range: `3`-`65535`
+- `neighbor_keepalive_interval` (Number) Time interval to send keepalive messages in seconds
+ - Range: `0`-`65535`
+- `neighbor_max_hop_count` (Number) Maximum number of hops to reach the neighbor
+ - Range: `1`-`255`
+ - Default value: `1`
+- `neighbor_min_hold_time` (Number) Minimum hold time in seconds
+ - Range: `3`-`65535`
+- `neighbor_nexthop_self` (Boolean) Use itself as next hop for this neighbor
+ - Default value: `false`
+- `neighbor_remote_as` (String) AS number of the BGP neighbor
+- `neighbor_routes_advertise_exist_nonexist_map_id` (String) Specified route maps are advertised when the prefix exists only in the Advertise Map.
+- `neighbor_routes_advertise_map_id` (String) Specified route maps are advertised when the prefix exists in the Advertise Map and Exist Map.
+- `neighbor_routes_advertise_map_use_exist` (Boolean) Use Exist Map or Non-Exist Map
+- `neighbor_routes_advertisement_interval` (Number) Time interval to advertise routes in seconds
+ - Range: `0`-`600`
+ - Default value: `0`
+- `neighbor_routes_remove_private_as` (Boolean) Remove private AS numbers from outgoing routing updates
+ - Default value: `false`
+- `neighbor_send_community_attribute` (Boolean) Send Community attribute to this neighbor
+ - Default value: `false`
+- `neighbor_shutdown` (Boolean) Shutdown administratively
+ - Default value: `false`
+- `neighbor_tcp_mtu_path_discovery` (Boolean) Use TCP path MTU discovery.
+ - Default value: `false`
+- `neighbor_tcp_transport_mode` (Boolean) True set it to active, False to passive.
+ - Default value: `false`
+- `neighbor_version` (String) Set BPG version: 0 - default, 4 - IPv4
+ - Choices: `0`, `4`
+ - Default value: `0`
+- `neighbor_weight` (Number) Weight of the neighbor
+ - Range: `0`-`65535`
+ - Default value: `0`
+- `update_source_interface_id` (String) Interface ID for the update source
+
+
+### Nested Schema for `ipv4_neighbors.neighbor_filter_access_lists`
+
+Optional:
+
+- `access_list_id` (String) Access List ID
+- `update_direction` (String) Filter direction
+ - Choices: `IN`, `OUT`
+
+
+
+### Nested Schema for `ipv4_neighbors.neighbor_filter_as_path_lists`
+
+Optional:
+
+- `as_path_id` (String) AS Path ID
+- `update_direction` (String) Filter direction
+ - Choices: `IN`, `OUT`
+
+
+
+### Nested Schema for `ipv4_neighbors.neighbor_filter_prefix_lists`
+
+Optional:
+
+- `prefix_list_id` (String) Route Map ID
+- `update_direction` (String) Filter direction
+ - Choices: `IN`, `OUT`
+
+
+
+### Nested Schema for `ipv4_neighbors.neighbor_filter_route_map_lists`
+
+Optional:
+
+- `route_map_id` (String) Route Map ID
+- `update_direction` (String) Filter direction
+ - Choices: `IN`, `OUT`
+
+
+
+
+### Nested Schema for `ipv4_networks`
+
+Optional:
+
+- `network_id` (String) Network object ID
+- `route_map_id` (String) Route Map ID
+
+
+
+### Nested Schema for `ipv4_redistributions`
+
+Optional:
+
+- `match_external1` (Boolean) Match OSPF External 1 metrics
+- `match_external2` (Boolean) Match OSPF External 2 metrics
+- `match_internal` (Boolean) Match OSPF Internal metrics
+- `match_nssa_external1` (Boolean) Match OSPF NSSA External 1 metrics
+- `match_nssa_external2` (Boolean) Match OSPF NSSA External 2 metrics
+- `metric` (Number) Metric value
+ - Range: `0`-`4294967295`
+- `process_id` (String) process ID
+- `route_map_id` (String) Route Map ID
+- `source_protocol` (String) Protocol to redistribute
+ - Choices: `RedistributeConnected`, `RedistributeStatic`, `RedistributeOSPF`, `RedistributeEIGRP`
+
+
+
+### Nested Schema for `ipv4_route_injections`
+
+Optional:
+
+- `exist_route_map_id` (String) Exist Route Map ID
+- `inject_route_map_id` (String) Inject Route Map ID
+
+## Import
+
+Import is supported using the following syntax:
+
+```shell
+terraform import fmc_device_bgp.example ","
+```
diff --git a/docs/resources/device_bgp_general_settings.md b/docs/resources/device_bgp_general_settings.md
new file mode 100644
index 00000000..66ecb3b4
--- /dev/null
+++ b/docs/resources/device_bgp_general_settings.md
@@ -0,0 +1,84 @@
+---
+# generated by https://github.com/hashicorp/terraform-plugin-docs
+page_title: "fmc_device_bgp_general_settings Resource - terraform-provider-fmc"
+subcategory: "Devices"
+description: |-
+ This resource can manage a Device BGP General Settings.
+---
+
+# fmc_device_bgp_general_settings (Resource)
+
+This resource can manage a Device BGP General Settings.
+
+## Example Usage
+
+```terraform
+resource "fmc_device_bgp_general_settings" "example" {
+ device_id = "76d24097-41c4-4558-a4d0-a8c07ac08470"
+ as_number = "65535"
+ router_id = "AUTOMATIC"
+ scanning_interval = 60
+ as_number_in_path_attribute = 50
+ tcp_path_mtu_discovery = true
+ reset_session_upon_failover = true
+ enforce_first_peer_as = true
+ use_dot_notation = false
+}
+```
+
+
+## Schema
+
+### Required
+
+- `as_number` (String) Autonomous System (AS) number in asplain or asdot format
+- `device_id` (String) UUID of the parent device (fmc_device.example.id).
+
+### Optional
+
+- `aggregate_timer` (Number) Interval at which BGP routes will be aggregated or to disable timer-based router aggregation (in seconds).
+ - Range: `6`-`60`
+- `as_number_in_path_attribute` (Number) Range to discard routes that have as-path segments that exceed a specified value.
+ - Range: `1`-`254`
+- `compare_med_from_different_neighbors` (Boolean) Allow comparing MED from different neighbors
+- `compare_router_id_in_path` (Boolean) Compare Router ID for identical EBGP paths
+- `default_local_preference` (Number) Default local preference
+ - Range: `0`-`4294967295`
+- `domain` (String) The name of the FMC domain
+- `enforce_first_peer_as` (Boolean) Discard updates received from an external BGP (eBGP) peers that do not list their autonomous system (AS) number.
+- `graceful_restart` (Boolean) Enable graceful restart
+- `graceful_restart_restart_time` (Number) Graceful Restart Time in seconds
+ - Range: `1`-`3600`
+- `graceful_restart_stale_path_time` (Number) Stalepath Time in seconds
+ - Range: `1`-`3600`
+- `hold_time` (Number) Hold time in seconds
+ - Range: `0`-`65535`
+- `keepalive_interval` (Number) Keepalive interval in seconds
+ - Range: `0`-`65535`
+- `log_neighbor_changes` (Boolean) Enable logging of BGP neighbor status changes.
+- `min_hold_time` (Number) Minimum hold time (0 or 3-65535 seconds)
+ - Range: `0`-`65535`
+- `missing_med_as_best` (Boolean) Treat missing MED as the best preferred path
+- `next_hop_address_tracking` (Boolean) Enable next hop address tracking
+- `next_hop_delay_interval` (Number) Next hop delay interval in seconds
+ - Range: `0`-`100`
+- `pick_best_med` (Boolean) Pick the best-MED path among paths advertised by neighbor AS
+- `reset_session_upon_failover` (Boolean) Reset session upon failover
+- `router_id` (String) String value for the routerID. Possible values can be 'AUTOMATIC' or valid ipv4 address
+- `scanning_interval` (Number) Scanning interval of BGP routers for next hop validation in Seconds.
+ - Range: `5`-`60`
+- `tcp_path_mtu_discovery` (Boolean) Use TCP path MTU discovery.
+- `use_dot_notation` (Boolean) Change format of BGP 4-byte autonomous system numbers from asplain (decimal values) to dot notation.
+
+### Read-Only
+
+- `id` (String) The id of the object
+- `name` (String) Object name; Always set to 'AsaBGPGeneralTable'
+
+## Import
+
+Import is supported using the following syntax:
+
+```shell
+terraform import fmc_device_bgp_general_settings.example ","
+```
diff --git a/docs/resources/device_ha_pair_monitoring.md b/docs/resources/device_ha_pair_monitoring.md
new file mode 100644
index 00000000..f6a2782a
--- /dev/null
+++ b/docs/resources/device_ha_pair_monitoring.md
@@ -0,0 +1,66 @@
+---
+# generated by https://github.com/hashicorp/terraform-plugin-docs
+page_title: "fmc_device_ha_pair_monitoring Resource - terraform-provider-fmc"
+subcategory: "Device"
+description: |-
+ This resource can manage a Device HA Pair Monitoring.
+---
+
+# fmc_device_ha_pair_monitoring (Resource)
+
+This resource can manage a Device HA Pair Monitoring.
+
+## Example Usage
+
+```terraform
+resource "fmc_device_ha_pair_monitoring" "example" {
+ device_id = "76d24097-41c4-4558-a4d0-a8c07ac08470"
+ logical_name = "outside"
+ monitor_interface = true
+ ipv4_standby_address = "10.1.1.2"
+ ipv6_addresses = [
+ {
+ active_address = "2006::1/30"
+ standby_address = "2006::2"
+ }
+ ]
+}
+```
+
+
+## Schema
+
+### Required
+
+- `device_id` (String) UUID of the parent HA device (fmc_device.example.id).
+- `logical_name` (String) Logical Name of the monitored interface.
+- `monitor_interface` (Boolean) Monitor this interface for failures.
+
+### Optional
+
+- `domain` (String) The name of the FMC domain
+- `ipv4_standby_address` (String) Standby IPv4 address. It has to be in the same subnet as primaty IP configured on this interface.
+- `ipv6_addresses` (Attributes List) (see [below for nested schema](#nestedatt--ipv6_addresses))
+
+### Read-Only
+
+- `id` (String) The id of the object
+- `ipv4_active_address` (String) Active IPv4 address from the interface.
+- `ipv4_netmask` (String) IPv4 Network Mask assigned on the interface.
+- `type` (String) Type of the resource.
+
+
+### Nested Schema for `ipv6_addresses`
+
+Optional:
+
+- `active_address` (String) Active IPv6 address with prefix. Address has to be configured on the interface.
+- `standby_address` (String) Standby IPv6 address. Address has to be from the same subnet as active IPv6 address.
+
+## Import
+
+Import is supported using the following syntax:
+
+```shell
+terraform import fmc_device_ha_pair_monitoring.example ","
+```
diff --git a/docs/resources/network.md b/docs/resources/network.md
index 49d5dd53..a3af78c4 100644
--- a/docs/resources/network.md
+++ b/docs/resources/network.md
@@ -34,12 +34,11 @@ resource "fmc_network" "example" {
- `description` (String) Description
- `domain` (String) The name of the FMC domain
- `overridable` (Boolean) Whether the object values can be overridden.
-- `type` (String) Type of the object; this value is always 'Network'.
- - Default value: `Network`
### Read-Only
- `id` (String) The id of the object
+- `type` (String) Type of the object; this value is always 'Network'.
## Import
diff --git a/docs/resources/networks.md b/docs/resources/networks.md
index e75075c4..b0a99d81 100644
--- a/docs/resources/networks.md
+++ b/docs/resources/networks.md
@@ -49,12 +49,11 @@ Optional:
- `description` (String) Optional user-created description.
- `overridable` (Boolean) Indicates whether object values can be overridden.
-- `type` (String) Type of the object; this value is always 'Network'.
- - Default value: `Network`
Read-Only:
- `id` (String) UUID of the managed Network.
+- `type` (String) Type of the object; this value is always 'Network'.
## Import
diff --git a/docs/resources/port_group.md b/docs/resources/port_group.md
index 7f248864..c33164b1 100644
--- a/docs/resources/port_group.md
+++ b/docs/resources/port_group.md
@@ -38,12 +38,11 @@ resource "fmc_port_group" "example" {
- `description` (String) Optional user-created description.
- `domain` (String) The name of the FMC domain
- `overridable` (Boolean) Indicates whether object values can be overridden.
-- `type` (String) Type of the object; this value is always 'PortObjectGroup'.
- - Default value: `PortObjectGroup`
### Read-Only
- `id` (String) The id of the object
+- `type` (String) Type of the object; this value is always 'PortObjectGroup'.
### Nested Schema for `objects`
diff --git a/docs/resources/port_groups.md b/docs/resources/port_groups.md
index bc251695..1b53465d 100644
--- a/docs/resources/port_groups.md
+++ b/docs/resources/port_groups.md
@@ -54,12 +54,11 @@ Optional:
- `description` (String) Optional user-created description.
- `overridable` (Boolean) Indicates whether object values can be overridden.
-- `type` (String) Type of the object; this value is always 'PortObjectGroup'.
- - Default value: `PortObjectGroup`
Read-Only:
- `id` (String) UUID of the managed Port Groups.
+- `type` (String) Type of the object; this value is always 'PortObjectGroup'.
### Nested Schema for `items.objects`
diff --git a/docs/resources/security_zone.md b/docs/resources/security_zone.md
index 44ee1f97..23124bd0 100644
--- a/docs/resources/security_zone.md
+++ b/docs/resources/security_zone.md
@@ -15,7 +15,7 @@ This resource can manage a Security Zone.
```terraform
resource "fmc_security_zone" "example" {
name = "security_zone_1"
- interface_mode = "ROUTED"
+ interface_type = "ROUTED"
}
```
@@ -24,19 +24,18 @@ resource "fmc_security_zone" "example" {
### Required
-- `interface_mode` (String) The mode of the associated interfaces, with the exception of mode ROUTED that corresponds to mode NONE of associated interfaces.
+- `interface_type` (String) The mode of the associated interfaces, with the exception of mode ROUTED that corresponds to mode NONE of associated interfaces.
- Choices: `PASSIVE`, `INLINE`, `SWITCHED`, `ROUTED`, `ASA`
- `name` (String) User-provided resource name.
### Optional
- `domain` (String) The name of the FMC domain
-- `type` (String) Type of the object; this value is always 'SecurityZone'.
- - Default value: `SecurityZone`
### Read-Only
- `id` (String) The id of the object
+- `type` (String) Type of the object; this value is always 'SecurityZone'.
## Import
diff --git a/docs/resources/security_zones.md b/docs/resources/security_zones.md
index f3056696..627e086b 100644
--- a/docs/resources/security_zones.md
+++ b/docs/resources/security_zones.md
@@ -16,7 +16,7 @@ This plural resource manages a bulk of Security Zones. The FMC API supports quic
resource "fmc_security_zones" "example" {
items = {
security_zone_1 = {
- interface_mode = "ROUTED"
+ interface_type = "ROUTED"
}
}
}
@@ -42,17 +42,13 @@ resource "fmc_security_zones" "example" {
Required:
-- `interface_mode` (String) The mode of the associated interfaces, with the exception of mode ROUTED that corresponds to mode NONE of associated interfaces.
+- `interface_type` (String) The mode of the associated interfaces, with the exception of mode ROUTED that corresponds to mode NONE of associated interfaces.
- Choices: `PASSIVE`, `INLINE`, `SWITCHED`, `ROUTED`, `ASA`
-Optional:
-
-- `type` (String) Type of the object; this value is always 'SecurityZone'.
- - Default value: `SecurityZone`
-
Read-Only:
- `id` (String) UUID of the managed Security Zone.
+- `type` (String) Type of the object; this value is always 'SecurityZone'.
## Import
diff --git a/examples/data-sources/fmc_bfd_template/data-source.tf b/examples/data-sources/fmc_bfd_template/data-source.tf
new file mode 100644
index 00000000..e977873f
--- /dev/null
+++ b/examples/data-sources/fmc_bfd_template/data-source.tf
@@ -0,0 +1,3 @@
+data "fmc_bfd_template" "example" {
+ id = "76d24097-41c4-4558-a4d0-a8c07ac08470"
+}
diff --git a/examples/data-sources/fmc_bgd_template/data-source.tf b/examples/data-sources/fmc_bgd_template/data-source.tf
new file mode 100644
index 00000000..87278826
--- /dev/null
+++ b/examples/data-sources/fmc_bgd_template/data-source.tf
@@ -0,0 +1,3 @@
+data "fmc_bgd_template" "example" {
+ id = "76d24097-41c4-4558-a4d0-a8c07ac08470"
+}
diff --git a/examples/data-sources/fmc_device_bfd/data-source.tf b/examples/data-sources/fmc_device_bfd/data-source.tf
new file mode 100644
index 00000000..dbc96a7c
--- /dev/null
+++ b/examples/data-sources/fmc_device_bfd/data-source.tf
@@ -0,0 +1,4 @@
+data "fmc_device_bfd" "example" {
+ id = "76d24097-41c4-4558-a4d0-a8c07ac08470"
+ device_id = "76d24097-41c4-4558-a4d0-a8c07ac08470"
+}
diff --git a/examples/data-sources/fmc_device_bgp/data-source.tf b/examples/data-sources/fmc_device_bgp/data-source.tf
new file mode 100644
index 00000000..b7c2fcdf
--- /dev/null
+++ b/examples/data-sources/fmc_device_bgp/data-source.tf
@@ -0,0 +1,4 @@
+data "fmc_device_bgp" "example" {
+ id = "76d24097-41c4-4558-a4d0-a8c07ac08470"
+ device_id = "76d24097-41c4-4558-a4d0-a8c07ac08470"
+}
diff --git a/examples/data-sources/fmc_device_bgp_general_settings/data-source.tf b/examples/data-sources/fmc_device_bgp_general_settings/data-source.tf
new file mode 100644
index 00000000..e991debc
--- /dev/null
+++ b/examples/data-sources/fmc_device_bgp_general_settings/data-source.tf
@@ -0,0 +1,4 @@
+data "fmc_device_bgp_general_settings" "example" {
+ id = "76d24097-41c4-4558-a4d0-a8c07ac08470"
+ device_id = "76d24097-41c4-4558-a4d0-a8c07ac08470"
+}
diff --git a/examples/data-sources/fmc_device_bgp_generel_settings/data-source.tf b/examples/data-sources/fmc_device_bgp_generel_settings/data-source.tf
new file mode 100644
index 00000000..cd1c0cfb
--- /dev/null
+++ b/examples/data-sources/fmc_device_bgp_generel_settings/data-source.tf
@@ -0,0 +1,4 @@
+data "fmc_device_bgp_generel_settings" "example" {
+ id = "76d24097-41c4-4558-a4d0-a8c07ac08470"
+ device_id = "76d24097-41c4-4558-a4d0-a8c07ac08470"
+}
diff --git a/examples/data-sources/fmc_device_ha_pair/data-source.tf b/examples/data-sources/fmc_device_ha_pair/data-source.tf
new file mode 100644
index 00000000..aac62b48
--- /dev/null
+++ b/examples/data-sources/fmc_device_ha_pair/data-source.tf
@@ -0,0 +1,3 @@
+data "fmc_device_ha_pair" "example" {
+ id = "76d24097-41c4-4558-a4d0-a8c07ac08470"
+}
diff --git a/examples/data-sources/fmc_device_ha_pair_monitoring/data-source.tf b/examples/data-sources/fmc_device_ha_pair_monitoring/data-source.tf
new file mode 100644
index 00000000..cb03d3e0
--- /dev/null
+++ b/examples/data-sources/fmc_device_ha_pair_monitoring/data-source.tf
@@ -0,0 +1,4 @@
+data "fmc_device_ha_pair_monitoring" "example" {
+ id = "76d24097-41c4-4558-a4d0-a8c07ac08470"
+ device_id = "76d24097-41c4-4558-a4d0-a8c07ac08470"
+}
diff --git a/examples/resources/fmc_bfd_template/import.sh b/examples/resources/fmc_bfd_template/import.sh
new file mode 100644
index 00000000..ed00cc19
--- /dev/null
+++ b/examples/resources/fmc_bfd_template/import.sh
@@ -0,0 +1 @@
+terraform import fmc_bfd_template.example ""
diff --git a/examples/resources/fmc_bfd_template/resource.tf b/examples/resources/fmc_bfd_template/resource.tf
new file mode 100644
index 00000000..42141988
--- /dev/null
+++ b/examples/resources/fmc_bfd_template/resource.tf
@@ -0,0 +1,12 @@
+resource "fmc_bfd_template" "example" {
+ name = "BFD_Template1"
+ hop_type = "SINGLE_HOP"
+ echo = "ENABLED"
+ interval_time = "MILLISECONDS"
+ min_transmit = 300
+ tx_rx_multiplier = 3
+ min_receive = 300
+ authentication_password = "Cisco123!"
+ authentication_key_id = 1
+ authentication_type = "MD5"
+}
diff --git a/examples/resources/fmc_bgd_template/import.sh b/examples/resources/fmc_bgd_template/import.sh
new file mode 100644
index 00000000..8f7c8880
--- /dev/null
+++ b/examples/resources/fmc_bgd_template/import.sh
@@ -0,0 +1 @@
+terraform import fmc_bgd_template.example ""
diff --git a/examples/resources/fmc_bgd_template/resource.tf b/examples/resources/fmc_bgd_template/resource.tf
new file mode 100644
index 00000000..ad675aac
--- /dev/null
+++ b/examples/resources/fmc_bgd_template/resource.tf
@@ -0,0 +1,9 @@
+resource "fmc_bgd_template" "example" {
+ name = "BFD_Template1"
+ hop_type = "SINGLE_HOP"
+ echo = "ENABLED"
+ interval_time = "MILLISECONDS"
+ min_transmit = 100000
+ tx_rx_multiplier = 3
+ min_receive = 100000
+}
diff --git a/examples/resources/fmc_device_bfd/import.sh b/examples/resources/fmc_device_bfd/import.sh
new file mode 100644
index 00000000..718eaaf1
--- /dev/null
+++ b/examples/resources/fmc_device_bfd/import.sh
@@ -0,0 +1 @@
+terraform import fmc_device_bfd.example ","
diff --git a/examples/resources/fmc_device_bfd/resource.tf b/examples/resources/fmc_device_bfd/resource.tf
new file mode 100644
index 00000000..fb7b2497
--- /dev/null
+++ b/examples/resources/fmc_device_bfd/resource.tf
@@ -0,0 +1,9 @@
+resource "fmc_device_bfd" "example" {
+ device_id = "76d24097-41c4-4558-a4d0-a8c07ac08470"
+ hop_type = "SINGLE_HOP"
+ bfd_template_id = "76d24097-41c4-4558-a4d0-a8c07ac08470"
+ interface_logical_name = "outside"
+ destination_host_object_id = "76d24097-41c4-4558-a4d0-a8c07ac08470"
+ source_host_object_id = "76d24097-41c4-4558-a4d0-a8c07ac08470"
+ interface_id = "76d24097-41c4-4558-a4d0-a8c07ac08470"
+}
diff --git a/examples/resources/fmc_device_bgp/import.sh b/examples/resources/fmc_device_bgp/import.sh
new file mode 100644
index 00000000..34790e31
--- /dev/null
+++ b/examples/resources/fmc_device_bgp/import.sh
@@ -0,0 +1 @@
+terraform import fmc_device_bgp.example ","
diff --git a/examples/resources/fmc_device_bgp/resource.tf b/examples/resources/fmc_device_bgp/resource.tf
new file mode 100644
index 00000000..68231751
--- /dev/null
+++ b/examples/resources/fmc_device_bgp/resource.tf
@@ -0,0 +1,22 @@
+resource "fmc_device_bgp" "example" {
+ device_id = "76d24097-41c4-4558-a4d0-a8c07ac08470"
+ ipv4_default_information_orginate = false
+ ipv4_auto_aummary = false
+ ipv4_bgp_supress_inactive = false
+ ipv4_synchronization = false
+ ipv4_bgp_redistribute_internal = false
+ ipv4_external_distance = 20
+ ipv4_internal_distance = 200
+ ipv4_local_distance = 200
+ ipv4_forward_packets_over_multipath_ibgp = 1
+ ipv4_forward_packets_over_multipath_ebgp = 1
+ ipv4_neighbors = [
+ {
+ neighbor_address = "10.1.1.1"
+ neighbor_remote_as = "65534"
+ neighbor_bfd = "SINGLE_HOP"
+ enable_address_family = true
+ neighbor_description = "My BGP Peer"
+ }
+ ]
+}
diff --git a/examples/resources/fmc_device_bgp_general_settings/import.sh b/examples/resources/fmc_device_bgp_general_settings/import.sh
new file mode 100644
index 00000000..9f728317
--- /dev/null
+++ b/examples/resources/fmc_device_bgp_general_settings/import.sh
@@ -0,0 +1 @@
+terraform import fmc_device_bgp_general_settings.example ","
diff --git a/examples/resources/fmc_device_bgp_general_settings/resource.tf b/examples/resources/fmc_device_bgp_general_settings/resource.tf
new file mode 100644
index 00000000..8605b5f4
--- /dev/null
+++ b/examples/resources/fmc_device_bgp_general_settings/resource.tf
@@ -0,0 +1,11 @@
+resource "fmc_device_bgp_general_settings" "example" {
+ device_id = "76d24097-41c4-4558-a4d0-a8c07ac08470"
+ as_number = "65535"
+ router_id = "AUTOMATIC"
+ scanning_interval = 60
+ as_number_in_path_attribute = 50
+ tcp_path_mtu_discovery = true
+ reset_session_upon_failover = true
+ enforce_first_peer_as = true
+ use_dot_notation = false
+}
diff --git a/examples/resources/fmc_device_bgp_generel_settings/import.sh b/examples/resources/fmc_device_bgp_generel_settings/import.sh
new file mode 100644
index 00000000..c5a3225f
--- /dev/null
+++ b/examples/resources/fmc_device_bgp_generel_settings/import.sh
@@ -0,0 +1 @@
+terraform import fmc_device_bgp_generel_settings.example ","
diff --git a/examples/resources/fmc_device_bgp_generel_settings/resource.tf b/examples/resources/fmc_device_bgp_generel_settings/resource.tf
new file mode 100644
index 00000000..ce00b414
--- /dev/null
+++ b/examples/resources/fmc_device_bgp_generel_settings/resource.tf
@@ -0,0 +1,5 @@
+resource "fmc_device_bgp_generel_settings" "example" {
+ device_id = "76d24097-41c4-4558-a4d0-a8c07ac08470"
+ as_number = "65535"
+ router_id = "AUTOMATIC"
+}
diff --git a/examples/resources/fmc_device_ha_pair/import.sh b/examples/resources/fmc_device_ha_pair/import.sh
new file mode 100644
index 00000000..224ab835
--- /dev/null
+++ b/examples/resources/fmc_device_ha_pair/import.sh
@@ -0,0 +1 @@
+terraform import fmc_device_ha_pair.example ""
diff --git a/examples/resources/fmc_device_ha_pair/resource.tf b/examples/resources/fmc_device_ha_pair/resource.tf
new file mode 100644
index 00000000..62255af9
--- /dev/null
+++ b/examples/resources/fmc_device_ha_pair/resource.tf
@@ -0,0 +1,27 @@
+resource "fmc_device_ha_pair" "example" {
+ name = "FTD_HA"
+ primary_device_id = "76d24097-41c4-4558-a4d0-a8c07ac08470"
+ secondary_device_id = "96d24097-41c4-4332-a4d0-a8c07ac08482"
+ is_encryption_enabled = false
+ use_same_link_for_failovers = false
+ shared_key = "cisco123"
+ enc_key_generation_scheme = "CUSTOM"
+ lan_failover_standby_ip = "1.1.1.2"
+ lan_failover_active_ip = "1.1.1.1"
+ lan_failover_name = "LAN-INTERFACE"
+ lan_failover_subnet_mask = "255.255.255.0"
+ lan_failover_ipv6_addr = false
+ lan_failover_interface_name = "GigabitEthernet0/0"
+ lan_failover_interface_id = "757kdgh5-41c4-4558-a4d0-a8c07ac08470"
+ lan_failover_interface_type = "PhysicalInterface"
+ stateful_failover_standby_ip = "10.10.10.2"
+ stateful_failover_active_ip = "10.10.10.1"
+ stateful_failover_name = "Stateful-INTERFACE"
+ stateful_failover_subnet_mask = "255.255.255.0"
+ stateful_failover_ipv6_addr = false
+ stateful_failover_interface_name = "GigabitEthernet0/0"
+ stateful_failover_interface_id = "76d24097-hj7r-7786-a4d0-a8c07ac08470"
+ stateful_failover_interface_type = "PhysicalInterface"
+ action = "SWITCH"
+ force_break = false
+}
diff --git a/examples/resources/fmc_device_ha_pair_monitoring/import.sh b/examples/resources/fmc_device_ha_pair_monitoring/import.sh
new file mode 100644
index 00000000..72f4d65f
--- /dev/null
+++ b/examples/resources/fmc_device_ha_pair_monitoring/import.sh
@@ -0,0 +1 @@
+terraform import fmc_device_ha_pair_monitoring.example ","
diff --git a/examples/resources/fmc_device_ha_pair_monitoring/resource.tf b/examples/resources/fmc_device_ha_pair_monitoring/resource.tf
new file mode 100644
index 00000000..f4b73367
--- /dev/null
+++ b/examples/resources/fmc_device_ha_pair_monitoring/resource.tf
@@ -0,0 +1,12 @@
+resource "fmc_device_ha_pair_monitoring" "example" {
+ device_id = "76d24097-41c4-4558-a4d0-a8c07ac08470"
+ logical_name = "outside"
+ monitor_interface = true
+ ipv4_standby_address = "10.1.1.2"
+ ipv6_addresses = [
+ {
+ active_address = "2006::1/30"
+ standby_address = "2006::2"
+ }
+ ]
+}
diff --git a/examples/resources/fmc_security_zone/resource.tf b/examples/resources/fmc_security_zone/resource.tf
index 4ddb38be..7ee3c662 100644
--- a/examples/resources/fmc_security_zone/resource.tf
+++ b/examples/resources/fmc_security_zone/resource.tf
@@ -1,4 +1,4 @@
resource "fmc_security_zone" "example" {
name = "security_zone_1"
- interface_mode = "ROUTED"
+ interface_type = "ROUTED"
}
diff --git a/examples/resources/fmc_security_zones/resource.tf b/examples/resources/fmc_security_zones/resource.tf
index 2a58a33d..f168b415 100644
--- a/examples/resources/fmc_security_zones/resource.tf
+++ b/examples/resources/fmc_security_zones/resource.tf
@@ -1,7 +1,7 @@
resource "fmc_security_zones" "example" {
items = {
security_zone_1 = {
- interface_mode = "ROUTED"
+ interface_type = "ROUTED"
}
}
}
diff --git a/gen/definitions/access_control_policy.yaml b/gen/definitions/access_control_policy.yaml
index 0769b365..b82e21fd 100644
--- a/gen/definitions/access_control_policy.yaml
+++ b/gen/definitions/access_control_policy.yaml
@@ -1,7 +1,6 @@
---
name: Access Control Policy
rest_endpoint: /api/fmc_config/v1/domain/{DOMAIN_UUID}/policy/accesspolicies
-data_source_name_query: true
doc_category: Policy
attributes:
- model_name: name
@@ -9,6 +8,7 @@ attributes:
mandatory: true
description: The name of the access control policy.
example: POLICY1
+ data_source_query: true
- model_name: description
type: String
description: Description
diff --git a/gen/definitions/bfd_template.yaml b/gen/definitions/bfd_template.yaml
new file mode 100644
index 00000000..22e48d07
--- /dev/null
+++ b/gen/definitions/bfd_template.yaml
@@ -0,0 +1,79 @@
+---
+name: BFD Template
+rest_endpoint: /api/fmc_config/v1/domain/{DOMAIN_UUID}/object/bfdtemplates
+doc_category: Objects
+attributes:
+ - model_name: name
+ type: String
+ mandatory: true
+ description: The name of the bfd template object.
+ example: BFD_Template1
+ data_source_query: true
+ - model_name: type
+ type: String
+ description: Type of the object; this value is always 'BFDTemplate'.
+ computed: true
+ - model_name: hopType
+ type: String
+ mandatory: true
+ description: The hop type.
+ enum_values: [ SINGLE_HOP, MULTI_HOP ]
+ example: "SINGLE_HOP"
+ - model_name: echo
+ type: String
+ mandatory: true
+ description: "Enables/disables BFD echo."
+ enum_values: [ ENABLED, DISABLED ]
+ example: "ENABLED"
+ - model_name: txRxInterval
+ tf_name: interval_time
+ type: String
+ description: Interval unit of measurement of time.
+ enum_values: [ MILLISECONDS, MICROSECONDS, NONE ]
+ example: "MILLISECONDS"
+ - model_name: minTransmit
+ type: Int64
+ description: BFD Minimum Transmit unit value.
+ min_int: 50
+ max_int: 999000
+ example: 300
+ - model_name: txRxMultiplier
+ type: Int64
+ description: BFD Multipler value.
+ min_int: 3
+ max_int: 50
+ example: 3
+ - model_name: minReceive
+ type: Int64
+ description: "BFD Minimum Receive unit value in ranges: 50-999 miliseconds, 50000-999000 microseconds"
+ min_int: 50
+ max_int: 999000
+ example: 300
+ - model_name: authKey
+ tf_name: authentication_password
+ data_path: [authentication]
+ type: String
+ description: "Password for BFD Authentication (1-24 characters)"
+ example: "Cisco123!"
+ - model_name: authKeyId
+ tf_name: authentication_key_id
+ data_path: [authentication]
+ type: Int64
+ description: Authentication Key ID
+ min_int: 0
+ max_int: 255
+ example: "1"
+ - model_name: authType
+ tf_name: authentication_type
+ data_path: [authentication]
+ type: String
+ description: "Authentication types"
+ example: "MD5"
+ enum_values: [MD5, METICULOUSMD5, METICULOUSSHA1, SHA1, NONE]
+ #- model_name: pwdEncryption
+ # tf_name: authentication_encryption
+ # data_path: [authentication]
+ # type: String
+ # description: "Authentication types: (MD5, METICULOUSMD5, METICULOUSSHA1, SHA1, NONE)"
+ # example: "NONE"
+ # enum_values: [UN_ENCRYPTED, ENCRYPTED, NONE]
\ No newline at end of file
diff --git a/gen/definitions/device.yaml b/gen/definitions/device.yaml
index 9be227f6..95aaf147 100644
--- a/gen/definitions/device.yaml
+++ b/gen/definitions/device.yaml
@@ -1,7 +1,6 @@
---
name: Device
rest_endpoint: /api/fmc_config/v1/domain/{DOMAIN_UUID}/devices/devicerecords
-data_source_name_query: true
doc_category: Devices
test_tags: [FTD_ADDR]
attributes:
@@ -11,6 +10,7 @@ attributes:
description: "User-specified name, must be unique. Example: 'Device 01 - 192.168.0.152'"
example: device1
minimum_test_value: '"device1min"'
+ data_source_query: true
- model_name: hostName
type: String
description: Hostname or IP address of the device. Either the host_name or nat_id must be present.
@@ -45,7 +45,6 @@ attributes:
type: String
description: Type of the device; this value is always 'Device'.
exclude_example: true
- requires_replace: true
default_value: Device
example: Device
- tf_name: access_policy_id
diff --git a/gen/definitions/device_bfd.yaml b/gen/definitions/device_bfd.yaml
new file mode 100644
index 00000000..3a747134
--- /dev/null
+++ b/gen/definitions/device_bfd.yaml
@@ -0,0 +1,67 @@
+---
+name: Device BFD
+rest_endpoint: /api/fmc_config/v1/domain/{DOMAIN_UUID}/devices/devicerecords/%v/routing/bfdpolicies
+doc_category: Device
+test_tags: [TF_VAR_device_id]
+attributes:
+ - tf_name: device_id
+ type: String
+ reference: true
+ description: UUID of the parent device (fmc_device.example.id).
+ example: 76d24097-41c4-4558-a4d0-a8c07ac08470
+ test_value: var.device_id
+ - model_name: type
+ type: String
+ computed: true
+ description: Type of the object; this value is always 'BFDPolicy'
+# General
+ - model_name: hopType
+ description: BFD Hop type.
+ mandatory: true
+ enum_values: [ SINGLE_HOP, MULTI_HOP ]
+ type: String
+ example: SINGLE_HOP
+ - model_name: id
+ tf_name: bfd_template_id
+ data_path: [template]
+ mandatory: true
+ type: String
+ description: ID of the BFD Template
+ example: 76d24097-41c4-4558-a4d0-a8c07ac08470
+ - model_name: ifname
+ data_path: [interface]
+ tf_name: interface_logical_name
+ description: Logical Name of the interface of BFD assignment if SINGLE_HOP selected.
+ type: String
+ example: "outside"
+ data_source_query: true
+ - model_name: id
+ data_path: [destinationAddress]
+ tf_name: destination_host_object_id
+ description: The ID of the destination host object if MULTI_HOP selected.
+ type: String
+ example: 76d24097-41c4-4558-a4d0-a8c07ac08470
+ - model_name: id
+ data_path: [sourceAddress]
+ tf_name: source_host_object_id
+ description: The ID of the source host object if MULTI_HOP selected.
+ type: String
+ example: 76d24097-41c4-4558-a4d0-a8c07ac08470
+ - model_name: id
+ data_path: [interface]
+ tf_name: interface_id
+ description: ID of the interface of BFD assignment if SINGLE_HOP selected.
+ type: String
+ example: 76d24097-41c4-4558-a4d0-a8c07ac08470
+ - model_name: slowTimer
+ type: Int64
+ description: "BFD Slow Timer value in range: 1000-30000, default: 1000"
+ min_int: 1000
+ max_int: 30000
+ default_value: 1000
+ exclude_example: true
+
+test_prerequisites: |-
+ variable "device_id" { default = null } // tests will set $TF_VAR_device_id
+
+
\ No newline at end of file
diff --git a/gen/definitions/device_bgp.yaml b/gen/definitions/device_bgp.yaml
new file mode 100644
index 00000000..03945087
--- /dev/null
+++ b/gen/definitions/device_bgp.yaml
@@ -0,0 +1,681 @@
+---
+name: Device BGP
+rest_endpoint: /api/fmc_config/v1/domain/{DOMAIN_UUID}/devices/devicerecords/%v/routing/bgp
+res_description: Under BGP General Settings, BGP has to be enabled and AS Number assigned first.
+doc_category: Devices
+test_tags: [TF_VAR_device_id]
+attributes:
+ - model_name: device_id
+ type: String
+ reference: true
+ requires_replace: true
+ description: UUID of the parent device (fmc_device.example.id).
+ example: 76d24097-41c4-4558-a4d0-a8c07ac08470
+ test_value: var.device_id
+ - model_name: name
+ type: String
+ description: Name of the object; this is always 'bgp'
+ computed: true
+ - model_name: type
+ type: String
+ description: Type of the object; this is always 'bgp'
+ computed: true
+ - model_name: asNumber
+ type: String
+ description: Autonomus System (AS) Number
+ computed: true
+ data_source_query: true
+# BGP - IPv4 - General
+ - model_name: type
+ tf_name: ipv4_address_family_type
+ data_path: [addressFamilyIPv4]
+ type: String
+ computed: true
+ - model_name: id
+ tf_name: ipv4_learned_route_map_id
+ data_path: [addressFamilyIPv4, aftableMap]
+ type: String
+ description: Learned Route Map ID
+ exclude_test: true
+ exclude_example: true
+ - model_name: defaultInformationOrginate
+ tf_name: ipv4_default_information_orginate
+ data_path: [addressFamilyIPv4]
+ type: Bool
+ example: "false"
+ description: Generate default routes
+ - model_name: autoSummary
+ tf_name: ipv4_auto_aummary
+ data_path: [addressFamilyIPv4]
+ type: Bool
+ example: "false"
+ description: Summarize subnet routes into network level routes
+ - model_name: bgpSupressInactive
+ tf_name: ipv4_bgp_supress_inactive
+ data_path: [addressFamilyIPv4]
+ type: Bool
+ example: "false"
+ description: Suppresing advertise inactive routes
+ - model_name: synchronization
+ tf_name: ipv4_synchronization
+ data_path: [addressFamilyIPv4]
+ type: Bool
+ example: "false"
+ description: Synchronize between BGP and IGP systems
+ - model_name: bgpRedistributeInternal
+ tf_name: ipv4_bgp_redistribute_internal
+ data_path: [addressFamilyIPv4]
+ type: Bool
+ example: "false"
+ description: Redistribute IBGP into IGP. (Use filtering to limit the number of prefixes that are redistributed)
+ - model_name: externalDistance
+ tf_name: ipv4_external_distance
+ data_path: [addressFamilyIPv4, distance]
+ type: Int64
+ description: Administrative route distance for external routes
+ min_int: 1
+ max_int: 255
+ default_value: 20
+ example: 20
+ - model_name: internalDistance
+ tf_name: ipv4_internal_distance
+ data_path: [addressFamilyIPv4, distance]
+ type: Int64
+ description: Administrative route distance for internal routes
+ min_int: 1
+ max_int: 255
+ default_value: 200
+ example: 200
+ - model_name: localDistance
+ tf_name: ipv4_local_distance
+ data_path: [addressFamilyIPv4, distance]
+ type: Int64
+ description: Administrative route distance for local routes
+ min_int: 1
+ max_int: 255
+ example: 200
+ default_value: 200
+ - model_name: ibgp
+ tf_name: ipv4_forward_packets_over_multipath_ibgp ## ipv4_number_of_ibgp_paths
+ data_path: [addressFamilyIPv4]
+ type: Int64
+ description: Number of paths to use for IBGP
+ min_int: 1
+ max_int: 8
+ example: 1
+ default_value: 1
+ - model_name: ebgp
+ tf_name: ipv4_forward_packets_over_multipath_ebgp ## ipv4_number_of_ebgp_paths
+ data_path: [addressFamilyIPv4]
+ type: Int64
+ description: Number of paths to use for EBGP
+ min_int: 1
+ max_int: 8
+ example: 1
+ default_value: 1
+# BGP - IPv4 - Neighbor
+ - model_name: neighbors
+ tf_name: ipv4_neighbors
+ data_path: [addressFamilyIPv4]
+ type: List
+ attributes:
+ - model_name: ipv4Address
+ tf_name: neighbor_address
+ type: String
+ description: IP address of the BGP neighbor
+ id: true
+ example: "10.1.1.1"
+ - model_name: remoteAs
+ tf_name: neighbor_remote_as
+ type: String
+ description: AS number of the BGP neighbor
+ id: true
+ example: "65534"
+ - model_name: fallOverBFD
+ data_path: [neighborGeneral]
+ tf_name: neighbor_bfd
+ type: String
+ description: BFD Fallover
+ enum_values: [ SINGLE_HOP, MULTI_HOP, AUTO_DETECT_HOP, NONE ]
+ example: "SINGLE_HOP"
+ default_value: "NONE"
+ - model_name: id
+ data_path: [neighborGeneral, updateSource]
+ tf_name: update_source_interface_id
+ type: String
+ description: Interface ID for the update source
+ example: 76d24097-41c4-4558-a4d0-a8c07ac08470
+ exclude_test: true
+ exclude_example: true
+ - model_name: enableAddress
+ data_path: [neighborGeneral]
+ tf_name: enable_address_family
+ type: Bool
+ description: Enable IPv4 address family
+ default_value: "false"
+ example: "true"
+ - model_name: shutdown
+ data_path: [neighborGeneral]
+ tf_name: neighbor_shutdown
+ description: Shutdown administratively
+ type: Bool
+ default_value: "false"
+ example: "false"
+ exclude_example: true
+ - model_name: description
+ tf_name: neighbor_description
+ data_path: [neighborGeneral]
+ type: String
+ description: Description of the neighbor
+ example: "My BGP Peer"
+# BGP - IPv4 - Neighbor - Filtering Routes
+ - model_name: neighborDistributeLists
+ tf_name: neighbor_filter_access_lists
+ data_path: [neighborFiltering]
+ type: List
+ exclude_test: true
+ exclude_example: true
+ attributes:
+ - model_name: id
+ tf_name: access_list_id
+ data_path: [accessList]
+ type: String
+ description: Access List ID
+ exclude_test: true
+ exclude_example: true
+ - model_name: filterUpdateAction
+ tf_name: update_direction
+ type: String
+ description: Filter direction
+ enum_values: [ IN, OUT ]
+ exclude_test: true
+ exclude_example: true
+ - model_name: neighborRouteMap
+ tf_name: neighbor_filter_route_map_lists
+ data_path: [neighborFiltering]
+ type: List
+ exclude_test: true
+ exclude_example: true
+ attributes:
+ - model_name: id
+ tf_name: route_map_id
+ data_path: [RouteMap]
+ type: String
+ description: Route Map ID
+ exclude_test: true
+ exclude_example: true
+ - model_name: filterUpdateAction
+ tf_name: update_direction
+ type: String
+ description: Filter direction
+ enum_values: [ IN, OUT ]
+ exclude_test: true
+ exclude_example: true
+ - model_name: ipv4PrefixListFilter
+ tf_name: neighbor_filter_prefix_lists
+ data_path: [neighborFiltering]
+ type: List
+ exclude_test: true
+ exclude_example: true
+ attributes:
+ - model_name: id
+ tf_name: prefix_list_id
+ data_path: [ipv4PrefixList]
+ type: String
+ description: Route Map ID
+ exclude_test: true
+ exclude_example: true
+ - model_name: filterUpdateAction
+ tf_name: update_direction
+ type: String
+ description: Filter direction
+ enum_values: [ IN, OUT ]
+ exclude_test: true
+ exclude_example: true
+ - model_name: neighborFilterList
+ tf_name: neighbor_filter_as_path_lists
+ data_path: [neighborFilterList]
+ type: List
+ exclude_test: true
+ exclude_example: true
+ attributes:
+ - model_name: filterUpdateAction
+ tf_name: update_direction
+ type: String
+ description: Filter direction
+ enum_values: [ IN, OUT ]
+ exclude_test: true
+ exclude_example: true
+ - model_name: id
+ tf_name: as_path_id
+ data_path: [asPathList]
+ type: String
+ description: AS Path ID
+ exclude_test: true
+ exclude_example: true
+ - model_name: maxPrefixLimit
+ data_path: [neighborFiltering, neighborMaximumPrefix]
+ tf_name: neighbor_filter_max_prefix
+ type: Int64
+ description: Maximum number of prefixes allowed from the neighbor
+ min_int: 1
+ max_int: 2147483647
+ example: 1
+ exclude_example: true
+ - model_name: warningOnly
+ data_path: [neighborFiltering, neighborMaximumPrefix]
+ tf_name: neighbor_filter_warning_only
+ type: Bool
+ description: Give only warning message when prefix limit exceeded or terminate peering when prefix limit is exceeded.
+ example: true
+ exclude_example: true
+ - model_name: thresholdValue
+ data_path: [neighborFiltering, neighborMaximumPrefix]
+ tf_name: neighbor_filter_threshold_value
+ type: Int64
+ description: Threshold value for the maximum number of prefixes allowed from the neighbor
+ min_int: 1
+ max_int: 100
+ example: 1
+ exclude_example: true
+ - model_name: restartInterval
+ data_path: [neighborFiltering, neighborMaximumPrefix]
+ tf_name: neighbor_filter_restart_interval
+ type: Int64
+ description: Time interval to restart the maximum prefix limit in Minutes
+ min_int: 1
+ max_int: 65535
+ example: 1
+ exclude_example: true
+# BGP - IPv4 - Neighbor - Routes
+ - model_name: advertisementInterval
+ data_path: [neighborRoutes]
+ tf_name: neighbor_routes_advertisement_interval
+ type: Int64
+ description: Time interval to advertise routes in seconds
+ min_int: 0
+ max_int: 600
+ default_value: 0
+ example: 1
+ exclude_example: true
+ - model_name: removePrivateAs
+ data_path: [neighborRoutes]
+ tf_name: neighbor_routes_remove_private_as
+ type: Bool
+ description: Remove private AS numbers from outgoing routing updates
+ default_value: "false"
+ example: "false"
+ exclude_example: true
+ - model_name: id
+ tf_name: neighbor_generate_default_route_map_id
+ data_path: [neighborFiltering, neighborDefaultOriginate, routeMap]
+ type: String
+ description: Generate default routes - Route Map
+ exclude_test: true
+ exclude_example: true
+ - model_name: existMap
+ data_path: [neighborRoutes, neighborAdvertiseMaps]
+ tf_name: neighbor_routes_advertise_map_use_exist
+ type: Bool
+ exclude_test: true
+ exclude_example: true
+ description: Use Exist Map or Non-Exist Map
+ - model_name: id
+ tf_name: neighbor_routes_advertise_map_id
+ data_path: [neighborRoutes, neighborAdvertiseMaps, routeMap]
+ type: String
+ id: true
+ description: Specified route maps are advertised when the prefix exists in the Advertise Map and Exist Map.
+ exclude_test: true
+ exclude_example: true
+ - model_name: id
+ tf_name: neighbor_routes_advertise_exist_nonexist_map_id
+ data_path: [neighborRoutes, neighborAdvertiseMaps, existRouteMap]
+ type: String
+ id: true
+ description: Specified route maps are advertised when the prefix exists only in the Advertise Map.
+ exclude_test: true
+ exclude_example: true
+# BGP - IPv4 - Neighbor - Timers
+ - model_name: keepAliveInterval
+ data_path: [neighborTimers]
+ tf_name: neighbor_keepalive_interval
+ type: Int64
+ description: Time interval to send keepalive messages in seconds
+ min_int: 0
+ max_int: 65535
+ example: 60
+ exclude_example: true
+ - model_name: holdTime
+ data_path: [neighborTimers]
+ tf_name: neighbor_hold_time
+ type: Int64
+ description: Time interval to hold the neighbor in seconds
+ min_int: 3
+ max_int: 65535
+ example: 180
+ exclude_example: true
+ - model_name: minimumHoldTime
+ data_path: [neighborTimers]
+ tf_name: neighbor_min_hold_time
+ type: Int64
+ description: Minimum hold time in seconds
+ min_int: 3
+ max_int: 65535
+ example: 3
+ exclude_example: true
+# BGP - IPv4 - Neighbor - Advanced
+ - model_name: neighborSecret
+ tf_name: neighbor_authentication_password
+ data_path: [neighborAdvanced]
+ type: String
+ description: Setting password enables authentication.
+ exclude_example: true
+ exclude_test: true
+ - model_name: sendCommunity
+ tf_name: neighbor_send_community_attribute
+ data_path: [neighborAdvanced]
+ type: Bool
+ description: Send Community attribute to this neighbor
+ default_value: "false"
+ example: "false"
+ exclude_example: true
+ - model_name: nextHopSelf
+ tf_name: neighbor_nexthop_self
+ data_path: [neighborAdvanced]
+ type: Bool
+ exclude_example: true
+ default_value: "false"
+ example: "false"
+ description: Use itself as next hop for this neighbor
+ - model_name: disableConnectedCheck
+ tf_name: neighbor_disable_connection_verification
+ data_path: [neighborAdvanced, neighborHops]
+ type: Bool
+ description: Disable Connection Verification
+ exclude_example: true
+ default_value: "false"
+ example: "false"
+ - model_name: disable
+ tf_name: neighbor_tcp_mtu_path_discovery
+ data_path: [neighborAdvanced, neighborTransportPathMTUDiscovery]
+ type: Bool
+ description: Use TCP path MTU discovery.
+ default_value: "false"
+ example: "false"
+ exclude_example: true
+ - model_name: maxHopCount
+ tf_name: neighbor_max_hop_count
+ data_path: [neighborAdvanced, neighborHops]
+ type: Int64
+ description: Maximum number of hops to reach the neighbor
+ min_int: 1
+ max_int: 255
+ default_value: 1
+ example: 1
+ exclude_example: true
+ - model_name: establishTCPSession
+ tf_name: neighbor_tcp_transport_mode
+ data_path: [neighborAdvanced, neighborTransportConnectionMode]
+ type: Bool
+ description: True set it to active, False to passive.
+ default_value: "false"
+ example: "false"
+ exclude_example: true
+ - model_name: neighborWeight
+ tf_name: neighbor_weight
+ data_path: [neighborAdvanced]
+ type: Int64
+ description: Weight of the neighbor
+ min_int: 0
+ max_int: 65535
+ default_value: 0
+ example: 0
+ exclude_example: true
+ - model_name: neighborVersion
+ tf_name: neighbor_version
+ data_path: [neighborAdvanced]
+ type: String
+ enum_values: ["0", "4"]
+ default_value: "0"
+ example: "0"
+ exclude_example: true
+ description: "Set BPG version: 0 - default, 4 - IPv4"
+# BGP - IPv4 - Neighbor - Migration
+ - model_name: asNumber
+ tf_name: neighbor_customized_local_as_number
+ data_path: [neighborLocalAs]
+ type: String
+ description: Customize the AS number for the routes received from neighbor
+ exclude_test: true
+ exclude_example: true
+ - model_name: noPrepend
+ tf_name: neighbor_customized_no_prepend
+ data_path: [neighborLocalAs]
+ type: Bool
+ description: Do not prepend local AS number to routes received from neighbor
+ exclude_test: true
+ exclude_example: true
+ - model_name: replaceAs
+ tf_name: neighbor_customized_replace_as
+ data_path: [neighborLocalAs]
+ type: Bool
+ description: Replace real AS number with local AS number in routes received from neighbor
+ exclude_test: true
+ exclude_example: true
+ - model_name: dualAs
+ tf_name: neighbor_customized_accept_both_as
+ data_path: [neighborLocalAs]
+ type: Bool
+ description: Accept either real AS number or local AS number in routes experienced from neighbor
+ exclude_test: true
+ exclude_example: true
+# BGP - IPv4 - Aggregate Address
+ - model_name: aggregateAddressesIPv4s
+ tf_name: ipv4_aggregate_addresses
+ data_path: [addressFamilyIPv4]
+ type: List
+ exclude_test: true
+ exclude_example: true
+ attributes:
+ - model_name: asSet
+ tf_name: generate_as
+ type: Bool
+ description: Generate AS set path information
+ exclude_test: true
+ exclude_example: true
+ - model_name: summaryOnly
+ tf_name: filter
+ type: Bool
+ description: Filter all routes from updates (summary only)
+ exclude_test: true
+ exclude_example: true
+ - model_name: id
+ tf_name: network_id
+ data_path: [ipv4AggregateNetwork]
+ type: String
+ description: Network ID
+ id: true
+ exclude_test: true
+ exclude_example: true
+ - model_name: id
+ tf_name: advertise_map_id
+ data_path: [advertiseMap]
+ type: String
+ description: Advertise Map ID
+ id: true
+ exclude_test: true
+ exclude_example: true
+ - model_name: id
+ tf_name: attribute_map_id
+ data_path: [attributeMap]
+ type: String
+ description: Attribute Map ID
+ id: true
+ exclude_test: true
+ exclude_example: true
+ - model_name: id
+ tf_name: suppress_map_id
+ data_path: [suppressMap]
+ type: String
+ description: Suppress Map ID
+ id: true
+ exclude_test: true
+ exclude_example: true
+# BGP - IPv4 - Filtering
+ - model_name: distributeLists
+ tf_name: ipv4_filterings
+ data_path: [addressFamilyIPv4]
+ type: List
+ exclude_test: true
+ exclude_example: true
+ attributes:
+ - model_name: id
+ tf_name: access_list_id
+ data_path: [ipv4AggregateNetwork]
+ type: String
+ description: Standard Access List ID
+ id: true
+ exclude_test: true
+ exclude_example: true
+ - model_name: type
+ tf_name: network_direction
+ type: String
+ enum_values: [incomingroutefilter, outgoingroutefilter]
+ description: Filtering directrion
+ exclude_test: true
+ exclude_example: true
+ - model_name: protocol
+ tf_name: protocol
+ data_path: [protocol]
+ type: String
+ description: Protocol ## TODO: Enum values
+ exclude_test: true
+ exclude_example: true
+ - model_name: processId ## TODO: Enum values
+ tf_name: prorocol_process
+ data_path: [protocol]
+ type: String
+ description: Process ID
+ exclude_test: true
+ exclude_example: true
+# BGP - IPv4 - Networks
+ - model_name: networks
+ tf_name: ipv4_networks
+ data_path: [addressFamilyIPv4]
+ type: List
+ exclude_test: true
+ exclude_example: true
+ attributes:
+ - model_name: id
+ tf_name: network_id
+ data_path: [ipv4Address]
+ type: String
+ description: Network object ID
+ id: true
+ exclude_test: true
+ exclude_example: true
+ - model_name: id
+ tf_name: route_map_id
+ data_path: [routeMap]
+ type: String
+ description: Route Map ID
+ id: true
+ exclude_test: true
+ exclude_example: true
+# BGP - IPv4 - Redistribution
+ - model_name: redistributeProtocols
+ tf_name: ipv4_redistributions
+ data_path: [addressFamilyIPv4]
+ type: List
+ exclude_test: true
+ exclude_example: true
+ attributes:
+ - model_name: type
+ tf_name: source_protocol
+ type: String
+ enum_values: [RedistributeConnected, RedistributeStatic, RedistributeOSPF, RedistributeEIGRP ]
+ description: Protocol to redistribute
+ exclude_test: true
+ exclude_example: true
+ - model_name: id
+ tf_name: route_map_id
+ data_path: [routeMap]
+ type: String
+ description: Route Map ID
+ id: true
+ exclude_test: true
+ exclude_example: true
+ - model_name: metricValue
+ tf_name: metric
+ data_path: [routeMetric]
+ type: Int64
+ description: Metric value
+ min_int: 0
+ max_int: 4294967295
+ exclude_test: true
+ exclude_example: true
+ - model_name: processId
+ type: String
+ description: process ID
+ exclude_test: true
+ exclude_example: true
+ - model_name: matchExternal1
+ type: Bool
+ description: Match OSPF External 1 metrics
+ exclude_test: true
+ exclude_example: true
+ - model_name: matchExternal2
+ type: Bool
+ description: Match OSPF External 2 metrics
+ exclude_test: true
+ exclude_example: true
+ - model_name: matchInternal
+ type: Bool
+ description: Match OSPF Internal metrics
+ exclude_test: true
+ exclude_example: true
+ - model_name: matchNssaExternal1
+ type: Bool
+ description: Match OSPF NSSA External 1 metrics
+ exclude_test: true
+ exclude_example: true
+ - model_name: matchNssaExternal2
+ type: Bool
+ description: Match OSPF NSSA External 2 metrics
+ exclude_test: true
+ exclude_example: true
+# BGP - IPv4 - Route Injection
+ - model_name: injectMaps
+ tf_name: ipv4_route_injections
+ data_path: [addressFamilyIPv4]
+ type: List
+ exclude_test: true
+ exclude_example: true
+ attributes:
+ - model_name: id
+ tf_name: inject_route_map_id
+ data_path: [injectMap, routeMap]
+ type: String
+ description: Inject Route Map ID
+ id: true
+ exclude_test: true
+ exclude_example: true
+ - model_name: id
+ tf_name: exist_route_map_id
+ data_path: [existMap, routeMap]
+ type: String
+ description: Exist Route Map ID
+ id: true
+ exclude_test: true
+ exclude_example: true
+
+# BGP - IPv6 - TODO
+
+test_prerequisites: |-
+ variable "device_id" { default = null } // tests will set $TF_VAR_device_id
+
+ resource "fmc_device_bgp_general_settings" "test" {
+ device_id = var.device_id
+ as_number = "6353"
+ }
diff --git a/gen/definitions/device_bgp_general_settings.yaml b/gen/definitions/device_bgp_general_settings.yaml
new file mode 100644
index 00000000..94f470ca
--- /dev/null
+++ b/gen/definitions/device_bgp_general_settings.yaml
@@ -0,0 +1,179 @@
+---
+name: Device BGP General Settings
+rest_endpoint: /api/fmc_config/v1/domain/{DOMAIN_UUID}/devices/devicerecords/%v/routing/bgpgeneralsettings
+doc_category: Devices
+test_tags: [TF_VAR_device_id]
+attributes:
+ - model_name: device_id
+ type: String
+ reference: true
+ requires_replace: true
+ description: UUID of the parent device (fmc_device.example.id).
+ example: 76d24097-41c4-4558-a4d0-a8c07ac08470
+ test_value: var.device_id
+ - model_name: name
+ type: String
+ description: Object name; Always set to 'AsaBGPGeneralTable'
+ computed: true
+ - model_name: asNumber
+ type: String
+ description: Autonomous System (AS) number in asplain or asdot format
+ mandatory: true
+ example: "65535"
+ data_source_query: true
+ - model_name: routerId
+ type: String
+ example: AUTOMATIC
+ description: String value for the routerID. Possible values can be 'AUTOMATIC' or valid ipv4 address
+# BGP - General
+ - model_name: scanTime
+ tf_name: scanning_interval
+ type: Int64
+ min_int: 5
+ max_int: 60
+ example: 60
+ description: Scanning interval of BGP routers for next hop validation in Seconds.
+ - model_name: maxasLimit
+ tf_name: as_number_in_path_attribute
+ type: Int64
+ min_int: 1
+ max_int: 254
+ example: 50
+ description: Range to discard routes that have as-path segments that exceed a specified value.
+ - model_name: logNeighborChanges
+ type: Bool
+ exclude_example: true
+ example: "false"
+ description: Enable logging of BGP neighbor status changes.
+ - model_name: transportPathMtuDiscovery
+ tf_name: tcp_path_mtu_discovery
+ type: Bool
+ example: "true"
+ description: Use TCP path MTU discovery.
+ - model_name: fastExternalFallOver
+ tf_name: reset_session_upon_failover
+ type: Bool
+ description: Reset session upon failover
+ example: "true"
+ - model_name: enforceFirstAs
+ tf_name: enforce_first_peer_as
+ type: Bool
+ description: Discard updates received from an external BGP (eBGP) peers that do not list their autonomous system (AS) number.
+ example: "true"
+ - model_name: asnotationDot
+ tf_name: use_dot_notation
+ type: Bool
+ example: "false"
+ description: Change format of BGP 4-byte autonomous system numbers from asplain (decimal values) to dot notation.
+ - model_name: aggregateTimer
+ type: Int64
+ min_int: 6
+ max_int: 60
+ example: 30
+ exclude_example: true
+ description: Interval at which BGP routes will be aggregated or to disable timer-based router aggregation (in seconds).
+# BGP - Best Path Selection
+ - model_name: defaultLocalPreferenceValue
+ tf_name: default_local_preference
+ data_path: [bestPath]
+ type: Int64
+ description: Default local preference
+ min_int: 0
+ max_int: 4294967295
+ example: 100
+ exclude_example: true
+ - model_name: alwaysCompareMed
+ tf_name: compare_med_from_different_neighbors
+ data_path: [bestPath]
+ type: Bool
+ description: Allow comparing MED from different neighbors
+ example: "true"
+ exclude_example: true
+ - model_name: deterministicMed
+ tf_name: compare_router_id_in_path
+ data_path: [bestPath]
+ type: Bool
+ description: Compare Router ID for identical EBGP paths
+ example: "true"
+ exclude_example: true
+ - model_name: bestPathCompareRouterId
+ tf_name: pick_best_med
+ data_path: [bestPath]
+ type: Bool
+ description: Pick the best-MED path among paths advertised by neighbor AS
+ example: "true"
+ exclude_example: true
+ - model_name: bestPathMedMissingAsWorst
+ tf_name: missing_med_as_best
+ data_path: [bestPath]
+ type: Bool
+ description: Treat missing MED as the best preferred path
+ example: "false"
+ exclude_example: true
+# BGP - Neighbor Timers
+ - model_name: keepAlive
+ tf_name: keepalive_interval
+ data_path: [bgptimers]
+ type: Int64
+ description: Keepalive interval in seconds
+ min_int: 0
+ max_int: 65535
+ example: 60
+ exclude_example: true
+ - model_name: holdTime
+ data_path: [bgptimers]
+ type: Int64
+ description: Hold time in seconds
+ min_int: 0
+ max_int: 65535
+ example: 180
+ exclude_example: true
+ - model_name: minHoldTime
+ data_path: [bgptimers]
+ type: Int64
+ description: Minimum hold time (0 or 3-65535 seconds)
+ min_int: 0
+ max_int: 65535
+ example: 0
+ exclude_example: true
+# BGP - Next Hop
+ - model_name: bgpNextHopTriggerEnable
+ tf_name: next_hop_address_tracking
+ type: Bool
+ description: Enable next hop address tracking
+ exclude_example: true
+ exclude_test: true
+ - model_name: bgpNextHopTriggerDelay
+ tf_name: next_hop_delay_interval
+ type: Int64
+ description: Next hop delay interval in seconds
+ min_int: 0
+ max_int: 100
+ example: 5
+ exclude_example: true
+# BGP - Graceful Restart (used in HA or Cluster setup)
+ - model_name: gracefulRestart
+ data_path: [bgpGracefulRestart]
+ type: Bool
+ description: Enable graceful restart
+ exclude_example: true
+ exclude_test: true
+ - model_name: gracefulRestartRestartTime
+ data_path: [bgpGracefulRestart]
+ type: Int64
+ description: Graceful Restart Time in seconds
+ min_int: 1
+ max_int: 3600
+ exclude_example: true
+ exclude_test: true
+ - model_name: gracefulRestartStalePathTime
+ data_path: [bgpGracefulRestart]
+ type: Int64
+ description: Stalepath Time in seconds
+ min_int: 1
+ max_int: 3600
+ exclude_example: true
+ exclude_test: true
+
+test_prerequisites: |-
+ variable "device_id" { default = null } // tests will set $TF_VAR_device_id
\ No newline at end of file
diff --git a/gen/definitions/device_etherchannel_interface.yaml b/gen/definitions/device_etherchannel_interface.yaml
index c7b5477e..f16fa91d 100644
--- a/gen/definitions/device_etherchannel_interface.yaml
+++ b/gen/definitions/device_etherchannel_interface.yaml
@@ -1,7 +1,6 @@
---
name: Device EtherChannel Interface
rest_endpoint: /api/fmc_config/v1/domain/{DOMAIN_UUID}/devices/devicerecords/%v/etherchannelinterfaces
-data_source_name_query: true
doc_category: Devices
test_tags: [TF_VAR_device_id, TF_VAR_interface_id, FMC_DEVICE_ETHERCHANNEL_INTERFACE]
attributes:
@@ -69,6 +68,7 @@ attributes:
type: String
description: Name of the interface; it must already be present on the device.
computed: true
+ data_source_query: true
- model_name: MTU
tf_name: mtu
type: Int64
diff --git a/gen/definitions/device_ha_pair_monitoring.yaml b/gen/definitions/device_ha_pair_monitoring.yaml
new file mode 100644
index 00000000..bd77f9d9
--- /dev/null
+++ b/gen/definitions/device_ha_pair_monitoring.yaml
@@ -0,0 +1,70 @@
+---
+name: Device HA Pair Monitoring
+rest_endpoint: /api/fmc_config/v1/domain/{DOMAIN_UUID}/devicehapairs/ftddevicehapairs/%v/monitoredinterfaces
+put_create: true
+doc_category: Device
+test_tags: [TF_VAR_device_ha_id]
+attributes:
+ - tf_name: device_id
+ type: String
+ reference: true
+ description: UUID of the parent HA device (fmc_device.example.id).
+ example: 76d24097-41c4-4558-a4d0-a8c07ac08470
+ test_value: var.device_ha_id
+ - model_name: type
+ type: String
+ computed: true
+ description: Type of the resource.
+# General
+ - model_name: name
+ tf_name: logical_name
+ description: Logical Name of the monitored interface.
+ mandatory: true
+ type: String
+ example: "outside"
+ data_source_query: true
+ - model_name: monitorForFailures
+ tf_name: monitor_interface
+ description: Monitor this interface for failures.
+ mandatory: true
+ type: Bool
+ example: true
+ - model_name: activeIPv4Address
+ tf_name: ipv4_active_address
+ data_path: [ipv4Configuration]
+ type: String
+ description: >-
+ Active IPv4 address from the interface.
+ computed: true
+ - model_name: standbyIPv4Address
+ tf_name: ipv4_standby_address
+ data_path: [ipv4Configuration]
+ type: String
+ description: >-
+ Standby IPv4 address. It has to be in the same subnet as primaty IP configured on this interface.
+ example: 10.1.1.2
+ - model_name: activeIPv4Mask
+ tf_name: ipv4_netmask
+ data_path: [ipv4Configuration]
+ type: String
+ description: >-
+ IPv4 Network Mask assigned on the interface.
+ computed: true
+ - model_name: ipv6ActiveStandbyPair
+ data_path: [ipv6Configuration]
+ tf_name: ipv6_addresses
+ type: List
+ attributes:
+ - model_name: activeIPv6
+ tf_name: active_address
+ type: String
+ description: Active IPv6 address with prefix. Address has to be configured on the interface.
+ example: "2006::1/30"
+ - model_name: standbyIPv6
+ tf_name: standby_address
+ type: String
+ description: Standby IPv6 address. Address has to be from the same subnet as active IPv6 address.
+ example: "2006::2"
+
+test_prerequisites: |-
+ variable "device_ha_id" { default = null } // tests will set $TF_VAR_device_ha_id
diff --git a/gen/definitions/device_physical_interface.yaml b/gen/definitions/device_physical_interface.yaml
index 8623ba8d..5d149797 100644
--- a/gen/definitions/device_physical_interface.yaml
+++ b/gen/definitions/device_physical_interface.yaml
@@ -2,7 +2,6 @@
name: Device Physical Interface
rest_endpoint: /api/fmc_config/v1/domain/{DOMAIN_UUID}/devices/devicerecords/%v/physicalinterfaces
put_create: true
-data_source_name_query: true
doc_category: Devices
test_tags: [TF_VAR_device_id]
attributes:
@@ -73,6 +72,7 @@ attributes:
description: Name of the interface; it must already be present on the device.
mandatory: true
example: GigabitEthernet0/1
+ data_source_query: true
- model_name: MTU
tf_name: mtu
type: Int64
diff --git a/gen/definitions/device_subinterface.yaml b/gen/definitions/device_subinterface.yaml
index f8a4a9b1..982f45be 100644
--- a/gen/definitions/device_subinterface.yaml
+++ b/gen/definitions/device_subinterface.yaml
@@ -2,7 +2,6 @@
name: Device Subinterface
rest_endpoint: /api/fmc_config/v1/domain/{DOMAIN_UUID}/devices/devicerecords/%v/subinterfaces
doc_category: Devices
-data_source_name_query: true
test_tags: [TF_VAR_device_id, TF_VAR_interface_name]
attributes:
- tf_name: device_id
@@ -20,6 +19,7 @@ attributes:
type: String
computed: true
description: Name of the subinterface in format `interface_name.subinterface_id` (eg. GigabitEthernet0/1.7).
+ data_source_query: true
# General
- model_name: ifname
tf_name: logical_name
diff --git a/gen/definitions/device_vrf.yaml b/gen/definitions/device_vrf.yaml
index d55c5708..633b6c18 100644
--- a/gen/definitions/device_vrf.yaml
+++ b/gen/definitions/device_vrf.yaml
@@ -1,7 +1,6 @@
---
name: Device VRF
rest_endpoint: /api/fmc_config/v1/domain/{DOMAIN_UUID}/devices/devicerecords/%v/routing/virtualrouters
-data_source_name_query: true
doc_category: Devices
test_tags: [TF_VAR_device_id, TF_VAR_interface_name]
attributes:
@@ -18,6 +17,7 @@ attributes:
requires_replace: true
description: The name of the VRF
example: VRF_A
+ data_source_query: true
- model_name: type
type: String
description: Type of the object; this value is always 'VirtualRouter'.
diff --git a/gen/definitions/device_vtep_policy.yaml b/gen/definitions/device_vtep_policy.yaml
index 12937f23..00700a81 100644
--- a/gen/definitions/device_vtep_policy.yaml
+++ b/gen/definitions/device_vtep_policy.yaml
@@ -12,7 +12,6 @@ attributes:
- tf_name: device_id
type: String
reference: true
- requires_replace: true
description: >-
UUID of the parent device (fmc_device.example.id).
example: 76d24097-41c4-4558-a4d0-a8c07ac08470
@@ -61,7 +60,6 @@ attributes:
description: Encapsulation type.
enum_values: [VXLAN, GENEVE]
default_value: VXLAN
- requires_replace: true
exclude_example: true
exclude_test: true
- model_name: nveNeighborDiscoveryType
diff --git a/gen/definitions/dynamic_objects.yaml b/gen/definitions/dynamic_objects.yaml
index e45a7dd8..7cf22075 100644
--- a/gen/definitions/dynamic_objects.yaml
+++ b/gen/definitions/dynamic_objects.yaml
@@ -7,8 +7,6 @@ res_description: >-
Updating/deleting `fmc_dynamic_objects` can thus take much more time than creating it
doc_category: Objects
is_bulk: true
-data_source_name_query: yes
-import_name_query: yes
minimum_version_bulk_delete: "7.0"
attributes:
- model_name: items
diff --git a/gen/definitions/extended_acl.yaml b/gen/definitions/extended_acl.yaml
index 9bb939cb..00f7c2ca 100644
--- a/gen/definitions/extended_acl.yaml
+++ b/gen/definitions/extended_acl.yaml
@@ -1,7 +1,6 @@
---
name: Extended ACL
rest_endpoint: /api/fmc_config/v1/domain/{DOMAIN_UUID}/object/extendedaccesslists
-data_source_name_query: true
doc_category: Objects
minimum_version_create: "7.2"
attributes:
@@ -10,6 +9,7 @@ attributes:
description: User-created name of the resource.
mandatory: true
example: extended_acl_1
+ data_source_query: true
- model_name: description
type: String
description: Optional user-created description.
diff --git a/gen/definitions/file_policy.yaml b/gen/definitions/file_policy.yaml
index bb73b5a6..63b515dd 100644
--- a/gen/definitions/file_policy.yaml
+++ b/gen/definitions/file_policy.yaml
@@ -1,7 +1,6 @@
---
name: File Policy
rest_endpoint: /api/fmc_config/v1/domain/{DOMAIN_UUID}/policy/filepolicies
-data_source_name_query: true
doc_category: Policy
attributes:
- model_name: name
@@ -9,6 +8,7 @@ attributes:
mandatory: true
description: The name of file policy.
example: file_policy_1
+ data_source_query: true
- model_name: type
type: String
description: Type of the object
diff --git a/gen/definitions/fqdn_object.yaml b/gen/definitions/fqdn_object.yaml
index 571c846c..87c028f9 100644
--- a/gen/definitions/fqdn_object.yaml
+++ b/gen/definitions/fqdn_object.yaml
@@ -1,7 +1,6 @@
---
name: FQDN Object
rest_endpoint: /api/fmc_config/v1/domain/{DOMAIN_UUID}/object/fqdns
-data_source_name_query: true
doc_category: Objects
attributes:
- model_name: name
@@ -9,6 +8,7 @@ attributes:
description: User-created name of the resource.
mandatory: true
example: fqdn_1
+ data_source_query: true
- model_name: value
type: String
description: The fully qualified domain name.
diff --git a/gen/definitions/fqdn_objects.yaml b/gen/definitions/fqdn_objects.yaml
index bde468e9..17e05880 100644
--- a/gen/definitions/fqdn_objects.yaml
+++ b/gen/definitions/fqdn_objects.yaml
@@ -7,8 +7,6 @@ res_description: >-
Updating/deleting `fmc_fqdn_objecs` can thus take much more time than creating it
doc_category: Objects
is_bulk: true
-data_source_name_query: yes
-import_name_query: yes
minimum_version_bulk_delete: "7.4"
attributes:
- model_name: items
diff --git a/gen/definitions/ftd_nat_policy.yaml b/gen/definitions/ftd_nat_policy.yaml
index 4fa7c7ab..f05e1fc4 100644
--- a/gen/definitions/ftd_nat_policy.yaml
+++ b/gen/definitions/ftd_nat_policy.yaml
@@ -1,7 +1,6 @@
---
name: FTD NAT Policy
rest_endpoint: /api/fmc_config/v1/domain/{DOMAIN_UUID}/policy/ftdnatpolicies
-data_source_name_query: true
doc_category: Policy
attributes:
- model_name: name
@@ -9,6 +8,7 @@ attributes:
mandatory: true
description: The name of the FTD Network Address Translation (NAT) policy.
example: nat_policy_1
+ data_source_query: true
- model_name: description
type: String
description: Policy description
diff --git a/gen/definitions/host.yaml b/gen/definitions/host.yaml
index 63e7eab5..79b05de2 100644
--- a/gen/definitions/host.yaml
+++ b/gen/definitions/host.yaml
@@ -1,7 +1,6 @@
---
name: Host
rest_endpoint: /api/fmc_config/v1/domain/{DOMAIN_UUID}/object/hosts
-data_source_name_query: true
doc_category: Objects
attributes:
- model_name: name
@@ -9,6 +8,7 @@ attributes:
mandatory: true
description: The name of the host object.
example: HOST1
+ data_source_query: true
- model_name: type
type: String
description: Type of the object; this value is always 'Host'.
diff --git a/gen/definitions/hosts.yaml b/gen/definitions/hosts.yaml
index bcdc6a3d..eb10b7bb 100644
--- a/gen/definitions/hosts.yaml
+++ b/gen/definitions/hosts.yaml
@@ -7,8 +7,6 @@ res_description: >-
Updating/deleting `fmc_hosts` can thus take much more time than creating it
doc_category: Objects
is_bulk: true
-data_source_name_query: yes
-import_name_query: yes
minimum_version_bulk_delete: "7.4"
attributes:
- model_name: items
diff --git a/gen/definitions/icmpv4_object.yaml b/gen/definitions/icmpv4_object.yaml
index 1ca7020d..5443e4aa 100644
--- a/gen/definitions/icmpv4_object.yaml
+++ b/gen/definitions/icmpv4_object.yaml
@@ -1,7 +1,6 @@
---
name: ICMPv4 Object
rest_endpoint: /api/fmc_config/v1/domain/{DOMAIN_UUID}/object/icmpv4objects
-data_source_name_query: true
doc_category: Objects
attributes:
- model_name: icmpType
@@ -23,6 +22,7 @@ attributes:
description: User-created name of the resource.
mandatory: true
example: icmpv4_net_unreachable
+ data_source_query: true
- model_name: description
type: String
description: Optional description of the resource.
diff --git a/gen/definitions/icmpv4_objects.yaml b/gen/definitions/icmpv4_objects.yaml
index 19d44c8f..fd3e6d5a 100644
--- a/gen/definitions/icmpv4_objects.yaml
+++ b/gen/definitions/icmpv4_objects.yaml
@@ -7,8 +7,6 @@ res_description: >-
Updating/deleting `fmc_icmpv4_objects` can thus take much more time than creating it
doc_category: Objects
is_bulk: true
-data_source_name_query: yes
-import_name_query: yes
minimum_version_bulk_delete: "7.4"
attributes:
- model_name: items
diff --git a/gen/definitions/icmpv6_object.yaml b/gen/definitions/icmpv6_object.yaml
index e89232cb..dad8aa2c 100644
--- a/gen/definitions/icmpv6_object.yaml
+++ b/gen/definitions/icmpv6_object.yaml
@@ -1,7 +1,6 @@
---
name: ICMPv6 Object
rest_endpoint: /api/fmc_config/v1/domain/{DOMAIN_UUID}/object/icmpv6objects
-data_source_name_query: true
doc_category: Objects
attributes:
- model_name: icmpType
@@ -23,6 +22,7 @@ attributes:
description: User-created name of the resource.
mandatory: true
example: icmpv6_addr_unreachable
+ data_source_query: true
- model_name: description
type: String
description: Optional user-created description.
diff --git a/gen/definitions/interface_group.yaml b/gen/definitions/interface_group.yaml
index e590780f..2b7487c9 100644
--- a/gen/definitions/interface_group.yaml
+++ b/gen/definitions/interface_group.yaml
@@ -1,7 +1,6 @@
---
name: Interface Group
rest_endpoint: /api/fmc_config/v1/domain/{DOMAIN_UUID}/object/interfacegroups
-data_source_name_query: true
doc_category: Objects
test_tags: [TF_VAR_device_id]
attributes:
@@ -10,6 +9,7 @@ attributes:
description: User-created name of the object.
mandatory: true
example: interface_group_1
+ data_source_query: true
- model_name: interfaceMode
type: String
description: All interfaces' types must match the interface mode.
diff --git a/gen/definitions/intrusion_policy.yaml b/gen/definitions/intrusion_policy.yaml
index 52486419..e0f36264 100644
--- a/gen/definitions/intrusion_policy.yaml
+++ b/gen/definitions/intrusion_policy.yaml
@@ -1,7 +1,6 @@
---
name: Intrusion Policy
rest_endpoint: /api/fmc_config/v1/domain/{DOMAIN_UUID}/policy/intrusionpolicies
-data_source_name_query: true
doc_category: Policy
attributes:
- model_name: name
@@ -11,6 +10,7 @@ attributes:
or 'Security Over Connectivity'.
mandatory: true
example: ips_policy_1
+ data_source_query: true
- model_name: description
type: String
description: Optional description of the policy.
diff --git a/gen/definitions/network.yaml b/gen/definitions/network.yaml
index 9eeadec8..6063da76 100644
--- a/gen/definitions/network.yaml
+++ b/gen/definitions/network.yaml
@@ -1,7 +1,6 @@
---
name: Network
rest_endpoint: /api/fmc_config/v1/domain/{DOMAIN_UUID}/object/networks
-data_source_name_query: true
doc_category: Objects
attributes:
- model_name: name
@@ -9,11 +8,11 @@ attributes:
mandatory: true
description: The name of the network object.
example: NET1
+ data_source_query: true
- model_name: type
type: String
- description: Type of the object; this value is always 'Network'.
- default_value: Network
- requires_replace: true
+ description: "Type of the object; this value is always 'Network'."
+ computed: true
exclude_example: true
exclude_test: true
- model_name: description
diff --git a/gen/definitions/network_analysis_policy.yaml b/gen/definitions/network_analysis_policy.yaml
index 5b57cb2c..c4f5af1d 100644
--- a/gen/definitions/network_analysis_policy.yaml
+++ b/gen/definitions/network_analysis_policy.yaml
@@ -1,7 +1,6 @@
---
name: Network Analysis Policy
rest_endpoint: /api/fmc_config/v1/domain/{DOMAIN_UUID}/policy/networkanalysispolicies
-data_source_name_query: true
doc_category: Policy
attributes:
- model_name: name
@@ -11,6 +10,7 @@ attributes:
or 'Security Over Connectivity'.
mandatory: true
example: net_analysis_policy_1
+ data_source_query: true
- model_name: description
type: String
description: Optional description of the policy.
diff --git a/gen/definitions/networks.yaml b/gen/definitions/networks.yaml
index aa7a65a9..d33a53ff 100644
--- a/gen/definitions/networks.yaml
+++ b/gen/definitions/networks.yaml
@@ -7,8 +7,6 @@ res_description: >-
Updating/deleting `fmc_networks` can thus take much more time than creating it
doc_category: Objects
is_bulk: true
-data_source_name_query: yes
-import_name_query: yes
minimum_version_bulk_delete: "7.4"
attributes:
- model_name: items
@@ -43,6 +41,6 @@ attributes:
- model_name: type
type: String
description: Type of the object; this value is always 'Network'.
- default_value: Network
+ computed: true
exclude_example: true
exclude_test: true
\ No newline at end of file
diff --git a/gen/definitions/port.yaml b/gen/definitions/port.yaml
index 03cc531c..817d0d49 100644
--- a/gen/definitions/port.yaml
+++ b/gen/definitions/port.yaml
@@ -1,7 +1,6 @@
---
name: Port
rest_endpoint: /api/fmc_config/v1/domain/{DOMAIN_UUID}/object/protocolportobjects
-data_source_name_query: true
doc_category: Objects
attributes:
- model_name: port
@@ -14,6 +13,7 @@ attributes:
description: User-created name of the resource.
mandatory: true
example: tcp443
+ data_source_query: true
- model_name: protocol
type: String
description: >-
diff --git a/gen/definitions/port_group.yaml b/gen/definitions/port_group.yaml
index e15928b3..70c91ade 100644
--- a/gen/definitions/port_group.yaml
+++ b/gen/definitions/port_group.yaml
@@ -1,7 +1,6 @@
---
name: Port Group
rest_endpoint: /api/fmc_config/v1/domain/{DOMAIN_UUID}/object/portobjectgroups
-data_source_name_query: true
doc_category: Objects
attributes:
- model_name: name
@@ -9,11 +8,11 @@ attributes:
description: User-created name of the object.
mandatory: true
example: portgroup_obj1
+ data_source_query: true
- model_name: type
type: String
description: Type of the object; this value is always 'PortObjectGroup'.
- default_value: PortObjectGroup
- requires_replace: true
+ computed: true
exclude_example: true
exclude_test: true
- model_name: description
diff --git a/gen/definitions/port_groups.yaml b/gen/definitions/port_groups.yaml
index e0fbc061..f4aca4e5 100644
--- a/gen/definitions/port_groups.yaml
+++ b/gen/definitions/port_groups.yaml
@@ -6,8 +6,6 @@ res_description: >-
The FMC API supports quick bulk creation for this resource, but the deletion/modification is done one-by-one.
Updating and deleting `fmc_port_groups` can thus take much more time than creating it (even >500 times more time,
i.e. >50000%, depending on the change size).
-data_source_name_query: true
-import_name_query: yes
is_bulk: true
doc_category: Objects
minimum_version_bulk_delete: "7.4"
@@ -28,8 +26,7 @@ attributes:
- model_name: type
type: String
description: Type of the object; this value is always 'PortObjectGroup'.
- default_value: PortObjectGroup
- requires_replace: true
+ computed: true
exclude_example: true
exclude_test: true
- model_name: description
diff --git a/gen/definitions/ports.yaml b/gen/definitions/ports.yaml
index 8b7d1563..2eb1fd51 100644
--- a/gen/definitions/ports.yaml
+++ b/gen/definitions/ports.yaml
@@ -7,8 +7,6 @@ res_description: >-
Updating/deleting `fmc_ports` can thus take much more time than creating it
doc_category: Objects
is_bulk: true
-data_source_name_query: yes
-import_name_query: yes
minimum_version_bulk_delete: "7.4"
attributes:
- model_name: items
diff --git a/gen/definitions/range.yaml b/gen/definitions/range.yaml
index f117711a..c5c2321e 100644
--- a/gen/definitions/range.yaml
+++ b/gen/definitions/range.yaml
@@ -1,7 +1,6 @@
---
name: Range
rest_endpoint: /api/fmc_config/v1/domain/{DOMAIN_UUID}/object/ranges
-data_source_name_query: true
doc_category: Objects
attributes:
- model_name: name
@@ -9,6 +8,7 @@ attributes:
description: User-created name of the resource.
mandatory: true
example: range1
+ data_source_query: true
- model_name: value
tf_name: ip_range
type: String
diff --git a/gen/definitions/ranges.yaml b/gen/definitions/ranges.yaml
index 8d475049..54d927ea 100644
--- a/gen/definitions/ranges.yaml
+++ b/gen/definitions/ranges.yaml
@@ -7,8 +7,6 @@ res_description: >-
Updating/deleting `fmc_ranges` can thus take much more time than creating it
doc_category: Objects
is_bulk: true
-data_source_name_query: yes
-import_name_query: yes
minimum_version_bulk_delete: "7.4"
attributes:
- model_name: items
diff --git a/gen/definitions/security_zone.yaml b/gen/definitions/security_zone.yaml
index 25206fb4..da221355 100644
--- a/gen/definitions/security_zone.yaml
+++ b/gen/definitions/security_zone.yaml
@@ -2,14 +2,15 @@
name: Security Zone
rest_endpoint: /api/fmc_config/v1/domain/{DOMAIN_UUID}/object/securityzones
doc_category: Objects
-data_source_name_query: true
attributes:
- model_name: name
type: String
mandatory: true
description: User-provided resource name.
example: security_zone_1
+ data_source_query: true
- model_name: interfaceMode
+ tf_name: interface_type
type: String
mandatory: true
description: >-
@@ -17,10 +18,9 @@ attributes:
to mode NONE of associated interfaces.
enum_values: [PASSIVE, INLINE, SWITCHED, ROUTED, ASA]
example: ROUTED
- requires_replace: true
- model_name: type
type: String
description: Type of the object; this value is always 'SecurityZone'.
- default_value: SecurityZone
+ computed: true
exclude_example: true
exclude_test: true
\ No newline at end of file
diff --git a/gen/definitions/security_zones.yaml b/gen/definitions/security_zones.yaml
index 14217ea6..e0d9c9f5 100644
--- a/gen/definitions/security_zones.yaml
+++ b/gen/definitions/security_zones.yaml
@@ -2,8 +2,6 @@
name: Security Zones
rest_endpoint: /api/fmc_config/v1/domain/{DOMAIN_UUID}/object/securityzones
is_bulk: true
-data_source_name_query: true
-import_name_query: yes
res_description: >-
This plural resource manages a bulk of Security Zones.
The FMC API supports quick bulk creation of this resource. Deletion of this resource is done one-by-one or in bulk, depending of FMC version. Modification is always done one-by-one.
@@ -26,6 +24,7 @@ attributes:
exclude_example: true
exclude_test: true
- model_name: interfaceMode
+ tf_name: interface_type
type: String
mandatory: true
description: >-
@@ -33,10 +32,9 @@ attributes:
to mode NONE of associated interfaces.
enum_values: [PASSIVE, INLINE, SWITCHED, ROUTED, ASA]
example: ROUTED
- requires_replace: true
- model_name: type
type: String
description: Type of the object; this value is always 'SecurityZone'.
- default_value: SecurityZone
+ computed: true
exclude_example: true
exclude_test: true
\ No newline at end of file
diff --git a/gen/definitions/sgt.yaml b/gen/definitions/sgt.yaml
index f3181852..121394ea 100644
--- a/gen/definitions/sgt.yaml
+++ b/gen/definitions/sgt.yaml
@@ -1,7 +1,6 @@
---
name: SGT
rest_endpoint: /api/fmc_config/v1/domain/{DOMAIN_UUID}/object/securitygrouptags
-data_source_name_query: true
doc_category: Objects
minimum_version_create: "7.4"
attributes:
@@ -10,6 +9,7 @@ attributes:
mandatory: true
description: The name of the SGT object.
example: SGT1
+ data_source_query: true
- model_name: type
type: String
description: Type of the object; this value is always 'SecurityGroupTag'.
diff --git a/gen/definitions/sgts.yaml b/gen/definitions/sgts.yaml
index 6aa85102..1d8ab4bb 100644
--- a/gen/definitions/sgts.yaml
+++ b/gen/definitions/sgts.yaml
@@ -1,10 +1,8 @@
---
name: SGTs
rest_endpoint: /api/fmc_config/v1/domain/{DOMAIN_UUID}/object/securitygrouptags
-data_source_name_query: true
is_bulk: true
doc_category: Objects
-import_name_query: yes
minimum_version_create: "7.4"
minimum_version_bulk_create: "999"
minimum_version_bulk_delete: "999"
diff --git a/gen/definitions/snmp_alert.yaml b/gen/definitions/snmp_alert.yaml
index 98255921..379f9b37 100644
--- a/gen/definitions/snmp_alert.yaml
+++ b/gen/definitions/snmp_alert.yaml
@@ -1,7 +1,6 @@
---
name: SNMP Alert
rest_endpoint: /api/fmc_config/v1/domain/{DOMAIN_UUID}/policy/snmpalerts
-data_source_name_query: true
no_resource: true
no_import: true
doc_category: Policy
@@ -12,10 +11,10 @@ attributes:
Name of the SNMP Alert. There is no built-in SNMP alert.
mandatory: true
example: test_snmp_alert_1
+ data_source_query: true
- model_name: type
type: String
description: Type of the object; this value is always 'SNMPAlert'.
- default_value: SNMPAlert
- requires_replace: true
+ computed: true
exclude_example: true
exclude_test: true
diff --git a/gen/definitions/snmp_alerts.yaml b/gen/definitions/snmp_alerts.yaml
index b1fd1357..1b1fb390 100644
--- a/gen/definitions/snmp_alerts.yaml
+++ b/gen/definitions/snmp_alerts.yaml
@@ -1,8 +1,6 @@
---
name: SNMP Alerts
rest_endpoint: /api/fmc_config/v1/domain/{DOMAIN_UUID}/policy/snmpalerts
-data_source_name_query: true
-import_name_query: true
no_resource: true
no_import: true
is_bulk: true
@@ -24,7 +22,6 @@ attributes:
- model_name: type
type: String
description: Type of the object; this value is always 'SNMPAlert'.
- default_value: SNMPAlert
- requires_replace: true
+ computed: true
exclude_example: true
exclude_test: true
diff --git a/gen/definitions/standard_acl.yaml b/gen/definitions/standard_acl.yaml
index b4d24593..da5c33b2 100644
--- a/gen/definitions/standard_acl.yaml
+++ b/gen/definitions/standard_acl.yaml
@@ -1,7 +1,6 @@
---
name: Standard ACL
rest_endpoint: /api/fmc_config/v1/domain/{DOMAIN_UUID}/object/standardaccesslists
-data_source_name_query: true
doc_category: Objects
minimum_version_create: "7.2"
attributes:
@@ -10,6 +9,7 @@ attributes:
description: User-created name of the resource.
mandatory: true
example: stdacl1
+ data_source_query: true
- model_name: description
type: String
description: Optional user-created description.
diff --git a/gen/definitions/syslog_alert.yaml b/gen/definitions/syslog_alert.yaml
index 62ac9240..51aa7d35 100644
--- a/gen/definitions/syslog_alert.yaml
+++ b/gen/definitions/syslog_alert.yaml
@@ -1,7 +1,6 @@
---
name: Syslog Alert
rest_endpoint: /api/fmc_config/v1/domain/{DOMAIN_UUID}/policy/syslogalerts
-data_source_name_query: true
no_resource: true
no_import: true
doc_category: Policy
@@ -12,10 +11,10 @@ attributes:
Name of the Syslog Alert. There is no built-in Syslog alert.
mandatory: true
example: test_syslog_alert_1
+ data_source_query: true
- model_name: type
type: String
description: Type of the object; this value is always 'SyslogAlert'.
- default_value: SyslogAlert
- requires_replace: true
+ computed: true
exclude_example: true
exclude_test: true
diff --git a/gen/definitions/syslog_alerts.yaml b/gen/definitions/syslog_alerts.yaml
index daeb4dcb..9724a278 100644
--- a/gen/definitions/syslog_alerts.yaml
+++ b/gen/definitions/syslog_alerts.yaml
@@ -1,8 +1,6 @@
---
name: Syslog Alerts
rest_endpoint: /api/fmc_config/v1/domain/{DOMAIN_UUID}/policy/syslogalerts
-data_source_name_query: true
-import_name_query: true
no_resource: true
no_import: true
is_bulk: true
@@ -24,7 +22,6 @@ attributes:
- model_name: type
type: String
description: Type of the object; this value is always 'SyslogAlert'.
- default_value: SyslogAlert
- requires_replace: true
+ computed: true
exclude_example: true
exclude_test: true
diff --git a/gen/definitions/url.yaml b/gen/definitions/url.yaml
index b54b49f1..ae0ba1ec 100644
--- a/gen/definitions/url.yaml
+++ b/gen/definitions/url.yaml
@@ -1,7 +1,6 @@
---
name: URL
rest_endpoint: /api/fmc_config/v1/domain/{DOMAIN_UUID}/object/urls
-data_source_name_query: true
doc_category: Objects
attributes:
- model_name: name
@@ -9,6 +8,7 @@ attributes:
description: User-created name of the resource.
mandatory: true
example: url_1
+ data_source_query: true
- model_name: url
type: String
description: URL value.
diff --git a/gen/definitions/url_group.yaml b/gen/definitions/url_group.yaml
index 146e0bed..c69e7482 100644
--- a/gen/definitions/url_group.yaml
+++ b/gen/definitions/url_group.yaml
@@ -1,7 +1,6 @@
---
name: URL Group
rest_endpoint: /api/fmc_config/v1/domain/{DOMAIN_UUID}/object/urlgroups
-data_source_name_query: true
doc_category: Objects
attributes:
- model_name: name
@@ -9,6 +8,7 @@ attributes:
description: User-created name of the object.
mandatory: true
example: url_group_1
+ data_source_query: true
- model_name: description
type: String
description: Optional user-created description.
diff --git a/gen/definitions/url_groups.yaml b/gen/definitions/url_groups.yaml
index b1dbf824..19780039 100644
--- a/gen/definitions/url_groups.yaml
+++ b/gen/definitions/url_groups.yaml
@@ -6,8 +6,6 @@ res_description: >-
The FMC API supports quick bulk creation for this resource, but the deletion/modification is done one-by-one.
Updating and deleting `fmc_url_groups` can thus take much more time than creating it (even >500 times more time,
i.e. >50000%, depending on the change size).
-data_source_name_query: true
-import_name_query: yes
is_bulk: true
doc_category: Objects
minimum_version_bulk_delete: "7.4"
diff --git a/gen/definitions/urls.yaml b/gen/definitions/urls.yaml
index ff5045f1..40b110fe 100644
--- a/gen/definitions/urls.yaml
+++ b/gen/definitions/urls.yaml
@@ -2,8 +2,6 @@
name: URLs
rest_endpoint: /api/fmc_config/v1/domain/{DOMAIN_UUID}/object/urls
is_bulk: true
-data_source_name_query: true
-import_name_query: yes
res_description: >-
This plural resource manages a bulk of URL objects.
The FMC API supports quick bulk creation of this resource. Deletion of this resource is done one-by-one or in bulk, depending of FMC version. Modification is always done one-by-one.
diff --git a/gen/definitions/variable_set.yaml b/gen/definitions/variable_set.yaml
index 0afc7f78..83cfdafd 100644
--- a/gen/definitions/variable_set.yaml
+++ b/gen/definitions/variable_set.yaml
@@ -1,7 +1,6 @@
---
name: Variable Set
rest_endpoint: /api/fmc_config/v1/domain/{DOMAIN_UUID}/object/variablesets
-data_source_name_query: true
no_resource: true
no_import: true
doc_category: Objects
@@ -12,6 +11,7 @@ attributes:
Name of the Variable Set. Names for built-in set is 'Default-Set'.
mandatory: true
example: test_variable_set_1
+ data_source_query: true
- model_name: description
type: String
description: Optional description of the policy.
@@ -19,7 +19,6 @@ attributes:
- model_name: type
type: String
description: Type of the object; this value is always 'VariableSet'.
- default_value: VariableSet
- requires_replace: true
+ computed: true
exclude_example: true
exclude_test: true
diff --git a/gen/definitions/vlan_tag.yaml b/gen/definitions/vlan_tag.yaml
index a4f9636f..d5a7f0a3 100644
--- a/gen/definitions/vlan_tag.yaml
+++ b/gen/definitions/vlan_tag.yaml
@@ -1,7 +1,6 @@
---
name: VLAN Tag
rest_endpoint: /api/fmc_config/v1/domain/{DOMAIN_UUID}/object/vlantags
-data_source_name_query: true
doc_category: Objects
attributes:
- model_name: name
@@ -9,6 +8,7 @@ attributes:
description: User-created name of the resource.
mandatory: true
example: vlan_tag_1
+ data_source_query: true
- model_name: description
type: String
description: Optional user-created description.
diff --git a/gen/definitions/vlan_tag_group.yaml b/gen/definitions/vlan_tag_group.yaml
index 4a762e7b..26aa1f93 100644
--- a/gen/definitions/vlan_tag_group.yaml
+++ b/gen/definitions/vlan_tag_group.yaml
@@ -1,7 +1,6 @@
---
name: VLAN Tag Group
rest_endpoint: /api/fmc_config/v1/domain/{DOMAIN_UUID}/object/vlangrouptags
-data_source_name_query: true
doc_category: Objects
attributes:
- model_name: name
@@ -9,6 +8,7 @@ attributes:
description: User-created name of the object.
mandatory: true
example: vlan_tag_group_1
+ data_source_query: true
- model_name: description
type: String
description: Optional user-created description.
diff --git a/gen/definitions/vlan_tag_groups.yaml b/gen/definitions/vlan_tag_groups.yaml
index 43a4b450..e3e3e3e1 100644
--- a/gen/definitions/vlan_tag_groups.yaml
+++ b/gen/definitions/vlan_tag_groups.yaml
@@ -6,8 +6,6 @@ res_description: >-
The FMC API supports quick bulk creation for this resource, but the deletion/modification is done one-by-one.
Updating and deleting `fmc_vlan_tag_groups` can thus take much more time than creating it (even >500 times more time,
i.e. >50000%, depending on the change size).
-data_source_name_query: true
-import_name_query: yes
is_bulk: true
doc_category: Objects
minimum_version_bulk_delete: "7.4"
diff --git a/gen/definitions/vlan_tags.yaml b/gen/definitions/vlan_tags.yaml
index 78b52a67..d2714937 100644
--- a/gen/definitions/vlan_tags.yaml
+++ b/gen/definitions/vlan_tags.yaml
@@ -2,8 +2,6 @@
name: VLAN Tags
rest_endpoint: /api/fmc_config/v1/domain/{DOMAIN_UUID}/object/vlantags
is_bulk: true
-data_source_name_query: true
-import_name_query: yes
res_description: >-
This plural resource manages a bulk of VLAN tags.
The FMC API supports quick bulk creation of this resource. Deletion of this resource is done one-by-one or in bulk, depending of FMC version. Modification is always done one-by-one.
diff --git a/gen/generator.go b/gen/generator.go
index d3666f3c..c7abf2ab 100644
--- a/gen/generator.go
+++ b/gen/generator.go
@@ -103,7 +103,6 @@ type YamlConfig struct {
PutCreate bool `yaml:"put_create"`
NoUpdate bool `yaml:"no_update"`
NoDelete bool `yaml:"no_delete"`
- DataSourceNameQuery bool `yaml:"data_source_name_query"`
MinimumVersion string `yaml:"minimum_version"`
MinimumVersionCreate string `yaml:"minimum_version_create"`
MinimumVersionBulkCreate string `yaml:"minimum_version_bulk_create"`
@@ -155,6 +154,7 @@ type YamlConfigAttribute struct {
TestValue string `yaml:"test_value"`
MinimumTestValue string `yaml:"minimum_test_value"`
TestTags []string `yaml:"test_tags"`
+ DataSourceQuery bool `yaml:"data_source_query"`
Attributes []YamlConfigAttribute `yaml:"attributes"`
GoTypeName string
}
@@ -217,6 +217,26 @@ func contains(s []string, str string) bool {
return false
}
+// Templating helper function to check if any of the attributes is a data source query
+func HasDataSourceQuery(attributes []YamlConfigAttribute) bool {
+ for _, attr := range attributes {
+ if attr.DataSourceQuery {
+ return true
+ }
+ }
+ return false
+}
+
+// Templating helper function to return Data Source Query Attribute
+func GetDataSourceQueryAttribute(config YamlConfig) YamlConfigAttribute {
+ for _, attr := range config.Attributes {
+ if attr.DataSourceQuery {
+ return attr
+ }
+ }
+ return YamlConfigAttribute{}
+}
+
// Templating helper function to return true if id included in attributes
func HasId(attributes []YamlConfigAttribute) bool {
for _, attr := range attributes {
@@ -352,28 +372,30 @@ func Subtract(a, b int) int {
// Map of templating functions
var functions = template.FuncMap{
- "toGoName": ToGoName,
- "camelCase": CamelCase,
- "snakeCase": SnakeCase,
- "sprintf": fmt.Sprintf,
- "errorf": Errorf,
- "toLower": strings.ToLower,
- "path": BuildPath,
- "hasId": HasId,
- "hasReference": HasReference,
- "hasResourceId": HasResourceId,
- "isListSet": IsListSet,
- "isList": IsList,
- "isSet": IsSet,
- "isStringListSet": IsStringListSet,
- "isInt64ListSet": IsInt64ListSet,
- "isNestedListMapSet": IsNestedListMapSet,
- "isNestedListSet": IsNestedListSet,
- "isNestedList": IsNestedList,
- "isNestedMap": IsNestedMap,
- "isNestedSet": IsNestedSet,
- "importParts": ImportParts,
- "subtract": Subtract,
+ "toGoName": ToGoName,
+ "camelCase": CamelCase,
+ "snakeCase": SnakeCase,
+ "sprintf": fmt.Sprintf,
+ "errorf": Errorf,
+ "toLower": strings.ToLower,
+ "path": BuildPath,
+ "hasDataSourceQuery": HasDataSourceQuery,
+ "getDataSourceQueryAttribute": GetDataSourceQueryAttribute,
+ "hasId": HasId,
+ "hasReference": HasReference,
+ "hasResourceId": HasResourceId,
+ "isListSet": IsListSet,
+ "isList": IsList,
+ "isSet": IsSet,
+ "isStringListSet": IsStringListSet,
+ "isInt64ListSet": IsInt64ListSet,
+ "isNestedListMapSet": IsNestedListMapSet,
+ "isNestedListSet": IsNestedListSet,
+ "isNestedList": IsNestedList,
+ "isNestedMap": IsNestedMap,
+ "isNestedSet": IsNestedSet,
+ "importParts": ImportParts,
+ "subtract": Subtract,
}
func (attr *YamlConfigAttribute) init(parentGoTypeName string) error {
@@ -435,6 +457,7 @@ func (attr *YamlConfigAttribute) init(parentGoTypeName string) error {
func NewYamlConfig(bytes []byte) (YamlConfig, error) {
var config YamlConfig
+ var hasDataSourceQuery bool = false
if err := yaml.Unmarshal(bytes, &config); err != nil {
return config, err
@@ -444,6 +467,12 @@ func NewYamlConfig(bytes []byte) (YamlConfig, error) {
if err := config.Attributes[i].init(CamelCase(config.Name)); err != nil {
return YamlConfig{}, err
}
+ if config.Attributes[i].DataSourceQuery {
+ if hasDataSourceQuery {
+ return YamlConfig{}, fmt.Errorf("Multiple `data_source_query` attributes found. Only one is allowed.")
+ }
+ hasDataSourceQuery = true
+ }
}
if config.DsDescription == "" {
config.DsDescription = fmt.Sprintf("This data source can read the %s.", config.Name)
diff --git a/gen/schema/schema.yaml b/gen/schema/schema.yaml
index 039b0e80..4000a4b9 100644
--- a/gen/schema/schema.yaml
+++ b/gen/schema/schema.yaml
@@ -7,7 +7,6 @@ rest_endpoint: str(required=False) # REST endpoint path
put_create: bool(required=False) # Set to true if the PUT request is used for create
no_update: bool(required=False) # Set to true if the PUT request is not supported
no_delete: bool(required=False) # Set to true if the DELETE request is not supported
-data_source_name_query: bool(required=False) # Set to true if the data source supports name queries
minimum_version: str(required=False) # Define a minimum supported version
minimum_version_create: str(required=False) # Define a minimum version that supports create (in case it's higher than `minimum_version`)
minimum_version_bulk_create: str(required=False) # Define a minimum version that supports bulk create (in case it's higher than `minimum_version`). Please use version "999" if not supported (fallback to one-by-one create)
@@ -57,5 +56,6 @@ attribute:
test_value: str(required=False) # Value used for acceptance test
minimum_test_value: str(required=False) # Value used for "minimum" resource acceptance test
test_tags: list(str(), required=False) # List of test tags, attribute is only included in acceptance tests if an environment variable with one of these tags is configured
+ data_source_query: bool(required=False) # Set to true if the attribute can be used in the data source query. This is supported only for top-level attributes.
attributes: list(include('attribute'), required=False) # List of attributes, only relevant if type is "List" or "Set"
\ No newline at end of file
diff --git a/gen/templates/data_source.go b/gen/templates/data_source.go
index 620b340f..67ba745e 100644
--- a/gen/templates/data_source.go
+++ b/gen/templates/data_source.go
@@ -56,8 +56,6 @@ func (d *{{camelCase .Name}}DataSource) Metadata(_ context.Context, req datasour
resp.TypeName = req.ProviderTypeName + "_{{snakeCase .Name}}"
}
-{{- $nameQuery := .DataSourceNameQuery}}
-
func (d *{{camelCase .Name}}DataSource) 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.
@@ -66,7 +64,7 @@ func (d *{{camelCase .Name}}DataSource) Schema(ctx context.Context, req datasour
Attributes: map[string]schema.Attribute{
"id": schema.StringAttribute{
MarkdownDescription: "The id of the object",
- {{- if not .DataSourceNameQuery}}
+ {{- if and (not (hasDataSourceQuery .Attributes)) (not .IsBulk) }}
Required: true,
{{- else}}
{{- if not .IsBulk}}
@@ -89,7 +87,7 @@ func (d *{{camelCase .Name}}DataSource) Schema(ctx context.Context, req datasour
{{- if .Reference}}
Required: true,
{{- else}}
- {{- if and (eq .ModelName "name") ($nameQuery)}}
+ {{- if .DataSourceQuery }}
Optional: true,
{{- end}}
{{- if isNestedMap .}}
@@ -159,13 +157,13 @@ func (d *{{camelCase .Name}}DataSource) Schema(ctx context.Context, req datasour
},
}
}
-
-{{- if and .DataSourceNameQuery (not .IsBulk)}}
+{{- $dataSourceAttribute := getDataSourceQueryAttribute .}}
+{{- if and (hasDataSourceQuery .Attributes) (not .IsBulk)}}
func (d *{{camelCase .Name}}DataSource) ConfigValidators(ctx context.Context) []datasource.ConfigValidator {
return []datasource.ConfigValidator{
datasourcevalidator.ExactlyOneOf(
path.MatchRoot("id"),
- path.MatchRoot("name"),
+ path.MatchRoot("{{$dataSourceAttribute.TfName}}"),
),
}
}
@@ -211,12 +209,12 @@ func (d *{{camelCase .Name}}DataSource) Read(ctx context.Context, req datasource
tflog.Debug(ctx, fmt.Sprintf("%s: Beginning Read", config.Id.String()))
- {{- if and .DataSourceNameQuery (not .IsBulk)}}
- if config.Id.IsNull() && !config.Name.IsNull() {
+ {{- if and (hasDataSourceQuery .Attributes) (not .IsBulk)}}
+ if config.Id.IsNull() && !config.{{toGoName $dataSourceAttribute.TfName}}.IsNull() {
offset := 0
limit := 1000
for page := 1; ; page++ {
- queryString := fmt.Sprintf("?limit=%d&offset=%d", limit, offset)
+ queryString := fmt.Sprintf("?limit=%d&offset=%d&expanded=true", limit, offset)
res, err := d.client.Get(config.getPath() + queryString, reqMods...)
if err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to retrieve objects, got error: %s", err))
@@ -224,9 +222,9 @@ func (d *{{camelCase .Name}}DataSource) Read(ctx context.Context, req datasource
}
if value := res.Get("items"); len(value.Array()) > 0 {
value.ForEach(func(k, v gjson.Result) bool {
- if config.Name.ValueString() == v.Get("name").String() {
+ if config.{{toGoName $dataSourceAttribute.TfName}}.ValueString() == v.Get("{{$dataSourceAttribute.ModelName}}").String() {
config.Id = types.StringValue(v.Get("id").String())
- tflog.Debug(ctx, fmt.Sprintf("%s: Found object with name '%v', id: %v", config.Id.String(), config.Name.ValueString(), config.Id.String()))
+ tflog.Debug(ctx, fmt.Sprintf("%s: Found object with {{$dataSourceAttribute.TfName}} '%v', id: %v", config.Id.String(), config.{{toGoName $dataSourceAttribute.TfName}}.ValueString(), config.Id.String()))
return false
}
return true
@@ -239,7 +237,7 @@ func (d *{{camelCase .Name}}DataSource) Read(ctx context.Context, req datasource
}
if config.Id.IsNull() {
- resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to find object with name: %s", config.Name.ValueString()))
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to find object with {{$dataSourceAttribute.TfName}}: %s", config.{{toGoName $dataSourceAttribute.TfName}}.ValueString()))
return
}
}
diff --git a/gen/templates/data_source_test.go b/gen/templates/data_source_test.go
index 852d9164..5f33e37a 100644
--- a/gen/templates/data_source_test.go
+++ b/gen/templates/data_source_test.go
@@ -146,7 +146,7 @@ func TestAccDataSourceFmc{{camelCase .Name}}(t *testing.T) {
Config: {{if .TestPrerequisites}}testAccDataSourceFmc{{camelCase .Name}}PrerequisitesConfig+{{end}}testAccDataSourceFmc{{camelCase .Name}}Config(),
Check: resource.ComposeTestCheckFunc(checks...),
},
- {{- if and .DataSourceNameQuery (not .IsBulk)}}
+ {{- if and (hasDataSourceQuery .Attributes) (not .IsBulk)}}
{
Config: {{if .TestPrerequisites}}testAccDataSourceFmc{{camelCase .Name}}PrerequisitesConfig+{{end}}testAccNamedDataSourceFmc{{camelCase .Name}}Config(),
Check: resource.ComposeTestCheckFunc(checks...),
@@ -288,7 +288,7 @@ func testAccDataSourceFmc{{camelCase .Name}}Config() string {
return config
}
-{{if and .DataSourceNameQuery (not .IsBulk) -}}
+{{if and (hasDataSourceQuery .Attributes) (not .IsBulk) -}}
func testAccNamedDataSourceFmc{{camelCase .Name}}Config() string {
config := `resource "fmc_{{snakeCase $name}}" "test" {` + "\n"
{{- range .Attributes}}
@@ -376,12 +376,16 @@ func testAccNamedDataSourceFmc{{camelCase .Name}}Config() string {
config += `
data "fmc_{{snakeCase .Name}}" "test" {
- name = fmc_{{snakeCase $name}}.test.name
{{- range .Attributes}}
{{- if .Reference}}
{{.TfName}} = {{if .TestValue}}{{.TestValue}}{{else}}{{if eq .Type "String"}}"{{.Example}}"{{else if isStringListSet .}}["{{.Example}}"]{{else if isInt64ListSet .}}[{{.Example}}]{{else}}{{.Example}}{{end}}{{end}}
{{- end}}
{{- end}}
+ {{- range .Attributes}}
+ {{- if .DataSourceQuery}}
+ {{.TfName}} = fmc_{{snakeCase $name}}.test.{{.TfName}}
+ {{- end}}
+ {{- end}}
}
`
return config
diff --git a/gen/templates/import.sh b/gen/templates/import.sh
index f6d0459c..d3959903 100644
--- a/gen/templates/import.sh
+++ b/gen/templates/import.sh
@@ -1,5 +1,5 @@
{{- if .IsBulk -}}
-terraform import fmc_{{snakeCase .Name}}.example ",[<{{snakeCase .Name}}{{if .ImportNameQuery}}_name{{else}}_id{{end}}>]"
+terraform import fmc_{{snakeCase .Name}}.example ",[<{{snakeCase .Name}}_name>]"
{{- else -}}
terraform import fmc_{{snakeCase .Name}}.example "{{$id := false}}{{range .Attributes}}{{if .Id}}{{$id = true}}<{{.TfName}}>{{end}}{{end}}{{if not $id}}{{range .Attributes}}{{if .Reference}}<{{.TfName}}>,{{end}}{{end}}{{end}}"
{{- end}}
\ No newline at end of file
diff --git a/gen/templates/model.go b/gen/templates/model.go
index e29082c8..fd760e18 100644
--- a/gen/templates/model.go
+++ b/gen/templates/model.go
@@ -301,7 +301,7 @@ func (data *{{camelCase .Name}}) fromBody(ctx context.Context, res gjson.Result)
parentRes.{{if .ModelName}}Get("{{range .DataPath}}{{.}}.{{end}}{{.ModelName}}").{{end}}ForEach(
func(_, v gjson.Result) bool {
- {{- if $.ImportNameQuery -}}
+ {{- if or $.ImportNameQuery $.IsBulk -}}
if v.Get("name").String() == k {
{{- else -}}
if v.Get("id").String() == data.Id.ValueString() && data.Id.ValueString() != "" {
@@ -313,7 +313,7 @@ func (data *{{camelCase .Name}}) fromBody(ctx context.Context, res gjson.Result)
},
)
if !res.Exists() {
- {{- if $.ImportNameQuery -}}
+ {{- if or $.ImportNameQuery $.IsBulk -}}
tflog.Debug(ctx, fmt.Sprintf("subresource not found, removing: name=%v", k))
{{- else -}}
tflog.Debug(ctx, fmt.Sprintf("subresource not found, removing: uuid=%s, key=%v", data.Id, k))
diff --git a/gen/templates/resource.go b/gen/templates/resource.go
index eaac77ec..0f4a4ef1 100644
--- a/gen/templates/resource.go
+++ b/gen/templates/resource.go
@@ -471,13 +471,21 @@ func (r *{{camelCase .Name}}Resource) Create(ctx context.Context, req resource.C
}
{{- if and .PutCreate (not .IsBulk)}}
- tflog.Debug(ctx, fmt.Sprintf("%s: considering object name %s", plan.Id, plan.Name))
- if plan.Id.ValueString() == "" && plan.Name.ValueString() != "" {
+ {{- $attrTfName := "name" }}
+ {{- $attrModelName := "name" }}
+ {{- if hasDataSourceQuery .Attributes}}
+ {{- $attr := getDataSourceQueryAttribute . }}
+ {{- $attrTfName = $attr.TfName }}
+ {{- $attrModelName = $attr.ModelName }}
+ {{- end}}
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: considering object {{$attrTfName}} %s", plan.Id, plan.{{toGoName $attrTfName}}))
+ if plan.Id.ValueString() == "" && plan.{{toGoName $attrTfName}}.ValueString() != "" {
offset := 0
limit := 1000
for page := 1; ; page++ {
- queryString := fmt.Sprintf("?limit=%d&offset=%d", limit, offset)
+ queryString := fmt.Sprintf("?limit=%d&offset=%d&expanded=true", limit, offset)
res, err := r.client.Get(plan.getPath()+queryString, reqMods...)
if err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to retrieve objects, got error: %s", err))
@@ -485,9 +493,9 @@ func (r *{{camelCase .Name}}Resource) Create(ctx context.Context, req resource.C
}
if value := res.Get("items"); len(value.Array()) > 0 {
value.ForEach(func(k, v gjson.Result) bool {
- if plan.Name.ValueString() == v.Get("name").String() {
+ if plan.{{toGoName $attrTfName}}.ValueString() == v.Get("{{$attrModelName}}").String() {
plan.Id = types.StringValue(v.Get("id").String())
- tflog.Debug(ctx, fmt.Sprintf("%s: Found object with name '%s', id: %s", plan.Id, plan.Name.ValueString(), plan.Id))
+ tflog.Debug(ctx, fmt.Sprintf("%s: Found object with {{$attrTfName}} '%s', id: %s", plan.Id, plan.{{toGoName $attrTfName}}.ValueString(), plan.Id))
return false
}
return true
@@ -500,7 +508,7 @@ func (r *{{camelCase .Name}}Resource) Create(ctx context.Context, req resource.C
}
if plan.Id.ValueString() == "" {
- resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to find object with name: %s", plan.Name.ValueString()))
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to find object with {{$attrTfName}}: %s", plan.{{toGoName $attrTfName}}.ValueString()))
return
}
}
diff --git a/internal/provider/data_source_fmc_bfd_template.go b/internal/provider/data_source_fmc_bfd_template.go
new file mode 100644
index 00000000..133967dd
--- /dev/null
+++ b/internal/provider/data_source_fmc_bfd_template.go
@@ -0,0 +1,205 @@
+// Copyright © 2023 Cisco Systems, Inc. and its affiliates.
+// All rights reserved.
+//
+// Licensed under the Mozilla Public License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://mozilla.org/MPL/2.0/
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// SPDX-License-Identifier: MPL-2.0
+
+package provider
+
+// Section below is generated&owned by "gen/generator.go". //template:begin imports
+import (
+ "context"
+ "fmt"
+ "net/url"
+
+ "github.com/hashicorp/terraform-plugin-framework-validators/datasourcevalidator"
+ "github.com/hashicorp/terraform-plugin-framework/datasource"
+ "github.com/hashicorp/terraform-plugin-framework/datasource/schema"
+ "github.com/hashicorp/terraform-plugin-framework/path"
+ "github.com/hashicorp/terraform-plugin-framework/types"
+ "github.com/hashicorp/terraform-plugin-log/tflog"
+ "github.com/netascode/go-fmc"
+ "github.com/tidwall/gjson"
+)
+
+// End of section. //template:end imports
+
+// Section below is generated&owned by "gen/generator.go". //template:begin model
+
+// Ensure the implementation satisfies the expected interfaces.
+var (
+ _ datasource.DataSource = &BFDTemplateDataSource{}
+ _ datasource.DataSourceWithConfigure = &BFDTemplateDataSource{}
+)
+
+func NewBFDTemplateDataSource() datasource.DataSource {
+ return &BFDTemplateDataSource{}
+}
+
+type BFDTemplateDataSource struct {
+ client *fmc.Client
+}
+
+func (d *BFDTemplateDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
+ resp.TypeName = req.ProviderTypeName + "_bfd_template"
+}
+
+func (d *BFDTemplateDataSource) 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 Template.",
+
+ Attributes: map[string]schema.Attribute{
+ "id": schema.StringAttribute{
+ MarkdownDescription: "The id of the object",
+ Optional: true,
+ Computed: true,
+ },
+ "domain": schema.StringAttribute{
+ MarkdownDescription: "The name of the FMC domain",
+ Optional: true,
+ },
+ "name": schema.StringAttribute{
+ MarkdownDescription: "The name of the bfd template object.",
+ Optional: true,
+ Computed: true,
+ },
+ "type": schema.StringAttribute{
+ MarkdownDescription: "Type of the object; this value is always 'BFDTemplate'.",
+ Computed: true,
+ },
+ "hop_type": schema.StringAttribute{
+ MarkdownDescription: "The hop type.",
+ Computed: true,
+ },
+ "echo": schema.StringAttribute{
+ MarkdownDescription: "Enables/disables BFD echo.",
+ Computed: true,
+ },
+ "interval_time": schema.StringAttribute{
+ MarkdownDescription: "Interval unit of measurement of time.",
+ Computed: true,
+ },
+ "min_transmit": schema.Int64Attribute{
+ MarkdownDescription: "BFD Minimum Transmit unit value.",
+ Computed: true,
+ },
+ "tx_rx_multiplier": schema.Int64Attribute{
+ MarkdownDescription: "BFD Multipler value.",
+ Computed: true,
+ },
+ "min_receive": schema.Int64Attribute{
+ MarkdownDescription: "BFD Minimum Receive unit value in ranges: 50-999 miliseconds, 50000-999000 microseconds",
+ Computed: true,
+ },
+ "authentication_password": schema.StringAttribute{
+ MarkdownDescription: "Password for BFD Authentication (1-24 characters)",
+ Computed: true,
+ },
+ "authentication_key_id": schema.Int64Attribute{
+ MarkdownDescription: "Authentication Key ID",
+ Computed: true,
+ },
+ "authentication_type": schema.StringAttribute{
+ MarkdownDescription: "Authentication types",
+ Computed: true,
+ },
+ },
+ }
+}
+func (d *BFDTemplateDataSource) ConfigValidators(ctx context.Context) []datasource.ConfigValidator {
+ return []datasource.ConfigValidator{
+ datasourcevalidator.ExactlyOneOf(
+ path.MatchRoot("id"),
+ path.MatchRoot("name"),
+ ),
+ }
+}
+
+func (d *BFDTemplateDataSource) Configure(_ context.Context, req datasource.ConfigureRequest, _ *datasource.ConfigureResponse) {
+ if req.ProviderData == nil {
+ return
+ }
+
+ d.client = req.ProviderData.(*FmcProviderData).Client
+}
+
+// End of section. //template:end model
+
+// Section below is generated&owned by "gen/generator.go". //template:begin read
+
+func (d *BFDTemplateDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
+ var config BFDTemplate
+
+ // Read config
+ diags := req.Config.Get(ctx, &config)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ // Set request domain if provided
+ reqMods := [](func(*fmc.Req)){}
+ if !config.Domain.IsNull() && config.Domain.ValueString() != "" {
+ reqMods = append(reqMods, fmc.DomainName(config.Domain.ValueString()))
+ }
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Beginning Read", config.Id.String()))
+ if config.Id.IsNull() && !config.Name.IsNull() {
+ offset := 0
+ limit := 1000
+ for page := 1; ; page++ {
+ queryString := fmt.Sprintf("?limit=%d&offset=%d&expanded=true", limit, offset)
+ res, err := d.client.Get(config.getPath()+queryString, reqMods...)
+ if err != nil {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to retrieve objects, got error: %s", err))
+ return
+ }
+ if value := res.Get("items"); len(value.Array()) > 0 {
+ value.ForEach(func(k, v gjson.Result) bool {
+ if config.Name.ValueString() == v.Get("name").String() {
+ config.Id = types.StringValue(v.Get("id").String())
+ tflog.Debug(ctx, fmt.Sprintf("%s: Found object with name '%v', id: %v", config.Id.String(), config.Name.ValueString(), config.Id.String()))
+ return false
+ }
+ return true
+ })
+ }
+ if !config.Id.IsNull() || !res.Get("paging.next.0").Exists() {
+ break
+ }
+ offset += limit
+ }
+
+ if config.Id.IsNull() {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to find object with name: %s", config.Name.ValueString()))
+ return
+ }
+ }
+ urlPath := config.getPath() + "/" + url.QueryEscape(config.Id.ValueString())
+ res, err := d.client.Get(urlPath, reqMods...)
+ if err != nil {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to retrieve object, got error: %s", err))
+ return
+ }
+
+ config.fromBody(ctx, res)
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Read finished successfully", config.Id.ValueString()))
+
+ diags = resp.State.Set(ctx, &config)
+ resp.Diagnostics.Append(diags...)
+}
+
+// End of section. //template:end read
diff --git a/internal/provider/data_source_fmc_bfd_template_test.go b/internal/provider/data_source_fmc_bfd_template_test.go
new file mode 100644
index 00000000..e8e8259e
--- /dev/null
+++ b/internal/provider/data_source_fmc_bfd_template_test.go
@@ -0,0 +1,112 @@
+// Copyright © 2023 Cisco Systems, Inc. and its affiliates.
+// All rights reserved.
+//
+// Licensed under the Mozilla Public License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://mozilla.org/MPL/2.0/
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// SPDX-License-Identifier: MPL-2.0
+
+package provider
+
+// Section below is generated&owned by "gen/generator.go". //template:begin imports
+import (
+ "testing"
+
+ "github.com/hashicorp/terraform-plugin-testing/helper/resource"
+)
+
+// End of section. //template:end imports
+
+// Section below is generated&owned by "gen/generator.go". //template:begin testAccDataSource
+
+func TestAccDataSourceFmcBFDTemplate(t *testing.T) {
+ var checks []resource.TestCheckFunc
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_bfd_template.test", "name", "BFD_Template1"))
+ checks = append(checks, resource.TestCheckResourceAttrSet("data.fmc_bfd_template.test", "type"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_bfd_template.test", "hop_type", "SINGLE_HOP"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_bfd_template.test", "echo", "ENABLED"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_bfd_template.test", "interval_time", "MILLISECONDS"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_bfd_template.test", "min_transmit", "300"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_bfd_template.test", "tx_rx_multiplier", "3"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_bfd_template.test", "min_receive", "300"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_bfd_template.test", "authentication_password", "Cisco123!"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_bfd_template.test", "authentication_key_id", "1"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_bfd_template.test", "authentication_type", "MD5"))
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { testAccPreCheck(t) },
+ ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
+ ErrorCheck: func(err error) error { return testAccErrorCheck(t, err) },
+ Steps: []resource.TestStep{
+ {
+ Config: testAccDataSourceFmcBFDTemplateConfig(),
+ Check: resource.ComposeTestCheckFunc(checks...),
+ },
+ {
+ Config: testAccNamedDataSourceFmcBFDTemplateConfig(),
+ Check: resource.ComposeTestCheckFunc(checks...),
+ },
+ },
+ })
+}
+
+// End of section. //template:end testAccDataSource
+
+// Section below is generated&owned by "gen/generator.go". //template:begin testPrerequisites
+// End of section. //template:end testPrerequisites
+
+// Section below is generated&owned by "gen/generator.go". //template:begin testAccDataSourceConfig
+
+func testAccDataSourceFmcBFDTemplateConfig() string {
+ config := `resource "fmc_bfd_template" "test" {` + "\n"
+ config += ` name = "BFD_Template1"` + "\n"
+ config += ` hop_type = "SINGLE_HOP"` + "\n"
+ config += ` echo = "ENABLED"` + "\n"
+ config += ` interval_time = "MILLISECONDS"` + "\n"
+ config += ` min_transmit = 300` + "\n"
+ config += ` tx_rx_multiplier = 3` + "\n"
+ config += ` min_receive = 300` + "\n"
+ config += ` authentication_password = "Cisco123!"` + "\n"
+ config += ` authentication_key_id = 1` + "\n"
+ config += ` authentication_type = "MD5"` + "\n"
+ config += `}` + "\n"
+
+ config += `
+ data "fmc_bfd_template" "test" {
+ id = fmc_bfd_template.test.id
+ }
+ `
+ return config
+}
+
+func testAccNamedDataSourceFmcBFDTemplateConfig() string {
+ config := `resource "fmc_bfd_template" "test" {` + "\n"
+ config += ` name = "BFD_Template1"` + "\n"
+ config += ` hop_type = "SINGLE_HOP"` + "\n"
+ config += ` echo = "ENABLED"` + "\n"
+ config += ` interval_time = "MILLISECONDS"` + "\n"
+ config += ` min_transmit = 300` + "\n"
+ config += ` tx_rx_multiplier = 3` + "\n"
+ config += ` min_receive = 300` + "\n"
+ config += ` authentication_password = "Cisco123!"` + "\n"
+ config += ` authentication_key_id = 1` + "\n"
+ config += ` authentication_type = "MD5"` + "\n"
+ config += `}` + "\n"
+
+ config += `
+ data "fmc_bfd_template" "test" {
+ name = fmc_bfd_template.test.name
+ }
+ `
+ return config
+}
+
+// End of section. //template:end testAccDataSourceConfig
diff --git a/internal/provider/data_source_fmc_bgd_template.go b/internal/provider/data_source_fmc_bgd_template.go
new file mode 100644
index 00000000..1704ea8e
--- /dev/null
+++ b/internal/provider/data_source_fmc_bgd_template.go
@@ -0,0 +1,193 @@
+// Copyright © 2023 Cisco Systems, Inc. and its affiliates.
+// All rights reserved.
+//
+// Licensed under the Mozilla Public License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://mozilla.org/MPL/2.0/
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// SPDX-License-Identifier: MPL-2.0
+
+package provider
+
+// Section below is generated&owned by "gen/generator.go". //template:begin imports
+import (
+ "context"
+ "fmt"
+ "net/url"
+
+ "github.com/hashicorp/terraform-plugin-framework-validators/datasourcevalidator"
+ "github.com/hashicorp/terraform-plugin-framework/datasource"
+ "github.com/hashicorp/terraform-plugin-framework/datasource/schema"
+ "github.com/hashicorp/terraform-plugin-framework/path"
+ "github.com/hashicorp/terraform-plugin-framework/types"
+ "github.com/hashicorp/terraform-plugin-log/tflog"
+ "github.com/netascode/go-fmc"
+ "github.com/tidwall/gjson"
+)
+
+// End of section. //template:end imports
+
+// Section below is generated&owned by "gen/generator.go". //template:begin model
+
+// Ensure the implementation satisfies the expected interfaces.
+var (
+ _ datasource.DataSource = &BGDTemplateDataSource{}
+ _ datasource.DataSourceWithConfigure = &BGDTemplateDataSource{}
+)
+
+func NewBGDTemplateDataSource() datasource.DataSource {
+ return &BGDTemplateDataSource{}
+}
+
+type BGDTemplateDataSource struct {
+ client *fmc.Client
+}
+
+func (d *BGDTemplateDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
+ resp.TypeName = req.ProviderTypeName + "_bgd_template"
+}
+
+func (d *BGDTemplateDataSource) 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 BGD Template.",
+
+ Attributes: map[string]schema.Attribute{
+ "id": schema.StringAttribute{
+ MarkdownDescription: "The id of the object",
+ Optional: true,
+ Computed: true,
+ },
+ "domain": schema.StringAttribute{
+ MarkdownDescription: "The name of the FMC domain",
+ Optional: true,
+ },
+ "name": schema.StringAttribute{
+ MarkdownDescription: "The name of the host object.",
+ Optional: true,
+ Computed: true,
+ },
+ "type": schema.StringAttribute{
+ MarkdownDescription: "Type of the object; this value is always 'BFDTemplate'.",
+ Computed: true,
+ },
+ "hop_type": schema.StringAttribute{
+ MarkdownDescription: "SINGLE_HOP | MULTI_HOP",
+ Computed: true,
+ },
+ "echo": schema.StringAttribute{
+ MarkdownDescription: "(ENABLED | DISABLED)",
+ Computed: true,
+ },
+ "interval_time": schema.StringAttribute{
+ MarkdownDescription: "(MILLISECONDS | MICROSECONDS | NONE)",
+ Computed: true,
+ },
+ "min_transmit": schema.Int64Attribute{
+ MarkdownDescription: "BFD Minimum Transmit",
+ Computed: true,
+ },
+ "tx_rx_multiplier": schema.Int64Attribute{
+ MarkdownDescription: "BFD Multipler",
+ Computed: true,
+ },
+ "min_receive": schema.Int64Attribute{
+ MarkdownDescription: "BFD Minimum Receive",
+ Computed: true,
+ },
+ },
+ }
+}
+func (d *BGDTemplateDataSource) ConfigValidators(ctx context.Context) []datasource.ConfigValidator {
+ return []datasource.ConfigValidator{
+ datasourcevalidator.ExactlyOneOf(
+ path.MatchRoot("id"),
+ path.MatchRoot("name"),
+ ),
+ }
+}
+
+func (d *BGDTemplateDataSource) Configure(_ context.Context, req datasource.ConfigureRequest, _ *datasource.ConfigureResponse) {
+ if req.ProviderData == nil {
+ return
+ }
+
+ d.client = req.ProviderData.(*FmcProviderData).Client
+}
+
+// End of section. //template:end model
+
+// Section below is generated&owned by "gen/generator.go". //template:begin read
+
+func (d *BGDTemplateDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
+ var config BGDTemplate
+
+ // Read config
+ diags := req.Config.Get(ctx, &config)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ // Set request domain if provided
+ reqMods := [](func(*fmc.Req)){}
+ if !config.Domain.IsNull() && config.Domain.ValueString() != "" {
+ reqMods = append(reqMods, fmc.DomainName(config.Domain.ValueString()))
+ }
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Beginning Read", config.Id.String()))
+ if config.Id.IsNull() && !config.Name.IsNull() {
+ offset := 0
+ limit := 1000
+ for page := 1; ; page++ {
+ queryString := fmt.Sprintf("?limit=%d&offset=%d&expanded=true", limit, offset)
+ res, err := d.client.Get(config.getPath()+queryString, reqMods...)
+ if err != nil {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to retrieve objects, got error: %s", err))
+ return
+ }
+ if value := res.Get("items"); len(value.Array()) > 0 {
+ value.ForEach(func(k, v gjson.Result) bool {
+ if config.Name.ValueString() == v.Get("name").String() {
+ config.Id = types.StringValue(v.Get("id").String())
+ tflog.Debug(ctx, fmt.Sprintf("%s: Found object with name '%v', id: %v", config.Id.String(), config.Name.ValueString(), config.Id.String()))
+ return false
+ }
+ return true
+ })
+ }
+ if !config.Id.IsNull() || !res.Get("paging.next.0").Exists() {
+ break
+ }
+ offset += limit
+ }
+
+ if config.Id.IsNull() {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to find object with name: %s", config.Name.ValueString()))
+ return
+ }
+ }
+ urlPath := config.getPath() + "/" + url.QueryEscape(config.Id.ValueString())
+ res, err := d.client.Get(urlPath, reqMods...)
+ if err != nil {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to retrieve object, got error: %s", err))
+ return
+ }
+
+ config.fromBody(ctx, res)
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Read finished successfully", config.Id.ValueString()))
+
+ diags = resp.State.Set(ctx, &config)
+ resp.Diagnostics.Append(diags...)
+}
+
+// End of section. //template:end read
diff --git a/internal/provider/data_source_fmc_bgd_template_test.go b/internal/provider/data_source_fmc_bgd_template_test.go
new file mode 100644
index 00000000..4fbcca9a
--- /dev/null
+++ b/internal/provider/data_source_fmc_bgd_template_test.go
@@ -0,0 +1,102 @@
+// Copyright © 2023 Cisco Systems, Inc. and its affiliates.
+// All rights reserved.
+//
+// Licensed under the Mozilla Public License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://mozilla.org/MPL/2.0/
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// SPDX-License-Identifier: MPL-2.0
+
+package provider
+
+// Section below is generated&owned by "gen/generator.go". //template:begin imports
+import (
+ "testing"
+
+ "github.com/hashicorp/terraform-plugin-testing/helper/resource"
+)
+
+// End of section. //template:end imports
+
+// Section below is generated&owned by "gen/generator.go". //template:begin testAccDataSource
+
+func TestAccDataSourceFmcBGDTemplate(t *testing.T) {
+ var checks []resource.TestCheckFunc
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_bgd_template.test", "name", "BFD_Template1"))
+ checks = append(checks, resource.TestCheckResourceAttrSet("data.fmc_bgd_template.test", "type"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_bgd_template.test", "hop_type", "SINGLE_HOP"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_bgd_template.test", "echo", "ENABLED"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_bgd_template.test", "interval_time", "MILLISECONDS"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_bgd_template.test", "min_transmit", "100000"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_bgd_template.test", "tx_rx_multiplier", "3"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_bgd_template.test", "min_receive", "100000"))
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { testAccPreCheck(t) },
+ ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
+ Steps: []resource.TestStep{
+ {
+ Config: testAccDataSourceFmcBGDTemplateConfig(),
+ Check: resource.ComposeTestCheckFunc(checks...),
+ },
+ {
+ Config: testAccNamedDataSourceFmcBGDTemplateConfig(),
+ Check: resource.ComposeTestCheckFunc(checks...),
+ },
+ },
+ })
+}
+
+// End of section. //template:end testAccDataSource
+
+// Section below is generated&owned by "gen/generator.go". //template:begin testPrerequisites
+// End of section. //template:end testPrerequisites
+
+// Section below is generated&owned by "gen/generator.go". //template:begin testAccDataSourceConfig
+
+func testAccDataSourceFmcBGDTemplateConfig() string {
+ config := `resource "fmc_bgd_template" "test" {` + "\n"
+ config += ` name = "BFD_Template1"` + "\n"
+ config += ` hop_type = "SINGLE_HOP"` + "\n"
+ config += ` echo = "ENABLED"` + "\n"
+ config += ` interval_time = "MILLISECONDS"` + "\n"
+ config += ` min_transmit = 100000` + "\n"
+ config += ` tx_rx_multiplier = 3` + "\n"
+ config += ` min_receive = 100000` + "\n"
+ config += `}` + "\n"
+
+ config += `
+ data "fmc_bgd_template" "test" {
+ id = fmc_bgd_template.test.id
+ }
+ `
+ return config
+}
+
+func testAccNamedDataSourceFmcBGDTemplateConfig() string {
+ config := `resource "fmc_bgd_template" "test" {` + "\n"
+ config += ` name = "BFD_Template1"` + "\n"
+ config += ` hop_type = "SINGLE_HOP"` + "\n"
+ config += ` echo = "ENABLED"` + "\n"
+ config += ` interval_time = "MILLISECONDS"` + "\n"
+ config += ` min_transmit = 100000` + "\n"
+ config += ` tx_rx_multiplier = 3` + "\n"
+ config += ` min_receive = 100000` + "\n"
+ config += `}` + "\n"
+
+ config += `
+ data "fmc_bgd_template" "test" {
+ name = fmc_bgd_template.test.name
+ }
+ `
+ return config
+}
+
+// End of section. //template:end testAccDataSourceConfig
diff --git a/internal/provider/data_source_fmc_device_bfd.go b/internal/provider/data_source_fmc_device_bfd.go
new file mode 100644
index 00000000..63d20363
--- /dev/null
+++ b/internal/provider/data_source_fmc_device_bfd.go
@@ -0,0 +1,197 @@
+// Copyright © 2023 Cisco Systems, Inc. and its affiliates.
+// All rights reserved.
+//
+// Licensed under the Mozilla Public License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://mozilla.org/MPL/2.0/
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// SPDX-License-Identifier: MPL-2.0
+
+package provider
+
+// Section below is generated&owned by "gen/generator.go". //template:begin imports
+import (
+ "context"
+ "fmt"
+ "net/url"
+
+ "github.com/hashicorp/terraform-plugin-framework-validators/datasourcevalidator"
+ "github.com/hashicorp/terraform-plugin-framework/datasource"
+ "github.com/hashicorp/terraform-plugin-framework/datasource/schema"
+ "github.com/hashicorp/terraform-plugin-framework/path"
+ "github.com/hashicorp/terraform-plugin-framework/types"
+ "github.com/hashicorp/terraform-plugin-log/tflog"
+ "github.com/netascode/go-fmc"
+ "github.com/tidwall/gjson"
+)
+
+// End of section. //template:end imports
+
+// Section below is generated&owned by "gen/generator.go". //template:begin model
+
+// Ensure the implementation satisfies the expected interfaces.
+var (
+ _ datasource.DataSource = &DeviceBFDDataSource{}
+ _ datasource.DataSourceWithConfigure = &DeviceBFDDataSource{}
+)
+
+func NewDeviceBFDDataSource() datasource.DataSource {
+ return &DeviceBFDDataSource{}
+}
+
+type DeviceBFDDataSource struct {
+ client *fmc.Client
+}
+
+func (d *DeviceBFDDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
+ resp.TypeName = req.ProviderTypeName + "_device_bfd"
+}
+
+func (d *DeviceBFDDataSource) 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 Device BFD.",
+
+ Attributes: map[string]schema.Attribute{
+ "id": schema.StringAttribute{
+ MarkdownDescription: "The id of the object",
+ Optional: true,
+ Computed: true,
+ },
+ "domain": schema.StringAttribute{
+ MarkdownDescription: "The name of the FMC domain",
+ Optional: true,
+ },
+ "device_id": schema.StringAttribute{
+ MarkdownDescription: "UUID of the parent device (fmc_device.example.id).",
+ Required: true,
+ },
+ "type": schema.StringAttribute{
+ MarkdownDescription: "Type of the object; this value is always 'BFDPolicy'",
+ Computed: true,
+ },
+ "hop_type": schema.StringAttribute{
+ MarkdownDescription: "BFD Hop type.",
+ Computed: true,
+ },
+ "bfd_template_id": schema.StringAttribute{
+ MarkdownDescription: "ID of the BFD Template",
+ Computed: true,
+ },
+ "interface_logical_name": schema.StringAttribute{
+ MarkdownDescription: "Logical Name of the interface of BFD assignment if SINGLE_HOP selected.",
+ Optional: true,
+ Computed: true,
+ },
+ "destination_host_object_id": schema.StringAttribute{
+ MarkdownDescription: "The ID of the destination host object if MULTI_HOP selected.",
+ Computed: true,
+ },
+ "source_host_object_id": schema.StringAttribute{
+ MarkdownDescription: "The ID of the source host object if MULTI_HOP selected.",
+ Computed: true,
+ },
+ "interface_id": schema.StringAttribute{
+ MarkdownDescription: "ID of the interface of BFD assignment if SINGLE_HOP selected.",
+ Computed: true,
+ },
+ "slow_timer": schema.Int64Attribute{
+ MarkdownDescription: "BFD Slow Timer value in range: 1000-30000, default: 1000",
+ Computed: true,
+ },
+ },
+ }
+}
+func (d *DeviceBFDDataSource) ConfigValidators(ctx context.Context) []datasource.ConfigValidator {
+ return []datasource.ConfigValidator{
+ datasourcevalidator.ExactlyOneOf(
+ path.MatchRoot("id"),
+ path.MatchRoot("interface_logical_name"),
+ ),
+ }
+}
+
+func (d *DeviceBFDDataSource) Configure(_ context.Context, req datasource.ConfigureRequest, _ *datasource.ConfigureResponse) {
+ if req.ProviderData == nil {
+ return
+ }
+
+ d.client = req.ProviderData.(*FmcProviderData).Client
+}
+
+// End of section. //template:end model
+
+// Section below is generated&owned by "gen/generator.go". //template:begin read
+
+func (d *DeviceBFDDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
+ var config DeviceBFD
+
+ // Read config
+ diags := req.Config.Get(ctx, &config)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ // Set request domain if provided
+ reqMods := [](func(*fmc.Req)){}
+ if !config.Domain.IsNull() && config.Domain.ValueString() != "" {
+ reqMods = append(reqMods, fmc.DomainName(config.Domain.ValueString()))
+ }
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Beginning Read", config.Id.String()))
+ if config.Id.IsNull() && !config.InterfaceLogicalName.IsNull() {
+ offset := 0
+ limit := 1000
+ for page := 1; ; page++ {
+ queryString := fmt.Sprintf("?limit=%d&offset=%d&expanded=true", limit, offset)
+ res, err := d.client.Get(config.getPath()+queryString, reqMods...)
+ if err != nil {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to retrieve objects, got error: %s", err))
+ return
+ }
+ if value := res.Get("items"); len(value.Array()) > 0 {
+ value.ForEach(func(k, v gjson.Result) bool {
+ if config.InterfaceLogicalName.ValueString() == v.Get("ifname").String() {
+ config.Id = types.StringValue(v.Get("id").String())
+ tflog.Debug(ctx, fmt.Sprintf("%s: Found object with interface_logical_name '%v', id: %v", config.Id.String(), config.InterfaceLogicalName.ValueString(), config.Id.String()))
+ return false
+ }
+ return true
+ })
+ }
+ if !config.Id.IsNull() || !res.Get("paging.next.0").Exists() {
+ break
+ }
+ offset += limit
+ }
+
+ if config.Id.IsNull() {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to find object with interface_logical_name: %s", config.InterfaceLogicalName.ValueString()))
+ return
+ }
+ }
+ urlPath := config.getPath() + "/" + url.QueryEscape(config.Id.ValueString())
+ res, err := d.client.Get(urlPath, reqMods...)
+ if err != nil {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to retrieve object, got error: %s", err))
+ return
+ }
+
+ config.fromBody(ctx, res)
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Read finished successfully", config.Id.ValueString()))
+
+ diags = resp.State.Set(ctx, &config)
+ resp.Diagnostics.Append(diags...)
+}
+
+// End of section. //template:end read
diff --git a/internal/provider/data_source_fmc_device_bfd_test.go b/internal/provider/data_source_fmc_device_bfd_test.go
new file mode 100644
index 00000000..3522d2a3
--- /dev/null
+++ b/internal/provider/data_source_fmc_device_bfd_test.go
@@ -0,0 +1,116 @@
+// Copyright © 2023 Cisco Systems, Inc. and its affiliates.
+// All rights reserved.
+//
+// Licensed under the Mozilla Public License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://mozilla.org/MPL/2.0/
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// SPDX-License-Identifier: MPL-2.0
+
+package provider
+
+// Section below is generated&owned by "gen/generator.go". //template:begin imports
+import (
+ "os"
+ "testing"
+
+ "github.com/hashicorp/terraform-plugin-testing/helper/resource"
+)
+
+// End of section. //template:end imports
+
+// Section below is generated&owned by "gen/generator.go". //template:begin testAccDataSource
+
+func TestAccDataSourceFmcDeviceBFD(t *testing.T) {
+ if os.Getenv("TF_VAR_device_id") == "" {
+ t.Skip("skipping test, set environment variable TF_VAR_device_id")
+ }
+ var checks []resource.TestCheckFunc
+ checks = append(checks, resource.TestCheckResourceAttrSet("data.fmc_device_bfd.test", "type"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_bfd.test", "hop_type", "SINGLE_HOP"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_bfd.test", "bfd_template_id", "76d24097-41c4-4558-a4d0-a8c07ac08470"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_bfd.test", "interface_logical_name", "outside"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_bfd.test", "destination_host_object_id", "76d24097-41c4-4558-a4d0-a8c07ac08470"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_bfd.test", "source_host_object_id", "76d24097-41c4-4558-a4d0-a8c07ac08470"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_bfd.test", "interface_id", "76d24097-41c4-4558-a4d0-a8c07ac08470"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_bfd.test", "slow_timer", ""))
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { testAccPreCheck(t) },
+ ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
+ ErrorCheck: func(err error) error { return testAccErrorCheck(t, err) },
+ Steps: []resource.TestStep{
+ {
+ Config: testAccDataSourceFmcDeviceBFDPrerequisitesConfig + testAccDataSourceFmcDeviceBFDConfig(),
+ Check: resource.ComposeTestCheckFunc(checks...),
+ },
+ {
+ Config: testAccDataSourceFmcDeviceBFDPrerequisitesConfig + testAccNamedDataSourceFmcDeviceBFDConfig(),
+ Check: resource.ComposeTestCheckFunc(checks...),
+ },
+ },
+ })
+}
+
+// End of section. //template:end testAccDataSource
+
+// Section below is generated&owned by "gen/generator.go". //template:begin testPrerequisites
+
+const testAccDataSourceFmcDeviceBFDPrerequisitesConfig = `
+variable "device_id" { default = null } // tests will set $TF_VAR_device_id
+`
+
+// End of section. //template:end testPrerequisites
+
+// Section below is generated&owned by "gen/generator.go". //template:begin testAccDataSourceConfig
+
+func testAccDataSourceFmcDeviceBFDConfig() string {
+ config := `resource "fmc_device_bfd" "test" {` + "\n"
+ config += ` device_id = var.device_id` + "\n"
+ config += ` hop_type = "SINGLE_HOP"` + "\n"
+ config += ` bfd_template_id = "76d24097-41c4-4558-a4d0-a8c07ac08470"` + "\n"
+ config += ` interface_logical_name = "outside"` + "\n"
+ config += ` destination_host_object_id = "76d24097-41c4-4558-a4d0-a8c07ac08470"` + "\n"
+ config += ` source_host_object_id = "76d24097-41c4-4558-a4d0-a8c07ac08470"` + "\n"
+ config += ` interface_id = "76d24097-41c4-4558-a4d0-a8c07ac08470"` + "\n"
+ config += ` slow_timer = ` + "\n"
+ config += `}` + "\n"
+
+ config += `
+ data "fmc_device_bfd" "test" {
+ id = fmc_device_bfd.test.id
+ device_id = var.device_id
+ }
+ `
+ return config
+}
+
+func testAccNamedDataSourceFmcDeviceBFDConfig() string {
+ config := `resource "fmc_device_bfd" "test" {` + "\n"
+ config += ` device_id = var.device_id` + "\n"
+ config += ` hop_type = "SINGLE_HOP"` + "\n"
+ config += ` bfd_template_id = "76d24097-41c4-4558-a4d0-a8c07ac08470"` + "\n"
+ config += ` interface_logical_name = "outside"` + "\n"
+ config += ` destination_host_object_id = "76d24097-41c4-4558-a4d0-a8c07ac08470"` + "\n"
+ config += ` source_host_object_id = "76d24097-41c4-4558-a4d0-a8c07ac08470"` + "\n"
+ config += ` interface_id = "76d24097-41c4-4558-a4d0-a8c07ac08470"` + "\n"
+ config += ` slow_timer = ` + "\n"
+ config += `}` + "\n"
+
+ config += `
+ data "fmc_device_bfd" "test" {
+ device_id = var.device_id
+ interface_logical_name = fmc_device_bfd.test.interface_logical_name
+ }
+ `
+ return config
+}
+
+// End of section. //template:end testAccDataSourceConfig
diff --git a/internal/provider/data_source_fmc_device_bgp.go b/internal/provider/data_source_fmc_device_bgp.go
new file mode 100644
index 00000000..d3f386c6
--- /dev/null
+++ b/internal/provider/data_source_fmc_device_bgp.go
@@ -0,0 +1,561 @@
+// Copyright © 2023 Cisco Systems, Inc. and its affiliates.
+// All rights reserved.
+//
+// Licensed under the Mozilla Public License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://mozilla.org/MPL/2.0/
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// SPDX-License-Identifier: MPL-2.0
+
+package provider
+
+// Section below is generated&owned by "gen/generator.go". //template:begin imports
+import (
+ "context"
+ "fmt"
+ "net/url"
+
+ "github.com/hashicorp/terraform-plugin-framework-validators/datasourcevalidator"
+ "github.com/hashicorp/terraform-plugin-framework/datasource"
+ "github.com/hashicorp/terraform-plugin-framework/datasource/schema"
+ "github.com/hashicorp/terraform-plugin-framework/path"
+ "github.com/hashicorp/terraform-plugin-framework/types"
+ "github.com/hashicorp/terraform-plugin-log/tflog"
+ "github.com/netascode/go-fmc"
+ "github.com/tidwall/gjson"
+)
+
+// End of section. //template:end imports
+
+// Section below is generated&owned by "gen/generator.go". //template:begin model
+
+// Ensure the implementation satisfies the expected interfaces.
+var (
+ _ datasource.DataSource = &DeviceBGPDataSource{}
+ _ datasource.DataSourceWithConfigure = &DeviceBGPDataSource{}
+)
+
+func NewDeviceBGPDataSource() datasource.DataSource {
+ return &DeviceBGPDataSource{}
+}
+
+type DeviceBGPDataSource struct {
+ client *fmc.Client
+}
+
+func (d *DeviceBGPDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
+ resp.TypeName = req.ProviderTypeName + "_device_bgp"
+}
+
+func (d *DeviceBGPDataSource) 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 Device BGP.",
+
+ Attributes: map[string]schema.Attribute{
+ "id": schema.StringAttribute{
+ MarkdownDescription: "The id of the object",
+ Optional: true,
+ Computed: true,
+ },
+ "domain": schema.StringAttribute{
+ MarkdownDescription: "The name of the FMC domain",
+ Optional: true,
+ },
+ "device_id": schema.StringAttribute{
+ MarkdownDescription: "UUID of the parent device (fmc_device.example.id).",
+ Required: true,
+ },
+ "name": schema.StringAttribute{
+ MarkdownDescription: "Name of the object; this is always 'bgp'",
+ Computed: true,
+ },
+ "type": schema.StringAttribute{
+ MarkdownDescription: "Type of the object; this is always 'bgp'",
+ Computed: true,
+ },
+ "as_number": schema.StringAttribute{
+ MarkdownDescription: "Autonomus System (AS) Number",
+ Optional: true,
+ Computed: true,
+ },
+ "ipv4_address_family_type": schema.StringAttribute{
+ MarkdownDescription: "",
+ Computed: true,
+ },
+ "ipv4_learned_route_map_id": schema.StringAttribute{
+ MarkdownDescription: "Learned Route Map ID",
+ Computed: true,
+ },
+ "ipv4_default_information_orginate": schema.BoolAttribute{
+ MarkdownDescription: "Generate default routes",
+ Computed: true,
+ },
+ "ipv4_auto_aummary": schema.BoolAttribute{
+ MarkdownDescription: "Summarize subnet routes into network level routes",
+ Computed: true,
+ },
+ "ipv4_bgp_supress_inactive": schema.BoolAttribute{
+ MarkdownDescription: "Suppresing advertise inactive routes",
+ Computed: true,
+ },
+ "ipv4_synchronization": schema.BoolAttribute{
+ MarkdownDescription: "Synchronize between BGP and IGP systems",
+ Computed: true,
+ },
+ "ipv4_bgp_redistribute_internal": schema.BoolAttribute{
+ MarkdownDescription: "Redistribute IBGP into IGP. (Use filtering to limit the number of prefixes that are redistributed)",
+ Computed: true,
+ },
+ "ipv4_external_distance": schema.Int64Attribute{
+ MarkdownDescription: "Administrative route distance for external routes",
+ Computed: true,
+ },
+ "ipv4_internal_distance": schema.Int64Attribute{
+ MarkdownDescription: "Administrative route distance for internal routes",
+ Computed: true,
+ },
+ "ipv4_local_distance": schema.Int64Attribute{
+ MarkdownDescription: "Administrative route distance for local routes",
+ Computed: true,
+ },
+ "ipv4_forward_packets_over_multipath_ibgp": schema.Int64Attribute{
+ MarkdownDescription: "Number of paths to use for IBGP",
+ Computed: true,
+ },
+ "ipv4_forward_packets_over_multipath_ebgp": schema.Int64Attribute{
+ MarkdownDescription: "Number of paths to use for EBGP",
+ Computed: true,
+ },
+ "ipv4_neighbors": schema.ListNestedAttribute{
+ MarkdownDescription: "",
+ Computed: true,
+ NestedObject: schema.NestedAttributeObject{
+ Attributes: map[string]schema.Attribute{
+ "neighbor_address": schema.StringAttribute{
+ MarkdownDescription: "IP address of the BGP neighbor",
+ Computed: true,
+ },
+ "neighbor_remote_as": schema.StringAttribute{
+ MarkdownDescription: "AS number of the BGP neighbor",
+ Computed: true,
+ },
+ "neighbor_bfd": schema.StringAttribute{
+ MarkdownDescription: "BFD Fallover",
+ Computed: true,
+ },
+ "update_source_interface_id": schema.StringAttribute{
+ MarkdownDescription: "Interface ID for the update source",
+ Computed: true,
+ },
+ "enable_address_family": schema.BoolAttribute{
+ MarkdownDescription: "Enable IPv4 address family",
+ Computed: true,
+ },
+ "neighbor_shutdown": schema.BoolAttribute{
+ MarkdownDescription: "Shutdown administratively",
+ Computed: true,
+ },
+ "neighbor_description": schema.StringAttribute{
+ MarkdownDescription: "Description of the neighbor",
+ Computed: true,
+ },
+ "neighbor_filter_access_lists": schema.ListNestedAttribute{
+ MarkdownDescription: "",
+ Computed: true,
+ NestedObject: schema.NestedAttributeObject{
+ Attributes: map[string]schema.Attribute{
+ "access_list_id": schema.StringAttribute{
+ MarkdownDescription: "Access List ID",
+ Computed: true,
+ },
+ "update_direction": schema.StringAttribute{
+ MarkdownDescription: "Filter direction",
+ Computed: true,
+ },
+ },
+ },
+ },
+ "neighbor_filter_route_map_lists": schema.ListNestedAttribute{
+ MarkdownDescription: "",
+ Computed: true,
+ NestedObject: schema.NestedAttributeObject{
+ Attributes: map[string]schema.Attribute{
+ "route_map_id": schema.StringAttribute{
+ MarkdownDescription: "Route Map ID",
+ Computed: true,
+ },
+ "update_direction": schema.StringAttribute{
+ MarkdownDescription: "Filter direction",
+ Computed: true,
+ },
+ },
+ },
+ },
+ "neighbor_filter_prefix_lists": schema.ListNestedAttribute{
+ MarkdownDescription: "",
+ Computed: true,
+ NestedObject: schema.NestedAttributeObject{
+ Attributes: map[string]schema.Attribute{
+ "prefix_list_id": schema.StringAttribute{
+ MarkdownDescription: "Route Map ID",
+ Computed: true,
+ },
+ "update_direction": schema.StringAttribute{
+ MarkdownDescription: "Filter direction",
+ Computed: true,
+ },
+ },
+ },
+ },
+ "neighbor_filter_as_path_lists": schema.ListNestedAttribute{
+ MarkdownDescription: "",
+ Computed: true,
+ NestedObject: schema.NestedAttributeObject{
+ Attributes: map[string]schema.Attribute{
+ "update_direction": schema.StringAttribute{
+ MarkdownDescription: "Filter direction",
+ Computed: true,
+ },
+ "as_path_id": schema.StringAttribute{
+ MarkdownDescription: "AS Path ID",
+ Computed: true,
+ },
+ },
+ },
+ },
+ "neighbor_filter_max_prefix": schema.Int64Attribute{
+ MarkdownDescription: "Maximum number of prefixes allowed from the neighbor",
+ Computed: true,
+ },
+ "neighbor_filter_warning_only": schema.BoolAttribute{
+ MarkdownDescription: "Give only warning message when prefix limit exceeded or terminate peering when prefix limit is exceeded.",
+ Computed: true,
+ },
+ "neighbor_filter_threshold_value": schema.Int64Attribute{
+ MarkdownDescription: "Threshold value for the maximum number of prefixes allowed from the neighbor",
+ Computed: true,
+ },
+ "neighbor_filter_restart_interval": schema.Int64Attribute{
+ MarkdownDescription: "Time interval to restart the maximum prefix limit in Minutes",
+ Computed: true,
+ },
+ "neighbor_routes_advertisement_interval": schema.Int64Attribute{
+ MarkdownDescription: "Time interval to advertise routes in seconds",
+ Computed: true,
+ },
+ "neighbor_routes_remove_private_as": schema.BoolAttribute{
+ MarkdownDescription: "Remove private AS numbers from outgoing routing updates",
+ Computed: true,
+ },
+ "neighbor_generate_default_route_map_id": schema.StringAttribute{
+ MarkdownDescription: "Generate default routes - Route Map",
+ Computed: true,
+ },
+ "neighbor_routes_advertise_map_use_exist": schema.BoolAttribute{
+ MarkdownDescription: "Use Exist Map or Non-Exist Map",
+ Computed: true,
+ },
+ "neighbor_routes_advertise_map_id": schema.StringAttribute{
+ MarkdownDescription: "Specified route maps are advertised when the prefix exists in the Advertise Map and Exist Map.",
+ Computed: true,
+ },
+ "neighbor_routes_advertise_exist_nonexist_map_id": schema.StringAttribute{
+ MarkdownDescription: "Specified route maps are advertised when the prefix exists only in the Advertise Map.",
+ Computed: true,
+ },
+ "neighbor_keepalive_interval": schema.Int64Attribute{
+ MarkdownDescription: "Time interval to send keepalive messages in seconds",
+ Computed: true,
+ },
+ "neighbor_hold_time": schema.Int64Attribute{
+ MarkdownDescription: "Time interval to hold the neighbor in seconds",
+ Computed: true,
+ },
+ "neighbor_min_hold_time": schema.Int64Attribute{
+ MarkdownDescription: "Minimum hold time in seconds",
+ Computed: true,
+ },
+ "neighbor_authentication_password": schema.StringAttribute{
+ MarkdownDescription: "Setting password enables authentication.",
+ Computed: true,
+ },
+ "neighbor_send_community_attribute": schema.BoolAttribute{
+ MarkdownDescription: "Send Community attribute to this neighbor",
+ Computed: true,
+ },
+ "neighbor_nexthop_self": schema.BoolAttribute{
+ MarkdownDescription: "Use itself as next hop for this neighbor",
+ Computed: true,
+ },
+ "neighbor_disable_connection_verification": schema.BoolAttribute{
+ MarkdownDescription: "Disable Connection Verification",
+ Computed: true,
+ },
+ "neighbor_tcp_mtu_path_discovery": schema.BoolAttribute{
+ MarkdownDescription: "Use TCP path MTU discovery.",
+ Computed: true,
+ },
+ "neighbor_max_hop_count": schema.Int64Attribute{
+ MarkdownDescription: "Maximum number of hops to reach the neighbor",
+ Computed: true,
+ },
+ "neighbor_tcp_transport_mode": schema.BoolAttribute{
+ MarkdownDescription: "True set it to active, False to passive.",
+ Computed: true,
+ },
+ "neighbor_weight": schema.Int64Attribute{
+ MarkdownDescription: "Weight of the neighbor",
+ Computed: true,
+ },
+ "neighbor_version": schema.StringAttribute{
+ MarkdownDescription: "Set BPG version: 0 - default, 4 - IPv4",
+ Computed: true,
+ },
+ "neighbor_customized_local_as_number": schema.StringAttribute{
+ MarkdownDescription: "Customize the AS number for the routes received from neighbor",
+ Computed: true,
+ },
+ "neighbor_customized_no_prepend": schema.BoolAttribute{
+ MarkdownDescription: "Do not prepend local AS number to routes received from neighbor",
+ Computed: true,
+ },
+ "neighbor_customized_replace_as": schema.BoolAttribute{
+ MarkdownDescription: "Replace real AS number with local AS number in routes received from neighbor",
+ Computed: true,
+ },
+ "neighbor_customized_accept_both_as": schema.BoolAttribute{
+ MarkdownDescription: "Accept either real AS number or local AS number in routes experienced from neighbor",
+ Computed: true,
+ },
+ },
+ },
+ },
+ "ipv4_aggregate_addresses": schema.ListNestedAttribute{
+ MarkdownDescription: "",
+ Computed: true,
+ NestedObject: schema.NestedAttributeObject{
+ Attributes: map[string]schema.Attribute{
+ "generate_as": schema.BoolAttribute{
+ MarkdownDescription: "Generate AS set path information",
+ Computed: true,
+ },
+ "filter": schema.BoolAttribute{
+ MarkdownDescription: "Filter all routes from updates (summary only)",
+ Computed: true,
+ },
+ "network_id": schema.StringAttribute{
+ MarkdownDescription: "Network ID",
+ Computed: true,
+ },
+ "advertise_map_id": schema.StringAttribute{
+ MarkdownDescription: "Advertise Map ID",
+ Computed: true,
+ },
+ "attribute_map_id": schema.StringAttribute{
+ MarkdownDescription: "Attribute Map ID",
+ Computed: true,
+ },
+ "suppress_map_id": schema.StringAttribute{
+ MarkdownDescription: "Suppress Map ID",
+ Computed: true,
+ },
+ },
+ },
+ },
+ "ipv4_filterings": schema.ListNestedAttribute{
+ MarkdownDescription: "",
+ Computed: true,
+ NestedObject: schema.NestedAttributeObject{
+ Attributes: map[string]schema.Attribute{
+ "access_list_id": schema.StringAttribute{
+ MarkdownDescription: "Standard Access List ID",
+ Computed: true,
+ },
+ "network_direction": schema.StringAttribute{
+ MarkdownDescription: "Filtering directrion",
+ Computed: true,
+ },
+ "protocol": schema.StringAttribute{
+ MarkdownDescription: "Protocol",
+ Computed: true,
+ },
+ "prorocol_process": schema.StringAttribute{
+ MarkdownDescription: "Process ID",
+ Computed: true,
+ },
+ },
+ },
+ },
+ "ipv4_networks": schema.ListNestedAttribute{
+ MarkdownDescription: "",
+ Computed: true,
+ NestedObject: schema.NestedAttributeObject{
+ Attributes: map[string]schema.Attribute{
+ "network_id": schema.StringAttribute{
+ MarkdownDescription: "Network object ID",
+ Computed: true,
+ },
+ "route_map_id": schema.StringAttribute{
+ MarkdownDescription: "Route Map ID",
+ Computed: true,
+ },
+ },
+ },
+ },
+ "ipv4_redistributions": schema.ListNestedAttribute{
+ MarkdownDescription: "",
+ Computed: true,
+ NestedObject: schema.NestedAttributeObject{
+ Attributes: map[string]schema.Attribute{
+ "source_protocol": schema.StringAttribute{
+ MarkdownDescription: "Protocol to redistribute",
+ Computed: true,
+ },
+ "route_map_id": schema.StringAttribute{
+ MarkdownDescription: "Route Map ID",
+ Computed: true,
+ },
+ "metric": schema.Int64Attribute{
+ MarkdownDescription: "Metric value",
+ Computed: true,
+ },
+ "process_id": schema.StringAttribute{
+ MarkdownDescription: "process ID",
+ Computed: true,
+ },
+ "match_external1": schema.BoolAttribute{
+ MarkdownDescription: "Match OSPF External 1 metrics",
+ Computed: true,
+ },
+ "match_external2": schema.BoolAttribute{
+ MarkdownDescription: "Match OSPF External 2 metrics",
+ Computed: true,
+ },
+ "match_internal": schema.BoolAttribute{
+ MarkdownDescription: "Match OSPF Internal metrics",
+ Computed: true,
+ },
+ "match_nssa_external1": schema.BoolAttribute{
+ MarkdownDescription: "Match OSPF NSSA External 1 metrics",
+ Computed: true,
+ },
+ "match_nssa_external2": schema.BoolAttribute{
+ MarkdownDescription: "Match OSPF NSSA External 2 metrics",
+ Computed: true,
+ },
+ },
+ },
+ },
+ "ipv4_route_injections": schema.ListNestedAttribute{
+ MarkdownDescription: "",
+ Computed: true,
+ NestedObject: schema.NestedAttributeObject{
+ Attributes: map[string]schema.Attribute{
+ "inject_route_map_id": schema.StringAttribute{
+ MarkdownDescription: "Inject Route Map ID",
+ Computed: true,
+ },
+ "exist_route_map_id": schema.StringAttribute{
+ MarkdownDescription: "Exist Route Map ID",
+ Computed: true,
+ },
+ },
+ },
+ },
+ },
+ }
+}
+func (d *DeviceBGPDataSource) ConfigValidators(ctx context.Context) []datasource.ConfigValidator {
+ return []datasource.ConfigValidator{
+ datasourcevalidator.ExactlyOneOf(
+ path.MatchRoot("id"),
+ path.MatchRoot("as_number"),
+ ),
+ }
+}
+
+func (d *DeviceBGPDataSource) Configure(_ context.Context, req datasource.ConfigureRequest, _ *datasource.ConfigureResponse) {
+ if req.ProviderData == nil {
+ return
+ }
+
+ d.client = req.ProviderData.(*FmcProviderData).Client
+}
+
+// End of section. //template:end model
+
+// Section below is generated&owned by "gen/generator.go". //template:begin read
+
+func (d *DeviceBGPDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
+ var config DeviceBGP
+
+ // Read config
+ diags := req.Config.Get(ctx, &config)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ // Set request domain if provided
+ reqMods := [](func(*fmc.Req)){}
+ if !config.Domain.IsNull() && config.Domain.ValueString() != "" {
+ reqMods = append(reqMods, fmc.DomainName(config.Domain.ValueString()))
+ }
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Beginning Read", config.Id.String()))
+ if config.Id.IsNull() && !config.AsNumber.IsNull() {
+ offset := 0
+ limit := 1000
+ for page := 1; ; page++ {
+ queryString := fmt.Sprintf("?limit=%d&offset=%d&expanded=true", limit, offset)
+ res, err := d.client.Get(config.getPath()+queryString, reqMods...)
+ if err != nil {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to retrieve objects, got error: %s", err))
+ return
+ }
+ if value := res.Get("items"); len(value.Array()) > 0 {
+ value.ForEach(func(k, v gjson.Result) bool {
+ if config.AsNumber.ValueString() == v.Get("asNumber").String() {
+ config.Id = types.StringValue(v.Get("id").String())
+ tflog.Debug(ctx, fmt.Sprintf("%s: Found object with as_number '%v', id: %v", config.Id.String(), config.AsNumber.ValueString(), config.Id.String()))
+ return false
+ }
+ return true
+ })
+ }
+ if !config.Id.IsNull() || !res.Get("paging.next.0").Exists() {
+ break
+ }
+ offset += limit
+ }
+
+ if config.Id.IsNull() {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to find object with as_number: %s", config.AsNumber.ValueString()))
+ return
+ }
+ }
+ urlPath := config.getPath() + "/" + url.QueryEscape(config.Id.ValueString())
+ res, err := d.client.Get(urlPath, reqMods...)
+ if err != nil {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to retrieve object, got error: %s", err))
+ return
+ }
+
+ config.fromBody(ctx, res)
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Read finished successfully", config.Id.ValueString()))
+
+ diags = resp.State.Set(ctx, &config)
+ resp.Diagnostics.Append(diags...)
+}
+
+// End of section. //template:end read
diff --git a/internal/provider/data_source_fmc_device_bgp_general_settings.go b/internal/provider/data_source_fmc_device_bgp_general_settings.go
new file mode 100644
index 00000000..f230dbee
--- /dev/null
+++ b/internal/provider/data_source_fmc_device_bgp_general_settings.go
@@ -0,0 +1,261 @@
+// Copyright © 2023 Cisco Systems, Inc. and its affiliates.
+// All rights reserved.
+//
+// Licensed under the Mozilla Public License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://mozilla.org/MPL/2.0/
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// SPDX-License-Identifier: MPL-2.0
+
+package provider
+
+// Section below is generated&owned by "gen/generator.go". //template:begin imports
+import (
+ "context"
+ "fmt"
+ "net/url"
+
+ "github.com/hashicorp/terraform-plugin-framework-validators/datasourcevalidator"
+ "github.com/hashicorp/terraform-plugin-framework/datasource"
+ "github.com/hashicorp/terraform-plugin-framework/datasource/schema"
+ "github.com/hashicorp/terraform-plugin-framework/path"
+ "github.com/hashicorp/terraform-plugin-framework/types"
+ "github.com/hashicorp/terraform-plugin-log/tflog"
+ "github.com/netascode/go-fmc"
+ "github.com/tidwall/gjson"
+)
+
+// End of section. //template:end imports
+
+// Section below is generated&owned by "gen/generator.go". //template:begin model
+
+// Ensure the implementation satisfies the expected interfaces.
+var (
+ _ datasource.DataSource = &DeviceBGPGeneralSettingsDataSource{}
+ _ datasource.DataSourceWithConfigure = &DeviceBGPGeneralSettingsDataSource{}
+)
+
+func NewDeviceBGPGeneralSettingsDataSource() datasource.DataSource {
+ return &DeviceBGPGeneralSettingsDataSource{}
+}
+
+type DeviceBGPGeneralSettingsDataSource struct {
+ client *fmc.Client
+}
+
+func (d *DeviceBGPGeneralSettingsDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
+ resp.TypeName = req.ProviderTypeName + "_device_bgp_general_settings"
+}
+
+func (d *DeviceBGPGeneralSettingsDataSource) 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 Device BGP General Settings.",
+
+ Attributes: map[string]schema.Attribute{
+ "id": schema.StringAttribute{
+ MarkdownDescription: "The id of the object",
+ Optional: true,
+ Computed: true,
+ },
+ "domain": schema.StringAttribute{
+ MarkdownDescription: "The name of the FMC domain",
+ Optional: true,
+ },
+ "device_id": schema.StringAttribute{
+ MarkdownDescription: "UUID of the parent device (fmc_device.example.id).",
+ Required: true,
+ },
+ "name": schema.StringAttribute{
+ MarkdownDescription: "Object name; Always set to 'AsaBGPGeneralTable'",
+ Computed: true,
+ },
+ "as_number": schema.StringAttribute{
+ MarkdownDescription: "Autonomous System (AS) number in asplain or asdot format",
+ Optional: true,
+ Computed: true,
+ },
+ "router_id": schema.StringAttribute{
+ MarkdownDescription: "String value for the routerID. Possible values can be 'AUTOMATIC' or valid ipv4 address",
+ Computed: true,
+ },
+ "scanning_interval": schema.Int64Attribute{
+ MarkdownDescription: "Scanning interval of BGP routers for next hop validation in Seconds.",
+ Computed: true,
+ },
+ "as_number_in_path_attribute": schema.Int64Attribute{
+ MarkdownDescription: "Range to discard routes that have as-path segments that exceed a specified value.",
+ Computed: true,
+ },
+ "log_neighbor_changes": schema.BoolAttribute{
+ MarkdownDescription: "Enable logging of BGP neighbor status changes.",
+ Computed: true,
+ },
+ "tcp_path_mtu_discovery": schema.BoolAttribute{
+ MarkdownDescription: "Use TCP path MTU discovery.",
+ Computed: true,
+ },
+ "reset_session_upon_failover": schema.BoolAttribute{
+ MarkdownDescription: "Reset session upon failover",
+ Computed: true,
+ },
+ "enforce_first_peer_as": schema.BoolAttribute{
+ MarkdownDescription: "Discard updates received from an external BGP (eBGP) peers that do not list their autonomous system (AS) number.",
+ Computed: true,
+ },
+ "use_dot_notation": schema.BoolAttribute{
+ MarkdownDescription: "Change format of BGP 4-byte autonomous system numbers from asplain (decimal values) to dot notation.",
+ Computed: true,
+ },
+ "aggregate_timer": schema.Int64Attribute{
+ MarkdownDescription: "Interval at which BGP routes will be aggregated or to disable timer-based router aggregation (in seconds).",
+ Computed: true,
+ },
+ "default_local_preference": schema.Int64Attribute{
+ MarkdownDescription: "Default local preference",
+ Computed: true,
+ },
+ "compare_med_from_different_neighbors": schema.BoolAttribute{
+ MarkdownDescription: "Allow comparing MED from different neighbors",
+ Computed: true,
+ },
+ "compare_router_id_in_path": schema.BoolAttribute{
+ MarkdownDescription: "Compare Router ID for identical EBGP paths",
+ Computed: true,
+ },
+ "pick_best_med": schema.BoolAttribute{
+ MarkdownDescription: "Pick the best-MED path among paths advertised by neighbor AS",
+ Computed: true,
+ },
+ "missing_med_as_best": schema.BoolAttribute{
+ MarkdownDescription: "Treat missing MED as the best preferred path",
+ Computed: true,
+ },
+ "keepalive_interval": schema.Int64Attribute{
+ MarkdownDescription: "Keepalive interval in seconds",
+ Computed: true,
+ },
+ "hold_time": schema.Int64Attribute{
+ MarkdownDescription: "Hold time in seconds",
+ Computed: true,
+ },
+ "min_hold_time": schema.Int64Attribute{
+ MarkdownDescription: "Minimum hold time (0 or 3-65535 seconds)",
+ Computed: true,
+ },
+ "next_hop_address_tracking": schema.BoolAttribute{
+ MarkdownDescription: "Enable next hop address tracking",
+ Computed: true,
+ },
+ "next_hop_delay_interval": schema.Int64Attribute{
+ MarkdownDescription: "Next hop delay interval in seconds",
+ Computed: true,
+ },
+ "graceful_restart": schema.BoolAttribute{
+ MarkdownDescription: "Enable graceful restart",
+ Computed: true,
+ },
+ "graceful_restart_restart_time": schema.Int64Attribute{
+ MarkdownDescription: "Graceful Restart Time in seconds",
+ Computed: true,
+ },
+ "graceful_restart_stale_path_time": schema.Int64Attribute{
+ MarkdownDescription: "Stalepath Time in seconds",
+ Computed: true,
+ },
+ },
+ }
+}
+func (d *DeviceBGPGeneralSettingsDataSource) ConfigValidators(ctx context.Context) []datasource.ConfigValidator {
+ return []datasource.ConfigValidator{
+ datasourcevalidator.ExactlyOneOf(
+ path.MatchRoot("id"),
+ path.MatchRoot("as_number"),
+ ),
+ }
+}
+
+func (d *DeviceBGPGeneralSettingsDataSource) Configure(_ context.Context, req datasource.ConfigureRequest, _ *datasource.ConfigureResponse) {
+ if req.ProviderData == nil {
+ return
+ }
+
+ d.client = req.ProviderData.(*FmcProviderData).Client
+}
+
+// End of section. //template:end model
+
+// Section below is generated&owned by "gen/generator.go". //template:begin read
+
+func (d *DeviceBGPGeneralSettingsDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
+ var config DeviceBGPGeneralSettings
+
+ // Read config
+ diags := req.Config.Get(ctx, &config)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ // Set request domain if provided
+ reqMods := [](func(*fmc.Req)){}
+ if !config.Domain.IsNull() && config.Domain.ValueString() != "" {
+ reqMods = append(reqMods, fmc.DomainName(config.Domain.ValueString()))
+ }
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Beginning Read", config.Id.String()))
+ if config.Id.IsNull() && !config.AsNumber.IsNull() {
+ offset := 0
+ limit := 1000
+ for page := 1; ; page++ {
+ queryString := fmt.Sprintf("?limit=%d&offset=%d&expanded=true", limit, offset)
+ res, err := d.client.Get(config.getPath()+queryString, reqMods...)
+ if err != nil {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to retrieve objects, got error: %s", err))
+ return
+ }
+ if value := res.Get("items"); len(value.Array()) > 0 {
+ value.ForEach(func(k, v gjson.Result) bool {
+ if config.AsNumber.ValueString() == v.Get("asNumber").String() {
+ config.Id = types.StringValue(v.Get("id").String())
+ tflog.Debug(ctx, fmt.Sprintf("%s: Found object with as_number '%v', id: %v", config.Id.String(), config.AsNumber.ValueString(), config.Id.String()))
+ return false
+ }
+ return true
+ })
+ }
+ if !config.Id.IsNull() || !res.Get("paging.next.0").Exists() {
+ break
+ }
+ offset += limit
+ }
+
+ if config.Id.IsNull() {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to find object with as_number: %s", config.AsNumber.ValueString()))
+ return
+ }
+ }
+ urlPath := config.getPath() + "/" + url.QueryEscape(config.Id.ValueString())
+ res, err := d.client.Get(urlPath, reqMods...)
+ if err != nil {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to retrieve object, got error: %s", err))
+ return
+ }
+
+ config.fromBody(ctx, res)
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Read finished successfully", config.Id.ValueString()))
+
+ diags = resp.State.Set(ctx, &config)
+ resp.Diagnostics.Append(diags...)
+}
+
+// End of section. //template:end read
diff --git a/internal/provider/data_source_fmc_device_bgp_general_settings_test.go b/internal/provider/data_source_fmc_device_bgp_general_settings_test.go
new file mode 100644
index 00000000..1e34b1c7
--- /dev/null
+++ b/internal/provider/data_source_fmc_device_bgp_general_settings_test.go
@@ -0,0 +1,152 @@
+// Copyright © 2023 Cisco Systems, Inc. and its affiliates.
+// All rights reserved.
+//
+// Licensed under the Mozilla Public License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://mozilla.org/MPL/2.0/
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// SPDX-License-Identifier: MPL-2.0
+
+package provider
+
+// Section below is generated&owned by "gen/generator.go". //template:begin imports
+import (
+ "os"
+ "testing"
+
+ "github.com/hashicorp/terraform-plugin-testing/helper/resource"
+)
+
+// End of section. //template:end imports
+
+// Section below is generated&owned by "gen/generator.go". //template:begin testAccDataSource
+
+func TestAccDataSourceFmcDeviceBGPGeneralSettings(t *testing.T) {
+ if os.Getenv("TF_VAR_device_id") == "" {
+ t.Skip("skipping test, set environment variable TF_VAR_device_id")
+ }
+ var checks []resource.TestCheckFunc
+ checks = append(checks, resource.TestCheckResourceAttrSet("data.fmc_device_bgp_general_settings.test", "name"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_bgp_general_settings.test", "as_number", "65535"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_bgp_general_settings.test", "router_id", "AUTOMATIC"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_bgp_general_settings.test", "scanning_interval", "60"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_bgp_general_settings.test", "as_number_in_path_attribute", "50"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_bgp_general_settings.test", "log_neighbor_changes", "false"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_bgp_general_settings.test", "tcp_path_mtu_discovery", "true"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_bgp_general_settings.test", "reset_session_upon_failover", "true"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_bgp_general_settings.test", "enforce_first_peer_as", "true"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_bgp_general_settings.test", "use_dot_notation", "false"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_bgp_general_settings.test", "aggregate_timer", "30"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_bgp_general_settings.test", "default_local_preference", "100"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_bgp_general_settings.test", "compare_med_from_different_neighbors", "true"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_bgp_general_settings.test", "compare_router_id_in_path", "true"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_bgp_general_settings.test", "pick_best_med", "true"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_bgp_general_settings.test", "missing_med_as_best", "false"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_bgp_general_settings.test", "keepalive_interval", "60"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_bgp_general_settings.test", "hold_time", "180"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_bgp_general_settings.test", "min_hold_time", "0"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_bgp_general_settings.test", "next_hop_delay_interval", "5"))
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { testAccPreCheck(t) },
+ ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
+ ErrorCheck: func(err error) error { return testAccErrorCheck(t, err) },
+ Steps: []resource.TestStep{
+ {
+ Config: testAccDataSourceFmcDeviceBGPGeneralSettingsPrerequisitesConfig + testAccDataSourceFmcDeviceBGPGeneralSettingsConfig(),
+ Check: resource.ComposeTestCheckFunc(checks...),
+ },
+ {
+ Config: testAccDataSourceFmcDeviceBGPGeneralSettingsPrerequisitesConfig + testAccNamedDataSourceFmcDeviceBGPGeneralSettingsConfig(),
+ Check: resource.ComposeTestCheckFunc(checks...),
+ },
+ },
+ })
+}
+
+// End of section. //template:end testAccDataSource
+
+// Section below is generated&owned by "gen/generator.go". //template:begin testPrerequisites
+
+const testAccDataSourceFmcDeviceBGPGeneralSettingsPrerequisitesConfig = `
+variable "device_id" { default = null } // tests will set $TF_VAR_device_id
+`
+
+// End of section. //template:end testPrerequisites
+
+// Section below is generated&owned by "gen/generator.go". //template:begin testAccDataSourceConfig
+
+func testAccDataSourceFmcDeviceBGPGeneralSettingsConfig() string {
+ config := `resource "fmc_device_bgp_general_settings" "test" {` + "\n"
+ config += ` device_id = var.device_id` + "\n"
+ config += ` as_number = "65535"` + "\n"
+ config += ` router_id = "AUTOMATIC"` + "\n"
+ config += ` scanning_interval = 60` + "\n"
+ config += ` as_number_in_path_attribute = 50` + "\n"
+ config += ` log_neighbor_changes = false` + "\n"
+ config += ` tcp_path_mtu_discovery = true` + "\n"
+ config += ` reset_session_upon_failover = true` + "\n"
+ config += ` enforce_first_peer_as = true` + "\n"
+ config += ` use_dot_notation = false` + "\n"
+ config += ` aggregate_timer = 30` + "\n"
+ config += ` default_local_preference = 100` + "\n"
+ config += ` compare_med_from_different_neighbors = true` + "\n"
+ config += ` compare_router_id_in_path = true` + "\n"
+ config += ` pick_best_med = true` + "\n"
+ config += ` missing_med_as_best = false` + "\n"
+ config += ` keepalive_interval = 60` + "\n"
+ config += ` hold_time = 180` + "\n"
+ config += ` min_hold_time = 0` + "\n"
+ config += ` next_hop_delay_interval = 5` + "\n"
+ config += `}` + "\n"
+
+ config += `
+ data "fmc_device_bgp_general_settings" "test" {
+ id = fmc_device_bgp_general_settings.test.id
+ device_id = var.device_id
+ }
+ `
+ return config
+}
+
+func testAccNamedDataSourceFmcDeviceBGPGeneralSettingsConfig() string {
+ config := `resource "fmc_device_bgp_general_settings" "test" {` + "\n"
+ config += ` device_id = var.device_id` + "\n"
+ config += ` as_number = "65535"` + "\n"
+ config += ` router_id = "AUTOMATIC"` + "\n"
+ config += ` scanning_interval = 60` + "\n"
+ config += ` as_number_in_path_attribute = 50` + "\n"
+ config += ` log_neighbor_changes = false` + "\n"
+ config += ` tcp_path_mtu_discovery = true` + "\n"
+ config += ` reset_session_upon_failover = true` + "\n"
+ config += ` enforce_first_peer_as = true` + "\n"
+ config += ` use_dot_notation = false` + "\n"
+ config += ` aggregate_timer = 30` + "\n"
+ config += ` default_local_preference = 100` + "\n"
+ config += ` compare_med_from_different_neighbors = true` + "\n"
+ config += ` compare_router_id_in_path = true` + "\n"
+ config += ` pick_best_med = true` + "\n"
+ config += ` missing_med_as_best = false` + "\n"
+ config += ` keepalive_interval = 60` + "\n"
+ config += ` hold_time = 180` + "\n"
+ config += ` min_hold_time = 0` + "\n"
+ config += ` next_hop_delay_interval = 5` + "\n"
+ config += `}` + "\n"
+
+ config += `
+ data "fmc_device_bgp_general_settings" "test" {
+ device_id = var.device_id
+ as_number = fmc_device_bgp_general_settings.test.as_number
+ }
+ `
+ return config
+}
+
+// End of section. //template:end testAccDataSourceConfig
diff --git a/internal/provider/data_source_fmc_device_bgp_test.go b/internal/provider/data_source_fmc_device_bgp_test.go
new file mode 100644
index 00000000..15d0146c
--- /dev/null
+++ b/internal/provider/data_source_fmc_device_bgp_test.go
@@ -0,0 +1,206 @@
+// Copyright © 2023 Cisco Systems, Inc. and its affiliates.
+// All rights reserved.
+//
+// Licensed under the Mozilla Public License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://mozilla.org/MPL/2.0/
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// SPDX-License-Identifier: MPL-2.0
+
+package provider
+
+// Section below is generated&owned by "gen/generator.go". //template:begin imports
+import (
+ "os"
+ "testing"
+
+ "github.com/hashicorp/terraform-plugin-testing/helper/resource"
+)
+
+// End of section. //template:end imports
+
+// Section below is generated&owned by "gen/generator.go". //template:begin testAccDataSource
+
+func TestAccDataSourceFmcDeviceBGP(t *testing.T) {
+ if os.Getenv("TF_VAR_device_id") == "" {
+ t.Skip("skipping test, set environment variable TF_VAR_device_id")
+ }
+ var checks []resource.TestCheckFunc
+ checks = append(checks, resource.TestCheckResourceAttrSet("data.fmc_device_bgp.test", "name"))
+ checks = append(checks, resource.TestCheckResourceAttrSet("data.fmc_device_bgp.test", "type"))
+ checks = append(checks, resource.TestCheckResourceAttrSet("data.fmc_device_bgp.test", "as_number"))
+ checks = append(checks, resource.TestCheckResourceAttrSet("data.fmc_device_bgp.test", "ipv4_address_family_type"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_bgp.test", "ipv4_default_information_orginate", "false"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_bgp.test", "ipv4_auto_aummary", "false"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_bgp.test", "ipv4_bgp_supress_inactive", "false"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_bgp.test", "ipv4_synchronization", "false"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_bgp.test", "ipv4_bgp_redistribute_internal", "false"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_bgp.test", "ipv4_external_distance", "20"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_bgp.test", "ipv4_internal_distance", "200"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_bgp.test", "ipv4_local_distance", "200"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_bgp.test", "ipv4_forward_packets_over_multipath_ibgp", "1"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_bgp.test", "ipv4_forward_packets_over_multipath_ebgp", "1"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_bgp.test", "ipv4_neighbors.0.neighbor_address", "10.1.1.1"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_bgp.test", "ipv4_neighbors.0.neighbor_remote_as", "65534"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_bgp.test", "ipv4_neighbors.0.neighbor_bfd", "SINGLE_HOP"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_bgp.test", "ipv4_neighbors.0.enable_address_family", "true"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_bgp.test", "ipv4_neighbors.0.neighbor_shutdown", "false"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_bgp.test", "ipv4_neighbors.0.neighbor_description", "My BGP Peer"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_bgp.test", "ipv4_neighbors.0.neighbor_filter_max_prefix", "1"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_bgp.test", "ipv4_neighbors.0.neighbor_filter_warning_only", "true"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_bgp.test", "ipv4_neighbors.0.neighbor_filter_threshold_value", "1"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_bgp.test", "ipv4_neighbors.0.neighbor_filter_restart_interval", "1"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_bgp.test", "ipv4_neighbors.0.neighbor_routes_advertisement_interval", "1"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_bgp.test", "ipv4_neighbors.0.neighbor_routes_remove_private_as", "false"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_bgp.test", "ipv4_neighbors.0.neighbor_keepalive_interval", "60"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_bgp.test", "ipv4_neighbors.0.neighbor_hold_time", "180"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_bgp.test", "ipv4_neighbors.0.neighbor_min_hold_time", "3"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_bgp.test", "ipv4_neighbors.0.neighbor_send_community_attribute", "false"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_bgp.test", "ipv4_neighbors.0.neighbor_nexthop_self", "false"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_bgp.test", "ipv4_neighbors.0.neighbor_disable_connection_verification", "false"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_bgp.test", "ipv4_neighbors.0.neighbor_tcp_mtu_path_discovery", "false"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_bgp.test", "ipv4_neighbors.0.neighbor_max_hop_count", "1"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_bgp.test", "ipv4_neighbors.0.neighbor_tcp_transport_mode", "false"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_bgp.test", "ipv4_neighbors.0.neighbor_weight", "0"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_bgp.test", "ipv4_neighbors.0.neighbor_version", "0"))
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { testAccPreCheck(t) },
+ ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
+ ErrorCheck: func(err error) error { return testAccErrorCheck(t, err) },
+ Steps: []resource.TestStep{
+ {
+ Config: testAccDataSourceFmcDeviceBGPPrerequisitesConfig + testAccDataSourceFmcDeviceBGPConfig(),
+ Check: resource.ComposeTestCheckFunc(checks...),
+ },
+ {
+ Config: testAccDataSourceFmcDeviceBGPPrerequisitesConfig + testAccNamedDataSourceFmcDeviceBGPConfig(),
+ Check: resource.ComposeTestCheckFunc(checks...),
+ },
+ },
+ })
+}
+
+// End of section. //template:end testAccDataSource
+
+// Section below is generated&owned by "gen/generator.go". //template:begin testPrerequisites
+
+const testAccDataSourceFmcDeviceBGPPrerequisitesConfig = `
+variable "device_id" { default = null } // tests will set $TF_VAR_device_id
+
+resource "fmc_device_bgp_general_settings" "test" {
+ device_id = var.device_id
+ as_number = "6353"
+}
+`
+
+// End of section. //template:end testPrerequisites
+
+// Section below is generated&owned by "gen/generator.go". //template:begin testAccDataSourceConfig
+
+func testAccDataSourceFmcDeviceBGPConfig() string {
+ config := `resource "fmc_device_bgp" "test" {` + "\n"
+ config += ` device_id = var.device_id` + "\n"
+ config += ` ipv4_default_information_orginate = false` + "\n"
+ config += ` ipv4_auto_aummary = false` + "\n"
+ config += ` ipv4_bgp_supress_inactive = false` + "\n"
+ config += ` ipv4_synchronization = false` + "\n"
+ config += ` ipv4_bgp_redistribute_internal = false` + "\n"
+ config += ` ipv4_external_distance = 20` + "\n"
+ config += ` ipv4_internal_distance = 200` + "\n"
+ config += ` ipv4_local_distance = 200` + "\n"
+ config += ` ipv4_forward_packets_over_multipath_ibgp = 1` + "\n"
+ config += ` ipv4_forward_packets_over_multipath_ebgp = 1` + "\n"
+ config += ` ipv4_neighbors = [{` + "\n"
+ config += ` neighbor_address = "10.1.1.1"` + "\n"
+ config += ` neighbor_remote_as = "65534"` + "\n"
+ config += ` neighbor_bfd = "SINGLE_HOP"` + "\n"
+ config += ` enable_address_family = true` + "\n"
+ config += ` neighbor_shutdown = false` + "\n"
+ config += ` neighbor_description = "My BGP Peer"` + "\n"
+ config += ` neighbor_filter_max_prefix = 1` + "\n"
+ config += ` neighbor_filter_warning_only = true` + "\n"
+ config += ` neighbor_filter_threshold_value = 1` + "\n"
+ config += ` neighbor_filter_restart_interval = 1` + "\n"
+ config += ` neighbor_routes_advertisement_interval = 1` + "\n"
+ config += ` neighbor_routes_remove_private_as = false` + "\n"
+ config += ` neighbor_keepalive_interval = 60` + "\n"
+ config += ` neighbor_hold_time = 180` + "\n"
+ config += ` neighbor_min_hold_time = 3` + "\n"
+ config += ` neighbor_send_community_attribute = false` + "\n"
+ config += ` neighbor_nexthop_self = false` + "\n"
+ config += ` neighbor_disable_connection_verification = false` + "\n"
+ config += ` neighbor_tcp_mtu_path_discovery = false` + "\n"
+ config += ` neighbor_max_hop_count = 1` + "\n"
+ config += ` neighbor_tcp_transport_mode = false` + "\n"
+ config += ` neighbor_weight = 0` + "\n"
+ config += ` neighbor_version = "0"` + "\n"
+ config += ` }]` + "\n"
+ config += `}` + "\n"
+
+ config += `
+ data "fmc_device_bgp" "test" {
+ id = fmc_device_bgp.test.id
+ device_id = var.device_id
+ }
+ `
+ return config
+}
+
+func testAccNamedDataSourceFmcDeviceBGPConfig() string {
+ config := `resource "fmc_device_bgp" "test" {` + "\n"
+ config += ` device_id = var.device_id` + "\n"
+ config += ` ipv4_default_information_orginate = false` + "\n"
+ config += ` ipv4_auto_aummary = false` + "\n"
+ config += ` ipv4_bgp_supress_inactive = false` + "\n"
+ config += ` ipv4_synchronization = false` + "\n"
+ config += ` ipv4_bgp_redistribute_internal = false` + "\n"
+ config += ` ipv4_external_distance = 20` + "\n"
+ config += ` ipv4_internal_distance = 200` + "\n"
+ config += ` ipv4_local_distance = 200` + "\n"
+ config += ` ipv4_forward_packets_over_multipath_ibgp = 1` + "\n"
+ config += ` ipv4_forward_packets_over_multipath_ebgp = 1` + "\n"
+ config += ` ipv4_neighbors = [{` + "\n"
+ config += ` neighbor_address = "10.1.1.1"` + "\n"
+ config += ` neighbor_remote_as = "65534"` + "\n"
+ config += ` neighbor_bfd = "SINGLE_HOP"` + "\n"
+ config += ` enable_address_family = true` + "\n"
+ config += ` neighbor_shutdown = false` + "\n"
+ config += ` neighbor_description = "My BGP Peer"` + "\n"
+ config += ` neighbor_filter_max_prefix = 1` + "\n"
+ config += ` neighbor_filter_warning_only = true` + "\n"
+ config += ` neighbor_filter_threshold_value = 1` + "\n"
+ config += ` neighbor_filter_restart_interval = 1` + "\n"
+ config += ` neighbor_routes_advertisement_interval = 1` + "\n"
+ config += ` neighbor_routes_remove_private_as = false` + "\n"
+ config += ` neighbor_keepalive_interval = 60` + "\n"
+ config += ` neighbor_hold_time = 180` + "\n"
+ config += ` neighbor_min_hold_time = 3` + "\n"
+ config += ` neighbor_send_community_attribute = false` + "\n"
+ config += ` neighbor_nexthop_self = false` + "\n"
+ config += ` neighbor_disable_connection_verification = false` + "\n"
+ config += ` neighbor_tcp_mtu_path_discovery = false` + "\n"
+ config += ` neighbor_max_hop_count = 1` + "\n"
+ config += ` neighbor_tcp_transport_mode = false` + "\n"
+ config += ` neighbor_weight = 0` + "\n"
+ config += ` neighbor_version = "0"` + "\n"
+ config += ` }]` + "\n"
+ config += `}` + "\n"
+
+ config += `
+ data "fmc_device_bgp" "test" {
+ device_id = var.device_id
+ as_number = fmc_device_bgp.test.as_number
+ }
+ `
+ return config
+}
+
+// End of section. //template:end testAccDataSourceConfig
diff --git a/internal/provider/data_source_fmc_device_etherchannel_interface.go b/internal/provider/data_source_fmc_device_etherchannel_interface.go
index 0b86eb41..30079067 100644
--- a/internal/provider/data_source_fmc_device_etherchannel_interface.go
+++ b/internal/provider/data_source_fmc_device_etherchannel_interface.go
@@ -460,7 +460,7 @@ func (d *DeviceEtherChannelInterfaceDataSource) Read(ctx context.Context, req da
offset := 0
limit := 1000
for page := 1; ; page++ {
- queryString := fmt.Sprintf("?limit=%d&offset=%d", limit, offset)
+ queryString := fmt.Sprintf("?limit=%d&offset=%d&expanded=true", limit, offset)
res, err := d.client.Get(config.getPath()+queryString, reqMods...)
if err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to retrieve objects, got error: %s", err))
diff --git a/internal/provider/data_source_fmc_device_etherchannel_interface_test.go b/internal/provider/data_source_fmc_device_etherchannel_interface_test.go
index 89efb6b3..4b26c4e4 100644
--- a/internal/provider/data_source_fmc_device_etherchannel_interface_test.go
+++ b/internal/provider/data_source_fmc_device_etherchannel_interface_test.go
@@ -123,8 +123,8 @@ func testAccNamedDataSourceFmcDeviceEtherChannelInterfaceConfig() string {
config += `
data "fmc_device_etherchannel_interface" "test" {
- name = fmc_device_etherchannel_interface.test.name
device_id = var.device_id
+ name = fmc_device_etherchannel_interface.test.name
}
`
return config
diff --git a/internal/provider/data_source_fmc_device_ha_pair_monitoring.go b/internal/provider/data_source_fmc_device_ha_pair_monitoring.go
new file mode 100644
index 00000000..4010defb
--- /dev/null
+++ b/internal/provider/data_source_fmc_device_ha_pair_monitoring.go
@@ -0,0 +1,205 @@
+// Copyright © 2023 Cisco Systems, Inc. and its affiliates.
+// All rights reserved.
+//
+// Licensed under the Mozilla Public License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://mozilla.org/MPL/2.0/
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// SPDX-License-Identifier: MPL-2.0
+
+package provider
+
+// Section below is generated&owned by "gen/generator.go". //template:begin imports
+import (
+ "context"
+ "fmt"
+ "net/url"
+
+ "github.com/hashicorp/terraform-plugin-framework-validators/datasourcevalidator"
+ "github.com/hashicorp/terraform-plugin-framework/datasource"
+ "github.com/hashicorp/terraform-plugin-framework/datasource/schema"
+ "github.com/hashicorp/terraform-plugin-framework/path"
+ "github.com/hashicorp/terraform-plugin-framework/types"
+ "github.com/hashicorp/terraform-plugin-log/tflog"
+ "github.com/netascode/go-fmc"
+ "github.com/tidwall/gjson"
+)
+
+// End of section. //template:end imports
+
+// Section below is generated&owned by "gen/generator.go". //template:begin model
+
+// Ensure the implementation satisfies the expected interfaces.
+var (
+ _ datasource.DataSource = &DeviceHAPairMonitoringDataSource{}
+ _ datasource.DataSourceWithConfigure = &DeviceHAPairMonitoringDataSource{}
+)
+
+func NewDeviceHAPairMonitoringDataSource() datasource.DataSource {
+ return &DeviceHAPairMonitoringDataSource{}
+}
+
+type DeviceHAPairMonitoringDataSource struct {
+ client *fmc.Client
+}
+
+func (d *DeviceHAPairMonitoringDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
+ resp.TypeName = req.ProviderTypeName + "_device_ha_pair_monitoring"
+}
+
+func (d *DeviceHAPairMonitoringDataSource) 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 Device HA Pair Monitoring.",
+
+ Attributes: map[string]schema.Attribute{
+ "id": schema.StringAttribute{
+ MarkdownDescription: "The id of the object",
+ Optional: true,
+ Computed: true,
+ },
+ "domain": schema.StringAttribute{
+ MarkdownDescription: "The name of the FMC domain",
+ Optional: true,
+ },
+ "device_id": schema.StringAttribute{
+ MarkdownDescription: "UUID of the parent HA device (fmc_device.example.id).",
+ Required: true,
+ },
+ "type": schema.StringAttribute{
+ MarkdownDescription: "Type of the resource.",
+ Computed: true,
+ },
+ "logical_name": schema.StringAttribute{
+ MarkdownDescription: "Logical Name of the monitored interface.",
+ Optional: true,
+ Computed: true,
+ },
+ "monitor_interface": schema.BoolAttribute{
+ MarkdownDescription: "Monitor this interface for failures.",
+ Computed: true,
+ },
+ "ipv4_active_address": schema.StringAttribute{
+ MarkdownDescription: "Active IPv4 address from the interface.",
+ Computed: true,
+ },
+ "ipv4_standby_address": schema.StringAttribute{
+ MarkdownDescription: "Standby IPv4 address. It has to be in the same subnet as primaty IP configured on this interface.",
+ Computed: true,
+ },
+ "ipv4_netmask": schema.StringAttribute{
+ MarkdownDescription: "IPv4 Network Mask assigned on the interface.",
+ Computed: true,
+ },
+ "ipv6_addresses": schema.ListNestedAttribute{
+ MarkdownDescription: "",
+ Computed: true,
+ NestedObject: schema.NestedAttributeObject{
+ Attributes: map[string]schema.Attribute{
+ "active_address": schema.StringAttribute{
+ MarkdownDescription: "Active IPv6 address with prefix. Address has to be configured on the interface.",
+ Computed: true,
+ },
+ "standby_address": schema.StringAttribute{
+ MarkdownDescription: "Standby IPv6 address. Address has to be from the same subnet as active IPv6 address.",
+ Computed: true,
+ },
+ },
+ },
+ },
+ },
+ }
+}
+func (d *DeviceHAPairMonitoringDataSource) ConfigValidators(ctx context.Context) []datasource.ConfigValidator {
+ return []datasource.ConfigValidator{
+ datasourcevalidator.ExactlyOneOf(
+ path.MatchRoot("id"),
+ path.MatchRoot("logical_name"),
+ ),
+ }
+}
+
+func (d *DeviceHAPairMonitoringDataSource) Configure(_ context.Context, req datasource.ConfigureRequest, _ *datasource.ConfigureResponse) {
+ if req.ProviderData == nil {
+ return
+ }
+
+ d.client = req.ProviderData.(*FmcProviderData).Client
+}
+
+// End of section. //template:end model
+
+// Section below is generated&owned by "gen/generator.go". //template:begin read
+
+func (d *DeviceHAPairMonitoringDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
+ var config DeviceHAPairMonitoring
+
+ // Read config
+ diags := req.Config.Get(ctx, &config)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ // Set request domain if provided
+ reqMods := [](func(*fmc.Req)){}
+ if !config.Domain.IsNull() && config.Domain.ValueString() != "" {
+ reqMods = append(reqMods, fmc.DomainName(config.Domain.ValueString()))
+ }
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Beginning Read", config.Id.String()))
+ if config.Id.IsNull() && !config.LogicalName.IsNull() {
+ offset := 0
+ limit := 1000
+ for page := 1; ; page++ {
+ queryString := fmt.Sprintf("?limit=%d&offset=%d&expanded=true", limit, offset)
+ res, err := d.client.Get(config.getPath()+queryString, reqMods...)
+ if err != nil {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to retrieve objects, got error: %s", err))
+ return
+ }
+ if value := res.Get("items"); len(value.Array()) > 0 {
+ value.ForEach(func(k, v gjson.Result) bool {
+ if config.LogicalName.ValueString() == v.Get("name").String() {
+ config.Id = types.StringValue(v.Get("id").String())
+ tflog.Debug(ctx, fmt.Sprintf("%s: Found object with logical_name '%v', id: %v", config.Id.String(), config.LogicalName.ValueString(), config.Id.String()))
+ return false
+ }
+ return true
+ })
+ }
+ if !config.Id.IsNull() || !res.Get("paging.next.0").Exists() {
+ break
+ }
+ offset += limit
+ }
+
+ if config.Id.IsNull() {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to find object with logical_name: %s", config.LogicalName.ValueString()))
+ return
+ }
+ }
+ urlPath := config.getPath() + "/" + url.QueryEscape(config.Id.ValueString())
+ res, err := d.client.Get(urlPath, reqMods...)
+ if err != nil {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to retrieve object, got error: %s", err))
+ return
+ }
+
+ config.fromBody(ctx, res)
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Read finished successfully", config.Id.ValueString()))
+
+ diags = resp.State.Set(ctx, &config)
+ resp.Diagnostics.Append(diags...)
+}
+
+// End of section. //template:end read
diff --git a/internal/provider/data_source_fmc_device_ha_pair_monitoring_test.go b/internal/provider/data_source_fmc_device_ha_pair_monitoring_test.go
new file mode 100644
index 00000000..48370389
--- /dev/null
+++ b/internal/provider/data_source_fmc_device_ha_pair_monitoring_test.go
@@ -0,0 +1,116 @@
+// Copyright © 2023 Cisco Systems, Inc. and its affiliates.
+// All rights reserved.
+//
+// Licensed under the Mozilla Public License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://mozilla.org/MPL/2.0/
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// SPDX-License-Identifier: MPL-2.0
+
+package provider
+
+// Section below is generated&owned by "gen/generator.go". //template:begin imports
+import (
+ "os"
+ "testing"
+
+ "github.com/hashicorp/terraform-plugin-testing/helper/resource"
+)
+
+// End of section. //template:end imports
+
+// Section below is generated&owned by "gen/generator.go". //template:begin testAccDataSource
+
+func TestAccDataSourceFmcDeviceHAPairMonitoring(t *testing.T) {
+ if os.Getenv("TF_VAR_device_ha_id") == "" {
+ t.Skip("skipping test, set environment variable TF_VAR_device_ha_id")
+ }
+ var checks []resource.TestCheckFunc
+ checks = append(checks, resource.TestCheckResourceAttrSet("data.fmc_device_ha_pair_monitoring.test", "type"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_ha_pair_monitoring.test", "logical_name", "outside"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_ha_pair_monitoring.test", "monitor_interface", "true"))
+ checks = append(checks, resource.TestCheckResourceAttrSet("data.fmc_device_ha_pair_monitoring.test", "ipv4_active_address"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_ha_pair_monitoring.test", "ipv4_standby_address", "10.1.1.2"))
+ checks = append(checks, resource.TestCheckResourceAttrSet("data.fmc_device_ha_pair_monitoring.test", "ipv4_netmask"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_ha_pair_monitoring.test", "ipv6_addresses.0.active_address", "2006::1/30"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_device_ha_pair_monitoring.test", "ipv6_addresses.0.standby_address", "2006::2"))
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { testAccPreCheck(t) },
+ ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
+ ErrorCheck: func(err error) error { return testAccErrorCheck(t, err) },
+ Steps: []resource.TestStep{
+ {
+ Config: testAccDataSourceFmcDeviceHAPairMonitoringPrerequisitesConfig + testAccDataSourceFmcDeviceHAPairMonitoringConfig(),
+ Check: resource.ComposeTestCheckFunc(checks...),
+ },
+ {
+ Config: testAccDataSourceFmcDeviceHAPairMonitoringPrerequisitesConfig + testAccNamedDataSourceFmcDeviceHAPairMonitoringConfig(),
+ Check: resource.ComposeTestCheckFunc(checks...),
+ },
+ },
+ })
+}
+
+// End of section. //template:end testAccDataSource
+
+// Section below is generated&owned by "gen/generator.go". //template:begin testPrerequisites
+
+const testAccDataSourceFmcDeviceHAPairMonitoringPrerequisitesConfig = `
+variable "device_ha_id" { default = null } // tests will set $TF_VAR_device_ha_id
+`
+
+// End of section. //template:end testPrerequisites
+
+// Section below is generated&owned by "gen/generator.go". //template:begin testAccDataSourceConfig
+
+func testAccDataSourceFmcDeviceHAPairMonitoringConfig() string {
+ config := `resource "fmc_device_ha_pair_monitoring" "test" {` + "\n"
+ config += ` device_id = var.device_ha_id` + "\n"
+ config += ` logical_name = "outside"` + "\n"
+ config += ` monitor_interface = true` + "\n"
+ config += ` ipv4_standby_address = "10.1.1.2"` + "\n"
+ config += ` ipv6_addresses = [{` + "\n"
+ config += ` active_address = "2006::1/30"` + "\n"
+ config += ` standby_address = "2006::2"` + "\n"
+ config += ` }]` + "\n"
+ config += `}` + "\n"
+
+ config += `
+ data "fmc_device_ha_pair_monitoring" "test" {
+ id = fmc_device_ha_pair_monitoring.test.id
+ device_id = var.device_ha_id
+ }
+ `
+ return config
+}
+
+func testAccNamedDataSourceFmcDeviceHAPairMonitoringConfig() string {
+ config := `resource "fmc_device_ha_pair_monitoring" "test" {` + "\n"
+ config += ` device_id = var.device_ha_id` + "\n"
+ config += ` logical_name = "outside"` + "\n"
+ config += ` monitor_interface = true` + "\n"
+ config += ` ipv4_standby_address = "10.1.1.2"` + "\n"
+ config += ` ipv6_addresses = [{` + "\n"
+ config += ` active_address = "2006::1/30"` + "\n"
+ config += ` standby_address = "2006::2"` + "\n"
+ config += ` }]` + "\n"
+ config += `}` + "\n"
+
+ config += `
+ data "fmc_device_ha_pair_monitoring" "test" {
+ device_id = var.device_ha_id
+ logical_name = fmc_device_ha_pair_monitoring.test.logical_name
+ }
+ `
+ return config
+}
+
+// End of section. //template:end testAccDataSourceConfig
diff --git a/internal/provider/data_source_fmc_device_physical_interface.go b/internal/provider/data_source_fmc_device_physical_interface.go
index efe25dda..50709a81 100644
--- a/internal/provider/data_source_fmc_device_physical_interface.go
+++ b/internal/provider/data_source_fmc_device_physical_interface.go
@@ -436,7 +436,7 @@ func (d *DevicePhysicalInterfaceDataSource) Read(ctx context.Context, req dataso
offset := 0
limit := 1000
for page := 1; ; page++ {
- queryString := fmt.Sprintf("?limit=%d&offset=%d", limit, offset)
+ queryString := fmt.Sprintf("?limit=%d&offset=%d&expanded=true", limit, offset)
res, err := d.client.Get(config.getPath()+queryString, reqMods...)
if err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to retrieve objects, got error: %s", err))
diff --git a/internal/provider/data_source_fmc_device_physical_interface_test.go b/internal/provider/data_source_fmc_device_physical_interface_test.go
index 944f9945..fd9daf0f 100644
--- a/internal/provider/data_source_fmc_device_physical_interface_test.go
+++ b/internal/provider/data_source_fmc_device_physical_interface_test.go
@@ -112,8 +112,8 @@ func testAccNamedDataSourceFmcDevicePhysicalInterfaceConfig() string {
config += `
data "fmc_device_physical_interface" "test" {
- name = fmc_device_physical_interface.test.name
device_id = var.device_id
+ name = fmc_device_physical_interface.test.name
}
`
return config
diff --git a/internal/provider/data_source_fmc_device_subinterface.go b/internal/provider/data_source_fmc_device_subinterface.go
index 0547a0c3..454bc401 100644
--- a/internal/provider/data_source_fmc_device_subinterface.go
+++ b/internal/provider/data_source_fmc_device_subinterface.go
@@ -118,7 +118,6 @@ func (d *DeviceSubinterfaceDataSource) Schema(ctx context.Context, req datasourc
},
"interface_name": schema.StringAttribute{
MarkdownDescription: "Name of the parent interface (fmc_device_physical_interface.example.name).",
- Optional: true,
Computed: true,
},
"sub_interface_id": schema.Int64Attribute{
diff --git a/internal/provider/data_source_fmc_device_subinterface_test.go b/internal/provider/data_source_fmc_device_subinterface_test.go
index e53183fb..de5c2de1 100644
--- a/internal/provider/data_source_fmc_device_subinterface_test.go
+++ b/internal/provider/data_source_fmc_device_subinterface_test.go
@@ -126,8 +126,8 @@ func testAccNamedDataSourceFmcDeviceSubinterfaceConfig() string {
config += `
data "fmc_device_subinterface" "test" {
- name = fmc_device_subinterface.test.name
device_id = var.device_id
+ name = fmc_device_subinterface.test.name
}
`
return config
diff --git a/internal/provider/data_source_fmc_device_vrf.go b/internal/provider/data_source_fmc_device_vrf.go
index cd98ffff..9727857b 100644
--- a/internal/provider/data_source_fmc_device_vrf.go
+++ b/internal/provider/data_source_fmc_device_vrf.go
@@ -152,7 +152,7 @@ func (d *DeviceVRFDataSource) Read(ctx context.Context, req datasource.ReadReque
offset := 0
limit := 1000
for page := 1; ; page++ {
- queryString := fmt.Sprintf("?limit=%d&offset=%d", limit, offset)
+ queryString := fmt.Sprintf("?limit=%d&offset=%d&expanded=true", limit, offset)
res, err := d.client.Get(config.getPath()+queryString, reqMods...)
if err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to retrieve objects, got error: %s", err))
diff --git a/internal/provider/data_source_fmc_device_vrf_test.go b/internal/provider/data_source_fmc_device_vrf_test.go
index 34b9277a..b09cb8b1 100644
--- a/internal/provider/data_source_fmc_device_vrf_test.go
+++ b/internal/provider/data_source_fmc_device_vrf_test.go
@@ -110,8 +110,8 @@ func testAccNamedDataSourceFmcDeviceVRFConfig() string {
config += `
data "fmc_device_vrf" "test" {
- name = fmc_device_vrf.test.name
device_id = var.device_id
+ name = fmc_device_vrf.test.name
}
`
return config
diff --git a/internal/provider/data_source_fmc_extended_acl.go b/internal/provider/data_source_fmc_extended_acl.go
index 64d748f9..989a69c2 100644
--- a/internal/provider/data_source_fmc_extended_acl.go
+++ b/internal/provider/data_source_fmc_extended_acl.go
@@ -228,7 +228,7 @@ func (d *ExtendedACLDataSource) Read(ctx context.Context, req datasource.ReadReq
offset := 0
limit := 1000
for page := 1; ; page++ {
- queryString := fmt.Sprintf("?limit=%d&offset=%d", limit, offset)
+ queryString := fmt.Sprintf("?limit=%d&offset=%d&expanded=true", limit, offset)
res, err := d.client.Get(config.getPath()+queryString, reqMods...)
if err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to retrieve objects, got error: %s", err))
diff --git a/internal/provider/data_source_fmc_fqdn_object.go b/internal/provider/data_source_fmc_fqdn_object.go
index f5037170..d4e308f1 100644
--- a/internal/provider/data_source_fmc_fqdn_object.go
+++ b/internal/provider/data_source_fmc_fqdn_object.go
@@ -136,7 +136,7 @@ func (d *FQDNObjectDataSource) Read(ctx context.Context, req datasource.ReadRequ
offset := 0
limit := 1000
for page := 1; ; page++ {
- queryString := fmt.Sprintf("?limit=%d&offset=%d", limit, offset)
+ queryString := fmt.Sprintf("?limit=%d&offset=%d&expanded=true", limit, offset)
res, err := d.client.Get(config.getPath()+queryString, reqMods...)
if err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to retrieve objects, got error: %s", err))
diff --git a/internal/provider/data_source_fmc_host.go b/internal/provider/data_source_fmc_host.go
index f09bc87e..046f514c 100644
--- a/internal/provider/data_source_fmc_host.go
+++ b/internal/provider/data_source_fmc_host.go
@@ -136,7 +136,7 @@ func (d *HostDataSource) Read(ctx context.Context, req datasource.ReadRequest, r
offset := 0
limit := 1000
for page := 1; ; page++ {
- queryString := fmt.Sprintf("?limit=%d&offset=%d", limit, offset)
+ queryString := fmt.Sprintf("?limit=%d&offset=%d&expanded=true", limit, offset)
res, err := d.client.Get(config.getPath()+queryString, reqMods...)
if err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to retrieve objects, got error: %s", err))
diff --git a/internal/provider/data_source_fmc_icmpv4_object.go b/internal/provider/data_source_fmc_icmpv4_object.go
index d7487ab2..f20496c6 100644
--- a/internal/provider/data_source_fmc_icmpv4_object.go
+++ b/internal/provider/data_source_fmc_icmpv4_object.go
@@ -140,7 +140,7 @@ func (d *ICMPv4ObjectDataSource) Read(ctx context.Context, req datasource.ReadRe
offset := 0
limit := 1000
for page := 1; ; page++ {
- queryString := fmt.Sprintf("?limit=%d&offset=%d", limit, offset)
+ queryString := fmt.Sprintf("?limit=%d&offset=%d&expanded=true", limit, offset)
res, err := d.client.Get(config.getPath()+queryString, reqMods...)
if err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to retrieve objects, got error: %s", err))
diff --git a/internal/provider/data_source_fmc_icmpv6_object.go b/internal/provider/data_source_fmc_icmpv6_object.go
index 7ad1dbaa..7245bac7 100644
--- a/internal/provider/data_source_fmc_icmpv6_object.go
+++ b/internal/provider/data_source_fmc_icmpv6_object.go
@@ -136,7 +136,7 @@ func (d *ICMPv6ObjectDataSource) Read(ctx context.Context, req datasource.ReadRe
offset := 0
limit := 1000
for page := 1; ; page++ {
- queryString := fmt.Sprintf("?limit=%d&offset=%d", limit, offset)
+ queryString := fmt.Sprintf("?limit=%d&offset=%d&expanded=true", limit, offset)
res, err := d.client.Get(config.getPath()+queryString, reqMods...)
if err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to retrieve objects, got error: %s", err))
diff --git a/internal/provider/data_source_fmc_interface_group.go b/internal/provider/data_source_fmc_interface_group.go
index eee9bf1d..92563e61 100644
--- a/internal/provider/data_source_fmc_interface_group.go
+++ b/internal/provider/data_source_fmc_interface_group.go
@@ -136,7 +136,7 @@ func (d *InterfaceGroupDataSource) Read(ctx context.Context, req datasource.Read
offset := 0
limit := 1000
for page := 1; ; page++ {
- queryString := fmt.Sprintf("?limit=%d&offset=%d", limit, offset)
+ queryString := fmt.Sprintf("?limit=%d&offset=%d&expanded=true", limit, offset)
res, err := d.client.Get(config.getPath()+queryString, reqMods...)
if err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to retrieve objects, got error: %s", err))
diff --git a/internal/provider/data_source_fmc_intrusion_policy.go b/internal/provider/data_source_fmc_intrusion_policy.go
index 06e0dda0..f6b1f9ee 100644
--- a/internal/provider/data_source_fmc_intrusion_policy.go
+++ b/internal/provider/data_source_fmc_intrusion_policy.go
@@ -132,7 +132,7 @@ func (d *IntrusionPolicyDataSource) Read(ctx context.Context, req datasource.Rea
offset := 0
limit := 1000
for page := 1; ; page++ {
- queryString := fmt.Sprintf("?limit=%d&offset=%d", limit, offset)
+ queryString := fmt.Sprintf("?limit=%d&offset=%d&expanded=true", limit, offset)
res, err := d.client.Get(config.getPath()+queryString, reqMods...)
if err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to retrieve objects, got error: %s", err))
diff --git a/internal/provider/data_source_fmc_network.go b/internal/provider/data_source_fmc_network.go
index 9fb6716e..d55782e5 100644
--- a/internal/provider/data_source_fmc_network.go
+++ b/internal/provider/data_source_fmc_network.go
@@ -136,7 +136,7 @@ func (d *NetworkDataSource) Read(ctx context.Context, req datasource.ReadRequest
offset := 0
limit := 1000
for page := 1; ; page++ {
- queryString := fmt.Sprintf("?limit=%d&offset=%d", limit, offset)
+ queryString := fmt.Sprintf("?limit=%d&offset=%d&expanded=true", limit, offset)
res, err := d.client.Get(config.getPath()+queryString, reqMods...)
if err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to retrieve objects, got error: %s", err))
diff --git a/internal/provider/data_source_fmc_network_analysis_policy.go b/internal/provider/data_source_fmc_network_analysis_policy.go
index 68cc8a45..9def5b24 100644
--- a/internal/provider/data_source_fmc_network_analysis_policy.go
+++ b/internal/provider/data_source_fmc_network_analysis_policy.go
@@ -132,7 +132,7 @@ func (d *NetworkAnalysisPolicyDataSource) Read(ctx context.Context, req datasour
offset := 0
limit := 1000
for page := 1; ; page++ {
- queryString := fmt.Sprintf("?limit=%d&offset=%d", limit, offset)
+ queryString := fmt.Sprintf("?limit=%d&offset=%d&expanded=true", limit, offset)
res, err := d.client.Get(config.getPath()+queryString, reqMods...)
if err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to retrieve objects, got error: %s", err))
diff --git a/internal/provider/data_source_fmc_port.go b/internal/provider/data_source_fmc_port.go
index 476ab8f3..cd8f2857 100644
--- a/internal/provider/data_source_fmc_port.go
+++ b/internal/provider/data_source_fmc_port.go
@@ -136,7 +136,7 @@ func (d *PortDataSource) Read(ctx context.Context, req datasource.ReadRequest, r
offset := 0
limit := 1000
for page := 1; ; page++ {
- queryString := fmt.Sprintf("?limit=%d&offset=%d", limit, offset)
+ queryString := fmt.Sprintf("?limit=%d&offset=%d&expanded=true", limit, offset)
res, err := d.client.Get(config.getPath()+queryString, reqMods...)
if err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to retrieve objects, got error: %s", err))
diff --git a/internal/provider/data_source_fmc_port_group.go b/internal/provider/data_source_fmc_port_group.go
index f237e6b7..ee326a50 100644
--- a/internal/provider/data_source_fmc_port_group.go
+++ b/internal/provider/data_source_fmc_port_group.go
@@ -148,7 +148,7 @@ func (d *PortGroupDataSource) Read(ctx context.Context, req datasource.ReadReque
offset := 0
limit := 1000
for page := 1; ; page++ {
- queryString := fmt.Sprintf("?limit=%d&offset=%d", limit, offset)
+ queryString := fmt.Sprintf("?limit=%d&offset=%d&expanded=true", limit, offset)
res, err := d.client.Get(config.getPath()+queryString, reqMods...)
if err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to retrieve objects, got error: %s", err))
diff --git a/internal/provider/data_source_fmc_range.go b/internal/provider/data_source_fmc_range.go
index 708d7c88..9c3229b2 100644
--- a/internal/provider/data_source_fmc_range.go
+++ b/internal/provider/data_source_fmc_range.go
@@ -132,7 +132,7 @@ func (d *RangeDataSource) Read(ctx context.Context, req datasource.ReadRequest,
offset := 0
limit := 1000
for page := 1; ; page++ {
- queryString := fmt.Sprintf("?limit=%d&offset=%d", limit, offset)
+ queryString := fmt.Sprintf("?limit=%d&offset=%d&expanded=true", limit, offset)
res, err := d.client.Get(config.getPath()+queryString, reqMods...)
if err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to retrieve objects, got error: %s", err))
diff --git a/internal/provider/data_source_fmc_security_zone.go b/internal/provider/data_source_fmc_security_zone.go
index b0a85143..eab4eb3e 100644
--- a/internal/provider/data_source_fmc_security_zone.go
+++ b/internal/provider/data_source_fmc_security_zone.go
@@ -75,7 +75,7 @@ func (d *SecurityZoneDataSource) Schema(ctx context.Context, req datasource.Sche
Optional: true,
Computed: true,
},
- "interface_mode": schema.StringAttribute{
+ "interface_type": schema.StringAttribute{
MarkdownDescription: "The mode of the associated interfaces, with the exception of mode ROUTED that corresponds to mode NONE of associated interfaces.",
Computed: true,
},
@@ -128,7 +128,7 @@ func (d *SecurityZoneDataSource) Read(ctx context.Context, req datasource.ReadRe
offset := 0
limit := 1000
for page := 1; ; page++ {
- queryString := fmt.Sprintf("?limit=%d&offset=%d", limit, offset)
+ queryString := fmt.Sprintf("?limit=%d&offset=%d&expanded=true", limit, offset)
res, err := d.client.Get(config.getPath()+queryString, reqMods...)
if err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to retrieve objects, got error: %s", err))
diff --git a/internal/provider/data_source_fmc_security_zone_test.go b/internal/provider/data_source_fmc_security_zone_test.go
index e40d04ab..abeebff9 100644
--- a/internal/provider/data_source_fmc_security_zone_test.go
+++ b/internal/provider/data_source_fmc_security_zone_test.go
@@ -31,7 +31,7 @@ import (
func TestAccDataSourceFmcSecurityZone(t *testing.T) {
var checks []resource.TestCheckFunc
checks = append(checks, resource.TestCheckResourceAttr("data.fmc_security_zone.test", "name", "security_zone_1"))
- checks = append(checks, resource.TestCheckResourceAttr("data.fmc_security_zone.test", "interface_mode", "ROUTED"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_security_zone.test", "interface_type", "ROUTED"))
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
@@ -59,7 +59,7 @@ func TestAccDataSourceFmcSecurityZone(t *testing.T) {
func testAccDataSourceFmcSecurityZoneConfig() string {
config := `resource "fmc_security_zone" "test" {` + "\n"
config += ` name = "security_zone_1"` + "\n"
- config += ` interface_mode = "ROUTED"` + "\n"
+ config += ` interface_type = "ROUTED"` + "\n"
config += `}` + "\n"
config += `
@@ -73,7 +73,7 @@ func testAccDataSourceFmcSecurityZoneConfig() string {
func testAccNamedDataSourceFmcSecurityZoneConfig() string {
config := `resource "fmc_security_zone" "test" {` + "\n"
config += ` name = "security_zone_1"` + "\n"
- config += ` interface_mode = "ROUTED"` + "\n"
+ config += ` interface_type = "ROUTED"` + "\n"
config += `}` + "\n"
config += `
diff --git a/internal/provider/data_source_fmc_security_zones.go b/internal/provider/data_source_fmc_security_zones.go
index af585607..70ba792c 100644
--- a/internal/provider/data_source_fmc_security_zones.go
+++ b/internal/provider/data_source_fmc_security_zones.go
@@ -74,7 +74,7 @@ func (d *SecurityZonesDataSource) Schema(ctx context.Context, req datasource.Sch
MarkdownDescription: "UUID of the managed Security Zone.",
Computed: true,
},
- "interface_mode": schema.StringAttribute{
+ "interface_type": schema.StringAttribute{
MarkdownDescription: "The mode of the associated interfaces, with the exception of mode ROUTED that corresponds to mode NONE of associated interfaces.",
Computed: true,
},
diff --git a/internal/provider/data_source_fmc_security_zones_test.go b/internal/provider/data_source_fmc_security_zones_test.go
index a421b59c..55b7708d 100644
--- a/internal/provider/data_source_fmc_security_zones_test.go
+++ b/internal/provider/data_source_fmc_security_zones_test.go
@@ -31,7 +31,7 @@ import (
func TestAccDataSourceFmcSecurityZones(t *testing.T) {
var checks []resource.TestCheckFunc
checks = append(checks, resource.TestCheckResourceAttrSet("data.fmc_security_zones.test", "items.security_zone_1.id"))
- checks = append(checks, resource.TestCheckResourceAttr("data.fmc_security_zones.test", "items.security_zone_1.interface_mode", "ROUTED"))
+ checks = append(checks, resource.TestCheckResourceAttr("data.fmc_security_zones.test", "items.security_zone_1.interface_type", "ROUTED"))
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
@@ -55,7 +55,7 @@ func TestAccDataSourceFmcSecurityZones(t *testing.T) {
func testAccDataSourceFmcSecurityZonesConfig() string {
config := `resource "fmc_security_zones" "test" {` + "\n"
config += ` items = { "security_zone_1" = {` + "\n"
- config += ` interface_mode = "ROUTED"` + "\n"
+ config += ` interface_type = "ROUTED"` + "\n"
config += ` }}` + "\n"
config += `}` + "\n"
diff --git a/internal/provider/data_source_fmc_sgt.go b/internal/provider/data_source_fmc_sgt.go
index b0d16268..cc6425b1 100644
--- a/internal/provider/data_source_fmc_sgt.go
+++ b/internal/provider/data_source_fmc_sgt.go
@@ -132,7 +132,7 @@ func (d *SGTDataSource) Read(ctx context.Context, req datasource.ReadRequest, re
offset := 0
limit := 1000
for page := 1; ; page++ {
- queryString := fmt.Sprintf("?limit=%d&offset=%d", limit, offset)
+ queryString := fmt.Sprintf("?limit=%d&offset=%d&expanded=true", limit, offset)
res, err := d.client.Get(config.getPath()+queryString, reqMods...)
if err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to retrieve objects, got error: %s", err))
diff --git a/internal/provider/data_source_fmc_snmp_alert.go b/internal/provider/data_source_fmc_snmp_alert.go
index 005b2a35..4c0be5f9 100644
--- a/internal/provider/data_source_fmc_snmp_alert.go
+++ b/internal/provider/data_source_fmc_snmp_alert.go
@@ -124,7 +124,7 @@ func (d *SNMPAlertDataSource) Read(ctx context.Context, req datasource.ReadReque
offset := 0
limit := 1000
for page := 1; ; page++ {
- queryString := fmt.Sprintf("?limit=%d&offset=%d", limit, offset)
+ queryString := fmt.Sprintf("?limit=%d&offset=%d&expanded=true", limit, offset)
res, err := d.client.Get(config.getPath()+queryString, reqMods...)
if err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to retrieve objects, got error: %s", err))
diff --git a/internal/provider/data_source_fmc_standard_acl.go b/internal/provider/data_source_fmc_standard_acl.go
index 7d342590..9a337777 100644
--- a/internal/provider/data_source_fmc_standard_acl.go
+++ b/internal/provider/data_source_fmc_standard_acl.go
@@ -164,7 +164,7 @@ func (d *StandardACLDataSource) Read(ctx context.Context, req datasource.ReadReq
offset := 0
limit := 1000
for page := 1; ; page++ {
- queryString := fmt.Sprintf("?limit=%d&offset=%d", limit, offset)
+ queryString := fmt.Sprintf("?limit=%d&offset=%d&expanded=true", limit, offset)
res, err := d.client.Get(config.getPath()+queryString, reqMods...)
if err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to retrieve objects, got error: %s", err))
diff --git a/internal/provider/data_source_fmc_syslog_alert.go b/internal/provider/data_source_fmc_syslog_alert.go
index 63ae174c..c66d9003 100644
--- a/internal/provider/data_source_fmc_syslog_alert.go
+++ b/internal/provider/data_source_fmc_syslog_alert.go
@@ -124,7 +124,7 @@ func (d *SyslogAlertDataSource) Read(ctx context.Context, req datasource.ReadReq
offset := 0
limit := 1000
for page := 1; ; page++ {
- queryString := fmt.Sprintf("?limit=%d&offset=%d", limit, offset)
+ queryString := fmt.Sprintf("?limit=%d&offset=%d&expanded=true", limit, offset)
res, err := d.client.Get(config.getPath()+queryString, reqMods...)
if err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to retrieve objects, got error: %s", err))
diff --git a/internal/provider/data_source_fmc_url.go b/internal/provider/data_source_fmc_url.go
index 099ec2d3..7923db25 100644
--- a/internal/provider/data_source_fmc_url.go
+++ b/internal/provider/data_source_fmc_url.go
@@ -132,7 +132,7 @@ func (d *URLDataSource) Read(ctx context.Context, req datasource.ReadRequest, re
offset := 0
limit := 1000
for page := 1; ; page++ {
- queryString := fmt.Sprintf("?limit=%d&offset=%d", limit, offset)
+ queryString := fmt.Sprintf("?limit=%d&offset=%d&expanded=true", limit, offset)
res, err := d.client.Get(config.getPath()+queryString, reqMods...)
if err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to retrieve objects, got error: %s", err))
diff --git a/internal/provider/data_source_fmc_url_group.go b/internal/provider/data_source_fmc_url_group.go
index bde66899..f5467138 100644
--- a/internal/provider/data_source_fmc_url_group.go
+++ b/internal/provider/data_source_fmc_url_group.go
@@ -152,7 +152,7 @@ func (d *URLGroupDataSource) Read(ctx context.Context, req datasource.ReadReques
offset := 0
limit := 1000
for page := 1; ; page++ {
- queryString := fmt.Sprintf("?limit=%d&offset=%d", limit, offset)
+ queryString := fmt.Sprintf("?limit=%d&offset=%d&expanded=true", limit, offset)
res, err := d.client.Get(config.getPath()+queryString, reqMods...)
if err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to retrieve objects, got error: %s", err))
diff --git a/internal/provider/data_source_fmc_variable_set.go b/internal/provider/data_source_fmc_variable_set.go
index 657a7fb8..400a4b7f 100644
--- a/internal/provider/data_source_fmc_variable_set.go
+++ b/internal/provider/data_source_fmc_variable_set.go
@@ -128,7 +128,7 @@ func (d *VariableSetDataSource) Read(ctx context.Context, req datasource.ReadReq
offset := 0
limit := 1000
for page := 1; ; page++ {
- queryString := fmt.Sprintf("?limit=%d&offset=%d", limit, offset)
+ queryString := fmt.Sprintf("?limit=%d&offset=%d&expanded=true", limit, offset)
res, err := d.client.Get(config.getPath()+queryString, reqMods...)
if err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to retrieve objects, got error: %s", err))
diff --git a/internal/provider/data_source_fmc_vlan_tag.go b/internal/provider/data_source_fmc_vlan_tag.go
index c7b9943b..03cb48db 100644
--- a/internal/provider/data_source_fmc_vlan_tag.go
+++ b/internal/provider/data_source_fmc_vlan_tag.go
@@ -136,7 +136,7 @@ func (d *VLANTagDataSource) Read(ctx context.Context, req datasource.ReadRequest
offset := 0
limit := 1000
for page := 1; ; page++ {
- queryString := fmt.Sprintf("?limit=%d&offset=%d", limit, offset)
+ queryString := fmt.Sprintf("?limit=%d&offset=%d&expanded=true", limit, offset)
res, err := d.client.Get(config.getPath()+queryString, reqMods...)
if err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to retrieve objects, got error: %s", err))
diff --git a/internal/provider/data_source_fmc_vlan_tag_group.go b/internal/provider/data_source_fmc_vlan_tag_group.go
index 1f7d19ea..19c436bc 100644
--- a/internal/provider/data_source_fmc_vlan_tag_group.go
+++ b/internal/provider/data_source_fmc_vlan_tag_group.go
@@ -156,7 +156,7 @@ func (d *VLANTagGroupDataSource) Read(ctx context.Context, req datasource.ReadRe
offset := 0
limit := 1000
for page := 1; ; page++ {
- queryString := fmt.Sprintf("?limit=%d&offset=%d", limit, offset)
+ queryString := fmt.Sprintf("?limit=%d&offset=%d&expanded=true", limit, offset)
res, err := d.client.Get(config.getPath()+queryString, reqMods...)
if err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to retrieve objects, got error: %s", err))
diff --git a/internal/provider/model_fmc_bfd_template.go b/internal/provider/model_fmc_bfd_template.go
new file mode 100644
index 00000000..1cab1185
--- /dev/null
+++ b/internal/provider/model_fmc_bfd_template.go
@@ -0,0 +1,251 @@
+// Copyright © 2023 Cisco Systems, Inc. and its affiliates.
+// All rights reserved.
+//
+// Licensed under the Mozilla Public License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://mozilla.org/MPL/2.0/
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// SPDX-License-Identifier: MPL-2.0
+
+package provider
+
+// Section below is generated&owned by "gen/generator.go". //template:begin imports
+import (
+ "context"
+
+ "github.com/hashicorp/terraform-plugin-framework/types"
+ "github.com/tidwall/gjson"
+ "github.com/tidwall/sjson"
+)
+
+// End of section. //template:end imports
+
+// Section below is generated&owned by "gen/generator.go". //template:begin types
+
+type BFDTemplate struct {
+ Id types.String `tfsdk:"id"`
+ Domain types.String `tfsdk:"domain"`
+ Name types.String `tfsdk:"name"`
+ Type types.String `tfsdk:"type"`
+ HopType types.String `tfsdk:"hop_type"`
+ Echo types.String `tfsdk:"echo"`
+ IntervalTime types.String `tfsdk:"interval_time"`
+ MinTransmit types.Int64 `tfsdk:"min_transmit"`
+ TxRxMultiplier types.Int64 `tfsdk:"tx_rx_multiplier"`
+ MinReceive types.Int64 `tfsdk:"min_receive"`
+ AuthenticationPassword types.String `tfsdk:"authentication_password"`
+ AuthenticationKeyId types.Int64 `tfsdk:"authentication_key_id"`
+ AuthenticationType types.String `tfsdk:"authentication_type"`
+}
+
+// End of section. //template:end types
+
+// Section below is generated&owned by "gen/generator.go". //template:begin getPath
+
+func (data BFDTemplate) getPath() string {
+ return "/api/fmc_config/v1/domain/{DOMAIN_UUID}/object/bfdtemplates"
+}
+
+// End of section. //template:end getPath
+
+// Section below is generated&owned by "gen/generator.go". //template:begin toBody
+
+func (data BFDTemplate) toBody(ctx context.Context, state BFDTemplate) string {
+ body := ""
+ if data.Id.ValueString() != "" {
+ body, _ = sjson.Set(body, "id", data.Id.ValueString())
+ }
+ if !data.Name.IsNull() {
+ body, _ = sjson.Set(body, "name", data.Name.ValueString())
+ }
+ if !data.HopType.IsNull() {
+ body, _ = sjson.Set(body, "hopType", data.HopType.ValueString())
+ }
+ if !data.Echo.IsNull() {
+ body, _ = sjson.Set(body, "echo", data.Echo.ValueString())
+ }
+ if !data.IntervalTime.IsNull() {
+ body, _ = sjson.Set(body, "txRxInterval", data.IntervalTime.ValueString())
+ }
+ if !data.MinTransmit.IsNull() {
+ body, _ = sjson.Set(body, "minTransmit", data.MinTransmit.ValueInt64())
+ }
+ if !data.TxRxMultiplier.IsNull() {
+ body, _ = sjson.Set(body, "txRxMultiplier", data.TxRxMultiplier.ValueInt64())
+ }
+ if !data.MinReceive.IsNull() {
+ body, _ = sjson.Set(body, "minReceive", data.MinReceive.ValueInt64())
+ }
+ if !data.AuthenticationPassword.IsNull() {
+ body, _ = sjson.Set(body, "authentication.authKey", data.AuthenticationPassword.ValueString())
+ }
+ if !data.AuthenticationKeyId.IsNull() {
+ body, _ = sjson.Set(body, "authentication.authKeyId", data.AuthenticationKeyId.ValueInt64())
+ }
+ if !data.AuthenticationType.IsNull() {
+ body, _ = sjson.Set(body, "authentication.authType", data.AuthenticationType.ValueString())
+ }
+ return body
+}
+
+// End of section. //template:end toBody
+
+// Section below is generated&owned by "gen/generator.go". //template:begin fromBody
+
+func (data *BFDTemplate) fromBody(ctx context.Context, res gjson.Result) {
+ if value := res.Get("name"); value.Exists() {
+ data.Name = types.StringValue(value.String())
+ } else {
+ data.Name = types.StringNull()
+ }
+ if value := res.Get("type"); value.Exists() {
+ data.Type = types.StringValue(value.String())
+ } else {
+ data.Type = types.StringNull()
+ }
+ if value := res.Get("hopType"); value.Exists() {
+ data.HopType = types.StringValue(value.String())
+ } else {
+ data.HopType = types.StringNull()
+ }
+ if value := res.Get("echo"); value.Exists() {
+ data.Echo = types.StringValue(value.String())
+ } else {
+ data.Echo = types.StringNull()
+ }
+ if value := res.Get("txRxInterval"); value.Exists() {
+ data.IntervalTime = types.StringValue(value.String())
+ } else {
+ data.IntervalTime = types.StringNull()
+ }
+ if value := res.Get("minTransmit"); value.Exists() {
+ data.MinTransmit = types.Int64Value(value.Int())
+ } else {
+ data.MinTransmit = types.Int64Null()
+ }
+ if value := res.Get("txRxMultiplier"); value.Exists() {
+ data.TxRxMultiplier = types.Int64Value(value.Int())
+ } else {
+ data.TxRxMultiplier = types.Int64Null()
+ }
+ if value := res.Get("minReceive"); value.Exists() {
+ data.MinReceive = types.Int64Value(value.Int())
+ } else {
+ data.MinReceive = types.Int64Null()
+ }
+ if value := res.Get("authentication.authKey"); value.Exists() {
+ data.AuthenticationPassword = types.StringValue(value.String())
+ } else {
+ data.AuthenticationPassword = types.StringNull()
+ }
+ if value := res.Get("authentication.authKeyId"); value.Exists() {
+ data.AuthenticationKeyId = types.Int64Value(value.Int())
+ } else {
+ data.AuthenticationKeyId = types.Int64Null()
+ }
+ if value := res.Get("authentication.authType"); value.Exists() {
+ data.AuthenticationType = types.StringValue(value.String())
+ } else {
+ data.AuthenticationType = types.StringNull()
+ }
+}
+
+// End of section. //template:end fromBody
+
+// Section below is generated&owned by "gen/generator.go". //template:begin fromBodyPartial
+
+// fromBodyPartial reads values from a gjson.Result into a tfstate model. It ignores null attributes in order to
+// uncouple the provider from the exact values that the backend API might summon to replace nulls. (Such behavior might
+// easily change across versions of the backend API.) For List/Set/Map attributes, the func only updates the
+// "managed" elements, instead of all elements.
+func (data *BFDTemplate) fromBodyPartial(ctx context.Context, res gjson.Result) {
+ if value := res.Get("name"); value.Exists() && !data.Name.IsNull() {
+ data.Name = types.StringValue(value.String())
+ } else {
+ data.Name = types.StringNull()
+ }
+ if value := res.Get("type"); value.Exists() && !data.Type.IsNull() {
+ data.Type = types.StringValue(value.String())
+ } else {
+ data.Type = types.StringNull()
+ }
+ if value := res.Get("hopType"); value.Exists() && !data.HopType.IsNull() {
+ data.HopType = types.StringValue(value.String())
+ } else {
+ data.HopType = types.StringNull()
+ }
+ if value := res.Get("echo"); value.Exists() && !data.Echo.IsNull() {
+ data.Echo = types.StringValue(value.String())
+ } else {
+ data.Echo = types.StringNull()
+ }
+ if value := res.Get("txRxInterval"); value.Exists() && !data.IntervalTime.IsNull() {
+ data.IntervalTime = types.StringValue(value.String())
+ } else {
+ data.IntervalTime = types.StringNull()
+ }
+ if value := res.Get("minTransmit"); value.Exists() && !data.MinTransmit.IsNull() {
+ data.MinTransmit = types.Int64Value(value.Int())
+ } else {
+ data.MinTransmit = types.Int64Null()
+ }
+ if value := res.Get("txRxMultiplier"); value.Exists() && !data.TxRxMultiplier.IsNull() {
+ data.TxRxMultiplier = types.Int64Value(value.Int())
+ } else {
+ data.TxRxMultiplier = types.Int64Null()
+ }
+ if value := res.Get("minReceive"); value.Exists() && !data.MinReceive.IsNull() {
+ data.MinReceive = types.Int64Value(value.Int())
+ } else {
+ data.MinReceive = types.Int64Null()
+ }
+ if value := res.Get("authentication.authKey"); value.Exists() && !data.AuthenticationPassword.IsNull() {
+ data.AuthenticationPassword = types.StringValue(value.String())
+ } else {
+ data.AuthenticationPassword = types.StringNull()
+ }
+ if value := res.Get("authentication.authKeyId"); value.Exists() && !data.AuthenticationKeyId.IsNull() {
+ data.AuthenticationKeyId = types.Int64Value(value.Int())
+ } else {
+ data.AuthenticationKeyId = types.Int64Null()
+ }
+ if value := res.Get("authentication.authType"); value.Exists() && !data.AuthenticationType.IsNull() {
+ data.AuthenticationType = types.StringValue(value.String())
+ } else {
+ data.AuthenticationType = types.StringNull()
+ }
+}
+
+// End of section. //template:end fromBodyPartial
+
+// Section below is generated&owned by "gen/generator.go". //template:begin fromBodyUnknowns
+
+// fromBodyUnknowns updates the Unknown Computed tfstate values from a JSON.
+// Known values are not changed (usual for Computed attributes with UseStateForUnknown or with Default).
+func (data *BFDTemplate) fromBodyUnknowns(ctx context.Context, res gjson.Result) {
+ if data.Type.IsUnknown() {
+ if value := res.Get("type"); value.Exists() {
+ data.Type = types.StringValue(value.String())
+ } else {
+ data.Type = types.StringNull()
+ }
+ }
+}
+
+// End of section. //template:end fromBodyUnknowns
+
+// Section below is generated&owned by "gen/generator.go". //template:begin Clone
+
+// End of section. //template:end Clone
+
+// Section below is generated&owned by "gen/generator.go". //template:begin toBodyNonBulk
+
+// End of section. //template:end toBodyNonBulk
diff --git a/internal/provider/model_fmc_bgd_template.go b/internal/provider/model_fmc_bgd_template.go
new file mode 100644
index 00000000..eac1b752
--- /dev/null
+++ b/internal/provider/model_fmc_bgd_template.go
@@ -0,0 +1,209 @@
+// Copyright © 2023 Cisco Systems, Inc. and its affiliates.
+// All rights reserved.
+//
+// Licensed under the Mozilla Public License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://mozilla.org/MPL/2.0/
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// SPDX-License-Identifier: MPL-2.0
+
+package provider
+
+// Section below is generated&owned by "gen/generator.go". //template:begin imports
+import (
+ "context"
+
+ "github.com/hashicorp/terraform-plugin-framework/types"
+ "github.com/tidwall/gjson"
+ "github.com/tidwall/sjson"
+)
+
+// End of section. //template:end imports
+
+// Section below is generated&owned by "gen/generator.go". //template:begin types
+
+type BGDTemplate struct {
+ Id types.String `tfsdk:"id"`
+ Domain types.String `tfsdk:"domain"`
+ Name types.String `tfsdk:"name"`
+ Type types.String `tfsdk:"type"`
+ HopType types.String `tfsdk:"hop_type"`
+ Echo types.String `tfsdk:"echo"`
+ IntervalTime types.String `tfsdk:"interval_time"`
+ MinTransmit types.Int64 `tfsdk:"min_transmit"`
+ TxRxMultiplier types.Int64 `tfsdk:"tx_rx_multiplier"`
+ MinReceive types.Int64 `tfsdk:"min_receive"`
+}
+
+// End of section. //template:end types
+
+// Section below is generated&owned by "gen/generator.go". //template:begin getPath
+
+func (data BGDTemplate) getPath() string {
+ return "/api/fmc_config/v1/domain/{DOMAIN_UUID}/object/bfdtemplates"
+}
+
+// End of section. //template:end getPath
+
+// Section below is generated&owned by "gen/generator.go". //template:begin toBody
+
+func (data BGDTemplate) toBody(ctx context.Context, state BGDTemplate) string {
+ body := ""
+ if data.Id.ValueString() != "" {
+ body, _ = sjson.Set(body, "id", data.Id.ValueString())
+ }
+ if !data.Name.IsNull() {
+ body, _ = sjson.Set(body, "name", data.Name.ValueString())
+ }
+ if !data.HopType.IsNull() {
+ body, _ = sjson.Set(body, "hopType", data.HopType.ValueString())
+ }
+ if !data.Echo.IsNull() {
+ body, _ = sjson.Set(body, "echo", data.Echo.ValueString())
+ }
+ if !data.IntervalTime.IsNull() {
+ body, _ = sjson.Set(body, "txRxInterval", data.IntervalTime.ValueString())
+ }
+ if !data.MinTransmit.IsNull() {
+ body, _ = sjson.Set(body, "minTransmit", data.MinTransmit.ValueInt64())
+ }
+ if !data.TxRxMultiplier.IsNull() {
+ body, _ = sjson.Set(body, "txRxMultiplier", data.TxRxMultiplier.ValueInt64())
+ }
+ if !data.MinReceive.IsNull() {
+ body, _ = sjson.Set(body, "minReceive", data.MinReceive.ValueInt64())
+ }
+ return body
+}
+
+// End of section. //template:end toBody
+
+// Section below is generated&owned by "gen/generator.go". //template:begin fromBody
+
+func (data *BGDTemplate) fromBody(ctx context.Context, res gjson.Result) {
+ if value := res.Get("name"); value.Exists() {
+ data.Name = types.StringValue(value.String())
+ } else {
+ data.Name = types.StringNull()
+ }
+ if value := res.Get("type"); value.Exists() {
+ data.Type = types.StringValue(value.String())
+ } else {
+ data.Type = types.StringNull()
+ }
+ if value := res.Get("hopType"); value.Exists() {
+ data.HopType = types.StringValue(value.String())
+ } else {
+ data.HopType = types.StringNull()
+ }
+ if value := res.Get("echo"); value.Exists() {
+ data.Echo = types.StringValue(value.String())
+ } else {
+ data.Echo = types.StringNull()
+ }
+ if value := res.Get("txRxInterval"); value.Exists() {
+ data.IntervalTime = types.StringValue(value.String())
+ } else {
+ data.IntervalTime = types.StringNull()
+ }
+ if value := res.Get("minTransmit"); value.Exists() {
+ data.MinTransmit = types.Int64Value(value.Int())
+ } else {
+ data.MinTransmit = types.Int64Value(100000)
+ }
+ if value := res.Get("txRxMultiplier"); value.Exists() {
+ data.TxRxMultiplier = types.Int64Value(value.Int())
+ } else {
+ data.TxRxMultiplier = types.Int64Value(3)
+ }
+ if value := res.Get("minReceive"); value.Exists() {
+ data.MinReceive = types.Int64Value(value.Int())
+ } else {
+ data.MinReceive = types.Int64Value(100000)
+ }
+}
+
+// End of section. //template:end fromBody
+
+// Section below is generated&owned by "gen/generator.go". //template:begin fromBodyPartial
+
+// fromBodyPartial reads values from a gjson.Result into a tfstate model. It ignores null attributes in order to
+// uncouple the provider from the exact values that the backend API might summon to replace nulls. (Such behavior might
+// easily change across versions of the backend API.) For List/Set/Map attributes, the func only updates the
+// "managed" elements, instead of all elements.
+func (data *BGDTemplate) fromBodyPartial(ctx context.Context, res gjson.Result) {
+ if value := res.Get("name"); value.Exists() && !data.Name.IsNull() {
+ data.Name = types.StringValue(value.String())
+ } else {
+ data.Name = types.StringNull()
+ }
+ if value := res.Get("type"); value.Exists() && !data.Type.IsNull() {
+ data.Type = types.StringValue(value.String())
+ } else {
+ data.Type = types.StringNull()
+ }
+ if value := res.Get("hopType"); value.Exists() && !data.HopType.IsNull() {
+ data.HopType = types.StringValue(value.String())
+ } else {
+ data.HopType = types.StringNull()
+ }
+ if value := res.Get("echo"); value.Exists() && !data.Echo.IsNull() {
+ data.Echo = types.StringValue(value.String())
+ } else {
+ data.Echo = types.StringNull()
+ }
+ if value := res.Get("txRxInterval"); value.Exists() && !data.IntervalTime.IsNull() {
+ data.IntervalTime = types.StringValue(value.String())
+ } else {
+ data.IntervalTime = types.StringNull()
+ }
+ if value := res.Get("minTransmit"); value.Exists() && !data.MinTransmit.IsNull() {
+ data.MinTransmit = types.Int64Value(value.Int())
+ } else if data.MinTransmit.ValueInt64() != 100000 {
+ data.MinTransmit = types.Int64Null()
+ }
+ if value := res.Get("txRxMultiplier"); value.Exists() && !data.TxRxMultiplier.IsNull() {
+ data.TxRxMultiplier = types.Int64Value(value.Int())
+ } else if data.TxRxMultiplier.ValueInt64() != 3 {
+ data.TxRxMultiplier = types.Int64Null()
+ }
+ if value := res.Get("minReceive"); value.Exists() && !data.MinReceive.IsNull() {
+ data.MinReceive = types.Int64Value(value.Int())
+ } else if data.MinReceive.ValueInt64() != 100000 {
+ data.MinReceive = types.Int64Null()
+ }
+}
+
+// End of section. //template:end fromBodyPartial
+
+// Section below is generated&owned by "gen/generator.go". //template:begin fromBodyUnknowns
+
+// fromBodyUnknowns updates the Unknown Computed tfstate values from a JSON.
+// Known values are not changed (usual for Computed attributes with UseStateForUnknown or with Default).
+func (data *BGDTemplate) fromBodyUnknowns(ctx context.Context, res gjson.Result) {
+ if data.Type.IsUnknown() {
+ if value := res.Get("type"); value.Exists() {
+ data.Type = types.StringValue(value.String())
+ } else {
+ data.Type = types.StringNull()
+ }
+ }
+}
+
+// End of section. //template:end fromBodyUnknowns
+
+// Section below is generated&owned by "gen/generator.go". //template:begin Clone
+
+// End of section. //template:end Clone
+
+// Section below is generated&owned by "gen/generator.go". //template:begin toBodyNonBulk
+
+// End of section. //template:end toBodyNonBulk
diff --git a/internal/provider/model_fmc_device_bfd.go b/internal/provider/model_fmc_device_bfd.go
new file mode 100644
index 00000000..7f443915
--- /dev/null
+++ b/internal/provider/model_fmc_device_bfd.go
@@ -0,0 +1,212 @@
+// Copyright © 2023 Cisco Systems, Inc. and its affiliates.
+// All rights reserved.
+//
+// Licensed under the Mozilla Public License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://mozilla.org/MPL/2.0/
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// SPDX-License-Identifier: MPL-2.0
+
+package provider
+
+// Section below is generated&owned by "gen/generator.go". //template:begin imports
+import (
+ "context"
+ "fmt"
+ "net/url"
+
+ "github.com/hashicorp/terraform-plugin-framework/types"
+ "github.com/tidwall/gjson"
+ "github.com/tidwall/sjson"
+)
+
+// End of section. //template:end imports
+
+// Section below is generated&owned by "gen/generator.go". //template:begin types
+
+type DeviceBFD struct {
+ Id types.String `tfsdk:"id"`
+ Domain types.String `tfsdk:"domain"`
+ DeviceId types.String `tfsdk:"device_id"`
+ Type types.String `tfsdk:"type"`
+ HopType types.String `tfsdk:"hop_type"`
+ BfdTemplateId types.String `tfsdk:"bfd_template_id"`
+ InterfaceLogicalName types.String `tfsdk:"interface_logical_name"`
+ DestinationHostObjectId types.String `tfsdk:"destination_host_object_id"`
+ SourceHostObjectId types.String `tfsdk:"source_host_object_id"`
+ InterfaceId types.String `tfsdk:"interface_id"`
+ SlowTimer types.Int64 `tfsdk:"slow_timer"`
+}
+
+// End of section. //template:end types
+
+// Section below is generated&owned by "gen/generator.go". //template:begin getPath
+
+func (data DeviceBFD) getPath() string {
+ return fmt.Sprintf("/api/fmc_config/v1/domain/{DOMAIN_UUID}/devices/devicerecords/%v/routing/bfdpolicies", url.QueryEscape(data.DeviceId.ValueString()))
+}
+
+// End of section. //template:end getPath
+
+// Section below is generated&owned by "gen/generator.go". //template:begin toBody
+
+func (data DeviceBFD) toBody(ctx context.Context, state DeviceBFD) string {
+ body := ""
+ if data.Id.ValueString() != "" {
+ body, _ = sjson.Set(body, "id", data.Id.ValueString())
+ }
+ if !data.HopType.IsNull() {
+ body, _ = sjson.Set(body, "hopType", data.HopType.ValueString())
+ }
+ if !data.BfdTemplateId.IsNull() {
+ body, _ = sjson.Set(body, "template.id", data.BfdTemplateId.ValueString())
+ }
+ if !data.InterfaceLogicalName.IsNull() {
+ body, _ = sjson.Set(body, "interface.ifname", data.InterfaceLogicalName.ValueString())
+ }
+ if !data.DestinationHostObjectId.IsNull() {
+ body, _ = sjson.Set(body, "destinationAddress.id", data.DestinationHostObjectId.ValueString())
+ }
+ if !data.SourceHostObjectId.IsNull() {
+ body, _ = sjson.Set(body, "sourceAddress.id", data.SourceHostObjectId.ValueString())
+ }
+ if !data.InterfaceId.IsNull() {
+ body, _ = sjson.Set(body, "interface.id", data.InterfaceId.ValueString())
+ }
+ if !data.SlowTimer.IsNull() {
+ body, _ = sjson.Set(body, "slowTimer", data.SlowTimer.ValueInt64())
+ }
+ return body
+}
+
+// End of section. //template:end toBody
+
+// Section below is generated&owned by "gen/generator.go". //template:begin fromBody
+
+func (data *DeviceBFD) fromBody(ctx context.Context, res gjson.Result) {
+ if value := res.Get("type"); value.Exists() {
+ data.Type = types.StringValue(value.String())
+ } else {
+ data.Type = types.StringNull()
+ }
+ if value := res.Get("hopType"); value.Exists() {
+ data.HopType = types.StringValue(value.String())
+ } else {
+ data.HopType = types.StringNull()
+ }
+ if value := res.Get("template.id"); value.Exists() {
+ data.BfdTemplateId = types.StringValue(value.String())
+ } else {
+ data.BfdTemplateId = types.StringNull()
+ }
+ if value := res.Get("interface.ifname"); value.Exists() {
+ data.InterfaceLogicalName = types.StringValue(value.String())
+ } else {
+ data.InterfaceLogicalName = types.StringNull()
+ }
+ if value := res.Get("destinationAddress.id"); value.Exists() {
+ data.DestinationHostObjectId = types.StringValue(value.String())
+ } else {
+ data.DestinationHostObjectId = types.StringNull()
+ }
+ if value := res.Get("sourceAddress.id"); value.Exists() {
+ data.SourceHostObjectId = types.StringValue(value.String())
+ } else {
+ data.SourceHostObjectId = types.StringNull()
+ }
+ if value := res.Get("interface.id"); value.Exists() {
+ data.InterfaceId = types.StringValue(value.String())
+ } else {
+ data.InterfaceId = types.StringNull()
+ }
+ if value := res.Get("slowTimer"); value.Exists() {
+ data.SlowTimer = types.Int64Value(value.Int())
+ } else {
+ data.SlowTimer = types.Int64Value(1000)
+ }
+}
+
+// End of section. //template:end fromBody
+
+// Section below is generated&owned by "gen/generator.go". //template:begin fromBodyPartial
+
+// fromBodyPartial reads values from a gjson.Result into a tfstate model. It ignores null attributes in order to
+// uncouple the provider from the exact values that the backend API might summon to replace nulls. (Such behavior might
+// easily change across versions of the backend API.) For List/Set/Map attributes, the func only updates the
+// "managed" elements, instead of all elements.
+func (data *DeviceBFD) fromBodyPartial(ctx context.Context, res gjson.Result) {
+ if value := res.Get("type"); value.Exists() && !data.Type.IsNull() {
+ data.Type = types.StringValue(value.String())
+ } else {
+ data.Type = types.StringNull()
+ }
+ if value := res.Get("hopType"); value.Exists() && !data.HopType.IsNull() {
+ data.HopType = types.StringValue(value.String())
+ } else {
+ data.HopType = types.StringNull()
+ }
+ if value := res.Get("template.id"); value.Exists() && !data.BfdTemplateId.IsNull() {
+ data.BfdTemplateId = types.StringValue(value.String())
+ } else {
+ data.BfdTemplateId = types.StringNull()
+ }
+ if value := res.Get("interface.ifname"); value.Exists() && !data.InterfaceLogicalName.IsNull() {
+ data.InterfaceLogicalName = types.StringValue(value.String())
+ } else {
+ data.InterfaceLogicalName = types.StringNull()
+ }
+ if value := res.Get("destinationAddress.id"); value.Exists() && !data.DestinationHostObjectId.IsNull() {
+ data.DestinationHostObjectId = types.StringValue(value.String())
+ } else {
+ data.DestinationHostObjectId = types.StringNull()
+ }
+ if value := res.Get("sourceAddress.id"); value.Exists() && !data.SourceHostObjectId.IsNull() {
+ data.SourceHostObjectId = types.StringValue(value.String())
+ } else {
+ data.SourceHostObjectId = types.StringNull()
+ }
+ if value := res.Get("interface.id"); value.Exists() && !data.InterfaceId.IsNull() {
+ data.InterfaceId = types.StringValue(value.String())
+ } else {
+ data.InterfaceId = types.StringNull()
+ }
+ if value := res.Get("slowTimer"); value.Exists() && !data.SlowTimer.IsNull() {
+ data.SlowTimer = types.Int64Value(value.Int())
+ } else if data.SlowTimer.ValueInt64() != 1000 {
+ data.SlowTimer = types.Int64Null()
+ }
+}
+
+// End of section. //template:end fromBodyPartial
+
+// Section below is generated&owned by "gen/generator.go". //template:begin fromBodyUnknowns
+
+// fromBodyUnknowns updates the Unknown Computed tfstate values from a JSON.
+// Known values are not changed (usual for Computed attributes with UseStateForUnknown or with Default).
+func (data *DeviceBFD) fromBodyUnknowns(ctx context.Context, res gjson.Result) {
+ if data.Type.IsUnknown() {
+ if value := res.Get("type"); value.Exists() {
+ data.Type = types.StringValue(value.String())
+ } else {
+ data.Type = types.StringNull()
+ }
+ }
+}
+
+// End of section. //template:end fromBodyUnknowns
+
+// Section below is generated&owned by "gen/generator.go". //template:begin Clone
+
+// End of section. //template:end Clone
+
+// Section below is generated&owned by "gen/generator.go". //template:begin toBodyNonBulk
+
+// End of section. //template:end toBodyNonBulk
diff --git a/internal/provider/model_fmc_device_bgp.go b/internal/provider/model_fmc_device_bgp.go
new file mode 100644
index 00000000..93d3150f
--- /dev/null
+++ b/internal/provider/model_fmc_device_bgp.go
@@ -0,0 +1,1797 @@
+// Copyright © 2023 Cisco Systems, Inc. and its affiliates.
+// All rights reserved.
+//
+// Licensed under the Mozilla Public License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://mozilla.org/MPL/2.0/
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// SPDX-License-Identifier: MPL-2.0
+
+package provider
+
+// Section below is generated&owned by "gen/generator.go". //template:begin imports
+import (
+ "context"
+ "fmt"
+ "net/url"
+ "slices"
+
+ "github.com/hashicorp/terraform-plugin-framework/types"
+ "github.com/hashicorp/terraform-plugin-log/tflog"
+ "github.com/tidwall/gjson"
+ "github.com/tidwall/sjson"
+)
+
+// End of section. //template:end imports
+
+// Section below is generated&owned by "gen/generator.go". //template:begin types
+
+type DeviceBGP struct {
+ Id types.String `tfsdk:"id"`
+ Domain types.String `tfsdk:"domain"`
+ DeviceId types.String `tfsdk:"device_id"`
+ Name types.String `tfsdk:"name"`
+ Type types.String `tfsdk:"type"`
+ AsNumber types.String `tfsdk:"as_number"`
+ Ipv4AddressFamilyType types.String `tfsdk:"ipv4_address_family_type"`
+ Ipv4LearnedRouteMapId types.String `tfsdk:"ipv4_learned_route_map_id"`
+ Ipv4DefaultInformationOrginate types.Bool `tfsdk:"ipv4_default_information_orginate"`
+ Ipv4AutoAummary types.Bool `tfsdk:"ipv4_auto_aummary"`
+ Ipv4BgpSupressInactive types.Bool `tfsdk:"ipv4_bgp_supress_inactive"`
+ Ipv4Synchronization types.Bool `tfsdk:"ipv4_synchronization"`
+ Ipv4BgpRedistributeInternal types.Bool `tfsdk:"ipv4_bgp_redistribute_internal"`
+ Ipv4ExternalDistance types.Int64 `tfsdk:"ipv4_external_distance"`
+ Ipv4InternalDistance types.Int64 `tfsdk:"ipv4_internal_distance"`
+ Ipv4LocalDistance types.Int64 `tfsdk:"ipv4_local_distance"`
+ Ipv4ForwardPacketsOverMultipathIbgp types.Int64 `tfsdk:"ipv4_forward_packets_over_multipath_ibgp"`
+ Ipv4ForwardPacketsOverMultipathEbgp types.Int64 `tfsdk:"ipv4_forward_packets_over_multipath_ebgp"`
+ Ipv4Neighbors []DeviceBGPIpv4Neighbors `tfsdk:"ipv4_neighbors"`
+ Ipv4AggregateAddresses []DeviceBGPIpv4AggregateAddresses `tfsdk:"ipv4_aggregate_addresses"`
+ Ipv4Filterings []DeviceBGPIpv4Filterings `tfsdk:"ipv4_filterings"`
+ Ipv4Networks []DeviceBGPIpv4Networks `tfsdk:"ipv4_networks"`
+ Ipv4Redistributions []DeviceBGPIpv4Redistributions `tfsdk:"ipv4_redistributions"`
+ Ipv4RouteInjections []DeviceBGPIpv4RouteInjections `tfsdk:"ipv4_route_injections"`
+}
+
+type DeviceBGPIpv4Neighbors struct {
+ NeighborAddress types.String `tfsdk:"neighbor_address"`
+ NeighborRemoteAs types.String `tfsdk:"neighbor_remote_as"`
+ NeighborBfd types.String `tfsdk:"neighbor_bfd"`
+ UpdateSourceInterfaceId types.String `tfsdk:"update_source_interface_id"`
+ EnableAddressFamily types.Bool `tfsdk:"enable_address_family"`
+ NeighborShutdown types.Bool `tfsdk:"neighbor_shutdown"`
+ NeighborDescription types.String `tfsdk:"neighbor_description"`
+ NeighborFilterAccessLists []DeviceBGPIpv4NeighborsNeighborFilterAccessLists `tfsdk:"neighbor_filter_access_lists"`
+ NeighborFilterRouteMapLists []DeviceBGPIpv4NeighborsNeighborFilterRouteMapLists `tfsdk:"neighbor_filter_route_map_lists"`
+ NeighborFilterPrefixLists []DeviceBGPIpv4NeighborsNeighborFilterPrefixLists `tfsdk:"neighbor_filter_prefix_lists"`
+ NeighborFilterAsPathLists []DeviceBGPIpv4NeighborsNeighborFilterAsPathLists `tfsdk:"neighbor_filter_as_path_lists"`
+ NeighborFilterMaxPrefix types.Int64 `tfsdk:"neighbor_filter_max_prefix"`
+ NeighborFilterWarningOnly types.Bool `tfsdk:"neighbor_filter_warning_only"`
+ NeighborFilterThresholdValue types.Int64 `tfsdk:"neighbor_filter_threshold_value"`
+ NeighborFilterRestartInterval types.Int64 `tfsdk:"neighbor_filter_restart_interval"`
+ NeighborRoutesAdvertisementInterval types.Int64 `tfsdk:"neighbor_routes_advertisement_interval"`
+ NeighborRoutesRemovePrivateAs types.Bool `tfsdk:"neighbor_routes_remove_private_as"`
+ NeighborGenerateDefaultRouteMapId types.String `tfsdk:"neighbor_generate_default_route_map_id"`
+ NeighborRoutesAdvertiseMapUseExist types.Bool `tfsdk:"neighbor_routes_advertise_map_use_exist"`
+ NeighborRoutesAdvertiseMapId types.String `tfsdk:"neighbor_routes_advertise_map_id"`
+ NeighborRoutesAdvertiseExistNonexistMapId types.String `tfsdk:"neighbor_routes_advertise_exist_nonexist_map_id"`
+ NeighborKeepaliveInterval types.Int64 `tfsdk:"neighbor_keepalive_interval"`
+ NeighborHoldTime types.Int64 `tfsdk:"neighbor_hold_time"`
+ NeighborMinHoldTime types.Int64 `tfsdk:"neighbor_min_hold_time"`
+ NeighborAuthenticationPassword types.String `tfsdk:"neighbor_authentication_password"`
+ NeighborSendCommunityAttribute types.Bool `tfsdk:"neighbor_send_community_attribute"`
+ NeighborNexthopSelf types.Bool `tfsdk:"neighbor_nexthop_self"`
+ NeighborDisableConnectionVerification types.Bool `tfsdk:"neighbor_disable_connection_verification"`
+ NeighborTcpMtuPathDiscovery types.Bool `tfsdk:"neighbor_tcp_mtu_path_discovery"`
+ NeighborMaxHopCount types.Int64 `tfsdk:"neighbor_max_hop_count"`
+ NeighborTcpTransportMode types.Bool `tfsdk:"neighbor_tcp_transport_mode"`
+ NeighborWeight types.Int64 `tfsdk:"neighbor_weight"`
+ NeighborVersion types.String `tfsdk:"neighbor_version"`
+ NeighborCustomizedLocalAsNumber types.String `tfsdk:"neighbor_customized_local_as_number"`
+ NeighborCustomizedNoPrepend types.Bool `tfsdk:"neighbor_customized_no_prepend"`
+ NeighborCustomizedReplaceAs types.Bool `tfsdk:"neighbor_customized_replace_as"`
+ NeighborCustomizedAcceptBothAs types.Bool `tfsdk:"neighbor_customized_accept_both_as"`
+}
+
+type DeviceBGPIpv4AggregateAddresses struct {
+ GenerateAs types.Bool `tfsdk:"generate_as"`
+ Filter types.Bool `tfsdk:"filter"`
+ NetworkId types.String `tfsdk:"network_id"`
+ AdvertiseMapId types.String `tfsdk:"advertise_map_id"`
+ AttributeMapId types.String `tfsdk:"attribute_map_id"`
+ SuppressMapId types.String `tfsdk:"suppress_map_id"`
+}
+
+type DeviceBGPIpv4Filterings struct {
+ AccessListId types.String `tfsdk:"access_list_id"`
+ NetworkDirection types.String `tfsdk:"network_direction"`
+ Protocol types.String `tfsdk:"protocol"`
+ ProrocolProcess types.String `tfsdk:"prorocol_process"`
+}
+
+type DeviceBGPIpv4Networks struct {
+ NetworkId types.String `tfsdk:"network_id"`
+ RouteMapId types.String `tfsdk:"route_map_id"`
+}
+
+type DeviceBGPIpv4Redistributions struct {
+ SourceProtocol types.String `tfsdk:"source_protocol"`
+ RouteMapId types.String `tfsdk:"route_map_id"`
+ Metric types.Int64 `tfsdk:"metric"`
+ ProcessId types.String `tfsdk:"process_id"`
+ MatchExternal1 types.Bool `tfsdk:"match_external1"`
+ MatchExternal2 types.Bool `tfsdk:"match_external2"`
+ MatchInternal types.Bool `tfsdk:"match_internal"`
+ MatchNssaExternal1 types.Bool `tfsdk:"match_nssa_external1"`
+ MatchNssaExternal2 types.Bool `tfsdk:"match_nssa_external2"`
+}
+
+type DeviceBGPIpv4RouteInjections struct {
+ InjectRouteMapId types.String `tfsdk:"inject_route_map_id"`
+ ExistRouteMapId types.String `tfsdk:"exist_route_map_id"`
+}
+
+type DeviceBGPIpv4NeighborsNeighborFilterAccessLists struct {
+ AccessListId types.String `tfsdk:"access_list_id"`
+ UpdateDirection types.String `tfsdk:"update_direction"`
+}
+type DeviceBGPIpv4NeighborsNeighborFilterRouteMapLists struct {
+ RouteMapId types.String `tfsdk:"route_map_id"`
+ UpdateDirection types.String `tfsdk:"update_direction"`
+}
+type DeviceBGPIpv4NeighborsNeighborFilterPrefixLists struct {
+ PrefixListId types.String `tfsdk:"prefix_list_id"`
+ UpdateDirection types.String `tfsdk:"update_direction"`
+}
+type DeviceBGPIpv4NeighborsNeighborFilterAsPathLists struct {
+ UpdateDirection types.String `tfsdk:"update_direction"`
+ AsPathId types.String `tfsdk:"as_path_id"`
+}
+
+// End of section. //template:end types
+
+// Section below is generated&owned by "gen/generator.go". //template:begin getPath
+
+func (data DeviceBGP) getPath() string {
+ return fmt.Sprintf("/api/fmc_config/v1/domain/{DOMAIN_UUID}/devices/devicerecords/%v/routing/bgp", url.QueryEscape(data.DeviceId.ValueString()))
+}
+
+// End of section. //template:end getPath
+
+// Section below is generated&owned by "gen/generator.go". //template:begin toBody
+
+func (data DeviceBGP) toBody(ctx context.Context, state DeviceBGP) string {
+ body := ""
+ if data.Id.ValueString() != "" {
+ body, _ = sjson.Set(body, "id", data.Id.ValueString())
+ }
+ if !data.Ipv4LearnedRouteMapId.IsNull() {
+ body, _ = sjson.Set(body, "addressFamilyIPv4.aftableMap.id", data.Ipv4LearnedRouteMapId.ValueString())
+ }
+ if !data.Ipv4DefaultInformationOrginate.IsNull() {
+ body, _ = sjson.Set(body, "addressFamilyIPv4.defaultInformationOrginate", data.Ipv4DefaultInformationOrginate.ValueBool())
+ }
+ if !data.Ipv4AutoAummary.IsNull() {
+ body, _ = sjson.Set(body, "addressFamilyIPv4.autoSummary", data.Ipv4AutoAummary.ValueBool())
+ }
+ if !data.Ipv4BgpSupressInactive.IsNull() {
+ body, _ = sjson.Set(body, "addressFamilyIPv4.bgpSupressInactive", data.Ipv4BgpSupressInactive.ValueBool())
+ }
+ if !data.Ipv4Synchronization.IsNull() {
+ body, _ = sjson.Set(body, "addressFamilyIPv4.synchronization", data.Ipv4Synchronization.ValueBool())
+ }
+ if !data.Ipv4BgpRedistributeInternal.IsNull() {
+ body, _ = sjson.Set(body, "addressFamilyIPv4.bgpRedistributeInternal", data.Ipv4BgpRedistributeInternal.ValueBool())
+ }
+ if !data.Ipv4ExternalDistance.IsNull() {
+ body, _ = sjson.Set(body, "addressFamilyIPv4.distance.externalDistance", data.Ipv4ExternalDistance.ValueInt64())
+ }
+ if !data.Ipv4InternalDistance.IsNull() {
+ body, _ = sjson.Set(body, "addressFamilyIPv4.distance.internalDistance", data.Ipv4InternalDistance.ValueInt64())
+ }
+ if !data.Ipv4LocalDistance.IsNull() {
+ body, _ = sjson.Set(body, "addressFamilyIPv4.distance.localDistance", data.Ipv4LocalDistance.ValueInt64())
+ }
+ if !data.Ipv4ForwardPacketsOverMultipathIbgp.IsNull() {
+ body, _ = sjson.Set(body, "addressFamilyIPv4.ibgp", data.Ipv4ForwardPacketsOverMultipathIbgp.ValueInt64())
+ }
+ if !data.Ipv4ForwardPacketsOverMultipathEbgp.IsNull() {
+ body, _ = sjson.Set(body, "addressFamilyIPv4.ebgp", data.Ipv4ForwardPacketsOverMultipathEbgp.ValueInt64())
+ }
+ if len(data.Ipv4Neighbors) > 0 {
+ body, _ = sjson.Set(body, "addressFamilyIPv4.neighbors", []interface{}{})
+ for _, item := range data.Ipv4Neighbors {
+ itemBody := ""
+ if !item.NeighborAddress.IsNull() {
+ itemBody, _ = sjson.Set(itemBody, "ipv4Address", item.NeighborAddress.ValueString())
+ }
+ if !item.NeighborRemoteAs.IsNull() {
+ itemBody, _ = sjson.Set(itemBody, "remoteAs", item.NeighborRemoteAs.ValueString())
+ }
+ if !item.NeighborBfd.IsNull() {
+ itemBody, _ = sjson.Set(itemBody, "neighborGeneral.fallOverBFD", item.NeighborBfd.ValueString())
+ }
+ if !item.UpdateSourceInterfaceId.IsNull() {
+ itemBody, _ = sjson.Set(itemBody, "neighborGeneral.updateSource.id", item.UpdateSourceInterfaceId.ValueString())
+ }
+ if !item.EnableAddressFamily.IsNull() {
+ itemBody, _ = sjson.Set(itemBody, "neighborGeneral.enableAddress", item.EnableAddressFamily.ValueBool())
+ }
+ if !item.NeighborShutdown.IsNull() {
+ itemBody, _ = sjson.Set(itemBody, "neighborGeneral.shutdown", item.NeighborShutdown.ValueBool())
+ }
+ if !item.NeighborDescription.IsNull() {
+ itemBody, _ = sjson.Set(itemBody, "neighborGeneral.description", item.NeighborDescription.ValueString())
+ }
+ if len(item.NeighborFilterAccessLists) > 0 {
+ itemBody, _ = sjson.Set(itemBody, "neighborFiltering.neighborDistributeLists", []interface{}{})
+ for _, childItem := range item.NeighborFilterAccessLists {
+ itemChildBody := ""
+ if !childItem.AccessListId.IsNull() {
+ itemChildBody, _ = sjson.Set(itemChildBody, "accessList.id", childItem.AccessListId.ValueString())
+ }
+ if !childItem.UpdateDirection.IsNull() {
+ itemChildBody, _ = sjson.Set(itemChildBody, "filterUpdateAction", childItem.UpdateDirection.ValueString())
+ }
+ itemBody, _ = sjson.SetRaw(itemBody, "neighborFiltering.neighborDistributeLists.-1", itemChildBody)
+ }
+ }
+ if len(item.NeighborFilterRouteMapLists) > 0 {
+ itemBody, _ = sjson.Set(itemBody, "neighborFiltering.neighborRouteMap", []interface{}{})
+ for _, childItem := range item.NeighborFilterRouteMapLists {
+ itemChildBody := ""
+ if !childItem.RouteMapId.IsNull() {
+ itemChildBody, _ = sjson.Set(itemChildBody, "RouteMap.id", childItem.RouteMapId.ValueString())
+ }
+ if !childItem.UpdateDirection.IsNull() {
+ itemChildBody, _ = sjson.Set(itemChildBody, "filterUpdateAction", childItem.UpdateDirection.ValueString())
+ }
+ itemBody, _ = sjson.SetRaw(itemBody, "neighborFiltering.neighborRouteMap.-1", itemChildBody)
+ }
+ }
+ if len(item.NeighborFilterPrefixLists) > 0 {
+ itemBody, _ = sjson.Set(itemBody, "neighborFiltering.ipv4PrefixListFilter", []interface{}{})
+ for _, childItem := range item.NeighborFilterPrefixLists {
+ itemChildBody := ""
+ if !childItem.PrefixListId.IsNull() {
+ itemChildBody, _ = sjson.Set(itemChildBody, "ipv4PrefixList.id", childItem.PrefixListId.ValueString())
+ }
+ if !childItem.UpdateDirection.IsNull() {
+ itemChildBody, _ = sjson.Set(itemChildBody, "filterUpdateAction", childItem.UpdateDirection.ValueString())
+ }
+ itemBody, _ = sjson.SetRaw(itemBody, "neighborFiltering.ipv4PrefixListFilter.-1", itemChildBody)
+ }
+ }
+ if len(item.NeighborFilterAsPathLists) > 0 {
+ itemBody, _ = sjson.Set(itemBody, "neighborFilterList.neighborFilterList", []interface{}{})
+ for _, childItem := range item.NeighborFilterAsPathLists {
+ itemChildBody := ""
+ if !childItem.UpdateDirection.IsNull() {
+ itemChildBody, _ = sjson.Set(itemChildBody, "filterUpdateAction", childItem.UpdateDirection.ValueString())
+ }
+ if !childItem.AsPathId.IsNull() {
+ itemChildBody, _ = sjson.Set(itemChildBody, "asPathList.id", childItem.AsPathId.ValueString())
+ }
+ itemBody, _ = sjson.SetRaw(itemBody, "neighborFilterList.neighborFilterList.-1", itemChildBody)
+ }
+ }
+ if !item.NeighborFilterMaxPrefix.IsNull() {
+ itemBody, _ = sjson.Set(itemBody, "neighborFiltering.neighborMaximumPrefix.maxPrefixLimit", item.NeighborFilterMaxPrefix.ValueInt64())
+ }
+ if !item.NeighborFilterWarningOnly.IsNull() {
+ itemBody, _ = sjson.Set(itemBody, "neighborFiltering.neighborMaximumPrefix.warningOnly", item.NeighborFilterWarningOnly.ValueBool())
+ }
+ if !item.NeighborFilterThresholdValue.IsNull() {
+ itemBody, _ = sjson.Set(itemBody, "neighborFiltering.neighborMaximumPrefix.thresholdValue", item.NeighborFilterThresholdValue.ValueInt64())
+ }
+ if !item.NeighborFilterRestartInterval.IsNull() {
+ itemBody, _ = sjson.Set(itemBody, "neighborFiltering.neighborMaximumPrefix.restartInterval", item.NeighborFilterRestartInterval.ValueInt64())
+ }
+ if !item.NeighborRoutesAdvertisementInterval.IsNull() {
+ itemBody, _ = sjson.Set(itemBody, "neighborRoutes.advertisementInterval", item.NeighborRoutesAdvertisementInterval.ValueInt64())
+ }
+ if !item.NeighborRoutesRemovePrivateAs.IsNull() {
+ itemBody, _ = sjson.Set(itemBody, "neighborRoutes.removePrivateAs", item.NeighborRoutesRemovePrivateAs.ValueBool())
+ }
+ if !item.NeighborGenerateDefaultRouteMapId.IsNull() {
+ itemBody, _ = sjson.Set(itemBody, "neighborFiltering.neighborDefaultOriginate.routeMap.id", item.NeighborGenerateDefaultRouteMapId.ValueString())
+ }
+ if !item.NeighborRoutesAdvertiseMapUseExist.IsNull() {
+ itemBody, _ = sjson.Set(itemBody, "neighborRoutes.neighborAdvertiseMaps.existMap", item.NeighborRoutesAdvertiseMapUseExist.ValueBool())
+ }
+ if !item.NeighborRoutesAdvertiseMapId.IsNull() {
+ itemBody, _ = sjson.Set(itemBody, "neighborRoutes.neighborAdvertiseMaps.routeMap.id", item.NeighborRoutesAdvertiseMapId.ValueString())
+ }
+ if !item.NeighborRoutesAdvertiseExistNonexistMapId.IsNull() {
+ itemBody, _ = sjson.Set(itemBody, "neighborRoutes.neighborAdvertiseMaps.existRouteMap.id", item.NeighborRoutesAdvertiseExistNonexistMapId.ValueString())
+ }
+ if !item.NeighborKeepaliveInterval.IsNull() {
+ itemBody, _ = sjson.Set(itemBody, "neighborTimers.keepAliveInterval", item.NeighborKeepaliveInterval.ValueInt64())
+ }
+ if !item.NeighborHoldTime.IsNull() {
+ itemBody, _ = sjson.Set(itemBody, "neighborTimers.holdTime", item.NeighborHoldTime.ValueInt64())
+ }
+ if !item.NeighborMinHoldTime.IsNull() {
+ itemBody, _ = sjson.Set(itemBody, "neighborTimers.minimumHoldTime", item.NeighborMinHoldTime.ValueInt64())
+ }
+ if !item.NeighborAuthenticationPassword.IsNull() {
+ itemBody, _ = sjson.Set(itemBody, "neighborAdvanced.neighborSecret", item.NeighborAuthenticationPassword.ValueString())
+ }
+ if !item.NeighborSendCommunityAttribute.IsNull() {
+ itemBody, _ = sjson.Set(itemBody, "neighborAdvanced.sendCommunity", item.NeighborSendCommunityAttribute.ValueBool())
+ }
+ if !item.NeighborNexthopSelf.IsNull() {
+ itemBody, _ = sjson.Set(itemBody, "neighborAdvanced.nextHopSelf", item.NeighborNexthopSelf.ValueBool())
+ }
+ if !item.NeighborDisableConnectionVerification.IsNull() {
+ itemBody, _ = sjson.Set(itemBody, "neighborAdvanced.neighborHops.disableConnectedCheck", item.NeighborDisableConnectionVerification.ValueBool())
+ }
+ if !item.NeighborTcpMtuPathDiscovery.IsNull() {
+ itemBody, _ = sjson.Set(itemBody, "neighborAdvanced.neighborTransportPathMTUDiscovery.disable", item.NeighborTcpMtuPathDiscovery.ValueBool())
+ }
+ if !item.NeighborMaxHopCount.IsNull() {
+ itemBody, _ = sjson.Set(itemBody, "neighborAdvanced.neighborHops.maxHopCount", item.NeighborMaxHopCount.ValueInt64())
+ }
+ if !item.NeighborTcpTransportMode.IsNull() {
+ itemBody, _ = sjson.Set(itemBody, "neighborAdvanced.neighborTransportConnectionMode.establishTCPSession", item.NeighborTcpTransportMode.ValueBool())
+ }
+ if !item.NeighborWeight.IsNull() {
+ itemBody, _ = sjson.Set(itemBody, "neighborAdvanced.neighborWeight", item.NeighborWeight.ValueInt64())
+ }
+ if !item.NeighborVersion.IsNull() {
+ itemBody, _ = sjson.Set(itemBody, "neighborAdvanced.neighborVersion", item.NeighborVersion.ValueString())
+ }
+ if !item.NeighborCustomizedLocalAsNumber.IsNull() {
+ itemBody, _ = sjson.Set(itemBody, "neighborLocalAs.asNumber", item.NeighborCustomizedLocalAsNumber.ValueString())
+ }
+ if !item.NeighborCustomizedNoPrepend.IsNull() {
+ itemBody, _ = sjson.Set(itemBody, "neighborLocalAs.noPrepend", item.NeighborCustomizedNoPrepend.ValueBool())
+ }
+ if !item.NeighborCustomizedReplaceAs.IsNull() {
+ itemBody, _ = sjson.Set(itemBody, "neighborLocalAs.replaceAs", item.NeighborCustomizedReplaceAs.ValueBool())
+ }
+ if !item.NeighborCustomizedAcceptBothAs.IsNull() {
+ itemBody, _ = sjson.Set(itemBody, "neighborLocalAs.dualAs", item.NeighborCustomizedAcceptBothAs.ValueBool())
+ }
+ body, _ = sjson.SetRaw(body, "addressFamilyIPv4.neighbors.-1", itemBody)
+ }
+ }
+ if len(data.Ipv4AggregateAddresses) > 0 {
+ body, _ = sjson.Set(body, "addressFamilyIPv4.aggregateAddressesIPv4s", []interface{}{})
+ for _, item := range data.Ipv4AggregateAddresses {
+ itemBody := ""
+ if !item.GenerateAs.IsNull() {
+ itemBody, _ = sjson.Set(itemBody, "asSet", item.GenerateAs.ValueBool())
+ }
+ if !item.Filter.IsNull() {
+ itemBody, _ = sjson.Set(itemBody, "summaryOnly", item.Filter.ValueBool())
+ }
+ if !item.NetworkId.IsNull() {
+ itemBody, _ = sjson.Set(itemBody, "ipv4AggregateNetwork.id", item.NetworkId.ValueString())
+ }
+ if !item.AdvertiseMapId.IsNull() {
+ itemBody, _ = sjson.Set(itemBody, "advertiseMap.id", item.AdvertiseMapId.ValueString())
+ }
+ if !item.AttributeMapId.IsNull() {
+ itemBody, _ = sjson.Set(itemBody, "attributeMap.id", item.AttributeMapId.ValueString())
+ }
+ if !item.SuppressMapId.IsNull() {
+ itemBody, _ = sjson.Set(itemBody, "suppressMap.id", item.SuppressMapId.ValueString())
+ }
+ body, _ = sjson.SetRaw(body, "addressFamilyIPv4.aggregateAddressesIPv4s.-1", itemBody)
+ }
+ }
+ if len(data.Ipv4Filterings) > 0 {
+ body, _ = sjson.Set(body, "addressFamilyIPv4.distributeLists", []interface{}{})
+ for _, item := range data.Ipv4Filterings {
+ itemBody := ""
+ if !item.AccessListId.IsNull() {
+ itemBody, _ = sjson.Set(itemBody, "ipv4AggregateNetwork.id", item.AccessListId.ValueString())
+ }
+ if !item.NetworkDirection.IsNull() {
+ itemBody, _ = sjson.Set(itemBody, "type", item.NetworkDirection.ValueString())
+ }
+ if !item.Protocol.IsNull() {
+ itemBody, _ = sjson.Set(itemBody, "protocol.protocol", item.Protocol.ValueString())
+ }
+ if !item.ProrocolProcess.IsNull() {
+ itemBody, _ = sjson.Set(itemBody, "protocol.processId", item.ProrocolProcess.ValueString())
+ }
+ body, _ = sjson.SetRaw(body, "addressFamilyIPv4.distributeLists.-1", itemBody)
+ }
+ }
+ if len(data.Ipv4Networks) > 0 {
+ body, _ = sjson.Set(body, "addressFamilyIPv4.networks", []interface{}{})
+ for _, item := range data.Ipv4Networks {
+ itemBody := ""
+ if !item.NetworkId.IsNull() {
+ itemBody, _ = sjson.Set(itemBody, "ipv4Address.id", item.NetworkId.ValueString())
+ }
+ if !item.RouteMapId.IsNull() {
+ itemBody, _ = sjson.Set(itemBody, "routeMap.id", item.RouteMapId.ValueString())
+ }
+ body, _ = sjson.SetRaw(body, "addressFamilyIPv4.networks.-1", itemBody)
+ }
+ }
+ if len(data.Ipv4Redistributions) > 0 {
+ body, _ = sjson.Set(body, "addressFamilyIPv4.redistributeProtocols", []interface{}{})
+ for _, item := range data.Ipv4Redistributions {
+ itemBody := ""
+ if !item.SourceProtocol.IsNull() {
+ itemBody, _ = sjson.Set(itemBody, "type", item.SourceProtocol.ValueString())
+ }
+ if !item.RouteMapId.IsNull() {
+ itemBody, _ = sjson.Set(itemBody, "routeMap.id", item.RouteMapId.ValueString())
+ }
+ if !item.Metric.IsNull() {
+ itemBody, _ = sjson.Set(itemBody, "routeMetric.metricValue", item.Metric.ValueInt64())
+ }
+ if !item.ProcessId.IsNull() {
+ itemBody, _ = sjson.Set(itemBody, "processId", item.ProcessId.ValueString())
+ }
+ if !item.MatchExternal1.IsNull() {
+ itemBody, _ = sjson.Set(itemBody, "matchExternal1", item.MatchExternal1.ValueBool())
+ }
+ if !item.MatchExternal2.IsNull() {
+ itemBody, _ = sjson.Set(itemBody, "matchExternal2", item.MatchExternal2.ValueBool())
+ }
+ if !item.MatchInternal.IsNull() {
+ itemBody, _ = sjson.Set(itemBody, "matchInternal", item.MatchInternal.ValueBool())
+ }
+ if !item.MatchNssaExternal1.IsNull() {
+ itemBody, _ = sjson.Set(itemBody, "matchNssaExternal1", item.MatchNssaExternal1.ValueBool())
+ }
+ if !item.MatchNssaExternal2.IsNull() {
+ itemBody, _ = sjson.Set(itemBody, "matchNssaExternal2", item.MatchNssaExternal2.ValueBool())
+ }
+ body, _ = sjson.SetRaw(body, "addressFamilyIPv4.redistributeProtocols.-1", itemBody)
+ }
+ }
+ if len(data.Ipv4RouteInjections) > 0 {
+ body, _ = sjson.Set(body, "addressFamilyIPv4.injectMaps", []interface{}{})
+ for _, item := range data.Ipv4RouteInjections {
+ itemBody := ""
+ if !item.InjectRouteMapId.IsNull() {
+ itemBody, _ = sjson.Set(itemBody, "injectMap.routeMap.id", item.InjectRouteMapId.ValueString())
+ }
+ if !item.ExistRouteMapId.IsNull() {
+ itemBody, _ = sjson.Set(itemBody, "existMap.routeMap.id", item.ExistRouteMapId.ValueString())
+ }
+ body, _ = sjson.SetRaw(body, "addressFamilyIPv4.injectMaps.-1", itemBody)
+ }
+ }
+ return body
+}
+
+// End of section. //template:end toBody
+
+// Section below is generated&owned by "gen/generator.go". //template:begin fromBody
+
+func (data *DeviceBGP) fromBody(ctx context.Context, res gjson.Result) {
+ if value := res.Get("name"); value.Exists() {
+ data.Name = types.StringValue(value.String())
+ } else {
+ data.Name = types.StringNull()
+ }
+ if value := res.Get("type"); value.Exists() {
+ data.Type = types.StringValue(value.String())
+ } else {
+ data.Type = types.StringNull()
+ }
+ if value := res.Get("asNumber"); value.Exists() {
+ data.AsNumber = types.StringValue(value.String())
+ } else {
+ data.AsNumber = types.StringNull()
+ }
+ if value := res.Get("addressFamilyIPv4.type"); value.Exists() {
+ data.Ipv4AddressFamilyType = types.StringValue(value.String())
+ } else {
+ data.Ipv4AddressFamilyType = types.StringNull()
+ }
+ if value := res.Get("addressFamilyIPv4.aftableMap.id"); value.Exists() {
+ data.Ipv4LearnedRouteMapId = types.StringValue(value.String())
+ } else {
+ data.Ipv4LearnedRouteMapId = types.StringNull()
+ }
+ if value := res.Get("addressFamilyIPv4.defaultInformationOrginate"); value.Exists() {
+ data.Ipv4DefaultInformationOrginate = types.BoolValue(value.Bool())
+ } else {
+ data.Ipv4DefaultInformationOrginate = types.BoolNull()
+ }
+ if value := res.Get("addressFamilyIPv4.autoSummary"); value.Exists() {
+ data.Ipv4AutoAummary = types.BoolValue(value.Bool())
+ } else {
+ data.Ipv4AutoAummary = types.BoolNull()
+ }
+ if value := res.Get("addressFamilyIPv4.bgpSupressInactive"); value.Exists() {
+ data.Ipv4BgpSupressInactive = types.BoolValue(value.Bool())
+ } else {
+ data.Ipv4BgpSupressInactive = types.BoolNull()
+ }
+ if value := res.Get("addressFamilyIPv4.synchronization"); value.Exists() {
+ data.Ipv4Synchronization = types.BoolValue(value.Bool())
+ } else {
+ data.Ipv4Synchronization = types.BoolNull()
+ }
+ if value := res.Get("addressFamilyIPv4.bgpRedistributeInternal"); value.Exists() {
+ data.Ipv4BgpRedistributeInternal = types.BoolValue(value.Bool())
+ } else {
+ data.Ipv4BgpRedistributeInternal = types.BoolNull()
+ }
+ if value := res.Get("addressFamilyIPv4.distance.externalDistance"); value.Exists() {
+ data.Ipv4ExternalDistance = types.Int64Value(value.Int())
+ } else {
+ data.Ipv4ExternalDistance = types.Int64Value(20)
+ }
+ if value := res.Get("addressFamilyIPv4.distance.internalDistance"); value.Exists() {
+ data.Ipv4InternalDistance = types.Int64Value(value.Int())
+ } else {
+ data.Ipv4InternalDistance = types.Int64Value(200)
+ }
+ if value := res.Get("addressFamilyIPv4.distance.localDistance"); value.Exists() {
+ data.Ipv4LocalDistance = types.Int64Value(value.Int())
+ } else {
+ data.Ipv4LocalDistance = types.Int64Value(200)
+ }
+ if value := res.Get("addressFamilyIPv4.ibgp"); value.Exists() {
+ data.Ipv4ForwardPacketsOverMultipathIbgp = types.Int64Value(value.Int())
+ } else {
+ data.Ipv4ForwardPacketsOverMultipathIbgp = types.Int64Value(1)
+ }
+ if value := res.Get("addressFamilyIPv4.ebgp"); value.Exists() {
+ data.Ipv4ForwardPacketsOverMultipathEbgp = types.Int64Value(value.Int())
+ } else {
+ data.Ipv4ForwardPacketsOverMultipathEbgp = types.Int64Value(1)
+ }
+ if value := res.Get("addressFamilyIPv4.neighbors"); value.Exists() {
+ data.Ipv4Neighbors = make([]DeviceBGPIpv4Neighbors, 0)
+ value.ForEach(func(k, res gjson.Result) bool {
+ parent := &data
+ data := DeviceBGPIpv4Neighbors{}
+ if value := res.Get("ipv4Address"); value.Exists() {
+ data.NeighborAddress = types.StringValue(value.String())
+ } else {
+ data.NeighborAddress = types.StringNull()
+ }
+ if value := res.Get("remoteAs"); value.Exists() {
+ data.NeighborRemoteAs = types.StringValue(value.String())
+ } else {
+ data.NeighborRemoteAs = types.StringNull()
+ }
+ if value := res.Get("neighborGeneral.fallOverBFD"); value.Exists() {
+ data.NeighborBfd = types.StringValue(value.String())
+ } else {
+ data.NeighborBfd = types.StringValue("NONE")
+ }
+ if value := res.Get("neighborGeneral.updateSource.id"); value.Exists() {
+ data.UpdateSourceInterfaceId = types.StringValue(value.String())
+ } else {
+ data.UpdateSourceInterfaceId = types.StringNull()
+ }
+ if value := res.Get("neighborGeneral.enableAddress"); value.Exists() {
+ data.EnableAddressFamily = types.BoolValue(value.Bool())
+ } else {
+ data.EnableAddressFamily = types.BoolValue(false)
+ }
+ if value := res.Get("neighborGeneral.shutdown"); value.Exists() {
+ data.NeighborShutdown = types.BoolValue(value.Bool())
+ } else {
+ data.NeighborShutdown = types.BoolValue(false)
+ }
+ if value := res.Get("neighborGeneral.description"); value.Exists() {
+ data.NeighborDescription = types.StringValue(value.String())
+ } else {
+ data.NeighborDescription = types.StringNull()
+ }
+ if value := res.Get("neighborFiltering.neighborDistributeLists"); value.Exists() {
+ data.NeighborFilterAccessLists = make([]DeviceBGPIpv4NeighborsNeighborFilterAccessLists, 0)
+ value.ForEach(func(k, res gjson.Result) bool {
+ parent := &data
+ data := DeviceBGPIpv4NeighborsNeighborFilterAccessLists{}
+ if value := res.Get("accessList.id"); value.Exists() {
+ data.AccessListId = types.StringValue(value.String())
+ } else {
+ data.AccessListId = types.StringNull()
+ }
+ if value := res.Get("filterUpdateAction"); value.Exists() {
+ data.UpdateDirection = types.StringValue(value.String())
+ } else {
+ data.UpdateDirection = types.StringNull()
+ }
+ (*parent).NeighborFilterAccessLists = append((*parent).NeighborFilterAccessLists, data)
+ return true
+ })
+ }
+ if value := res.Get("neighborFiltering.neighborRouteMap"); value.Exists() {
+ data.NeighborFilterRouteMapLists = make([]DeviceBGPIpv4NeighborsNeighborFilterRouteMapLists, 0)
+ value.ForEach(func(k, res gjson.Result) bool {
+ parent := &data
+ data := DeviceBGPIpv4NeighborsNeighborFilterRouteMapLists{}
+ if value := res.Get("RouteMap.id"); value.Exists() {
+ data.RouteMapId = types.StringValue(value.String())
+ } else {
+ data.RouteMapId = types.StringNull()
+ }
+ if value := res.Get("filterUpdateAction"); value.Exists() {
+ data.UpdateDirection = types.StringValue(value.String())
+ } else {
+ data.UpdateDirection = types.StringNull()
+ }
+ (*parent).NeighborFilterRouteMapLists = append((*parent).NeighborFilterRouteMapLists, data)
+ return true
+ })
+ }
+ if value := res.Get("neighborFiltering.ipv4PrefixListFilter"); value.Exists() {
+ data.NeighborFilterPrefixLists = make([]DeviceBGPIpv4NeighborsNeighborFilterPrefixLists, 0)
+ value.ForEach(func(k, res gjson.Result) bool {
+ parent := &data
+ data := DeviceBGPIpv4NeighborsNeighborFilterPrefixLists{}
+ if value := res.Get("ipv4PrefixList.id"); value.Exists() {
+ data.PrefixListId = types.StringValue(value.String())
+ } else {
+ data.PrefixListId = types.StringNull()
+ }
+ if value := res.Get("filterUpdateAction"); value.Exists() {
+ data.UpdateDirection = types.StringValue(value.String())
+ } else {
+ data.UpdateDirection = types.StringNull()
+ }
+ (*parent).NeighborFilterPrefixLists = append((*parent).NeighborFilterPrefixLists, data)
+ return true
+ })
+ }
+ if value := res.Get("neighborFilterList.neighborFilterList"); value.Exists() {
+ data.NeighborFilterAsPathLists = make([]DeviceBGPIpv4NeighborsNeighborFilterAsPathLists, 0)
+ value.ForEach(func(k, res gjson.Result) bool {
+ parent := &data
+ data := DeviceBGPIpv4NeighborsNeighborFilterAsPathLists{}
+ if value := res.Get("filterUpdateAction"); value.Exists() {
+ data.UpdateDirection = types.StringValue(value.String())
+ } else {
+ data.UpdateDirection = types.StringNull()
+ }
+ if value := res.Get("asPathList.id"); value.Exists() {
+ data.AsPathId = types.StringValue(value.String())
+ } else {
+ data.AsPathId = types.StringNull()
+ }
+ (*parent).NeighborFilterAsPathLists = append((*parent).NeighborFilterAsPathLists, data)
+ return true
+ })
+ }
+ if value := res.Get("neighborFiltering.neighborMaximumPrefix.maxPrefixLimit"); value.Exists() {
+ data.NeighborFilterMaxPrefix = types.Int64Value(value.Int())
+ } else {
+ data.NeighborFilterMaxPrefix = types.Int64Null()
+ }
+ if value := res.Get("neighborFiltering.neighborMaximumPrefix.warningOnly"); value.Exists() {
+ data.NeighborFilterWarningOnly = types.BoolValue(value.Bool())
+ } else {
+ data.NeighborFilterWarningOnly = types.BoolNull()
+ }
+ if value := res.Get("neighborFiltering.neighborMaximumPrefix.thresholdValue"); value.Exists() {
+ data.NeighborFilterThresholdValue = types.Int64Value(value.Int())
+ } else {
+ data.NeighborFilterThresholdValue = types.Int64Null()
+ }
+ if value := res.Get("neighborFiltering.neighborMaximumPrefix.restartInterval"); value.Exists() {
+ data.NeighborFilterRestartInterval = types.Int64Value(value.Int())
+ } else {
+ data.NeighborFilterRestartInterval = types.Int64Null()
+ }
+ if value := res.Get("neighborRoutes.advertisementInterval"); value.Exists() {
+ data.NeighborRoutesAdvertisementInterval = types.Int64Value(value.Int())
+ } else {
+ data.NeighborRoutesAdvertisementInterval = types.Int64Value(0)
+ }
+ if value := res.Get("neighborRoutes.removePrivateAs"); value.Exists() {
+ data.NeighborRoutesRemovePrivateAs = types.BoolValue(value.Bool())
+ } else {
+ data.NeighborRoutesRemovePrivateAs = types.BoolValue(false)
+ }
+ if value := res.Get("neighborFiltering.neighborDefaultOriginate.routeMap.id"); value.Exists() {
+ data.NeighborGenerateDefaultRouteMapId = types.StringValue(value.String())
+ } else {
+ data.NeighborGenerateDefaultRouteMapId = types.StringNull()
+ }
+ if value := res.Get("neighborRoutes.neighborAdvertiseMaps.existMap"); value.Exists() {
+ data.NeighborRoutesAdvertiseMapUseExist = types.BoolValue(value.Bool())
+ } else {
+ data.NeighborRoutesAdvertiseMapUseExist = types.BoolNull()
+ }
+ if value := res.Get("neighborRoutes.neighborAdvertiseMaps.routeMap.id"); value.Exists() {
+ data.NeighborRoutesAdvertiseMapId = types.StringValue(value.String())
+ } else {
+ data.NeighborRoutesAdvertiseMapId = types.StringNull()
+ }
+ if value := res.Get("neighborRoutes.neighborAdvertiseMaps.existRouteMap.id"); value.Exists() {
+ data.NeighborRoutesAdvertiseExistNonexistMapId = types.StringValue(value.String())
+ } else {
+ data.NeighborRoutesAdvertiseExistNonexistMapId = types.StringNull()
+ }
+ if value := res.Get("neighborTimers.keepAliveInterval"); value.Exists() {
+ data.NeighborKeepaliveInterval = types.Int64Value(value.Int())
+ } else {
+ data.NeighborKeepaliveInterval = types.Int64Null()
+ }
+ if value := res.Get("neighborTimers.holdTime"); value.Exists() {
+ data.NeighborHoldTime = types.Int64Value(value.Int())
+ } else {
+ data.NeighborHoldTime = types.Int64Null()
+ }
+ if value := res.Get("neighborTimers.minimumHoldTime"); value.Exists() {
+ data.NeighborMinHoldTime = types.Int64Value(value.Int())
+ } else {
+ data.NeighborMinHoldTime = types.Int64Null()
+ }
+ if value := res.Get("neighborAdvanced.neighborSecret"); value.Exists() {
+ data.NeighborAuthenticationPassword = types.StringValue(value.String())
+ } else {
+ data.NeighborAuthenticationPassword = types.StringNull()
+ }
+ if value := res.Get("neighborAdvanced.sendCommunity"); value.Exists() {
+ data.NeighborSendCommunityAttribute = types.BoolValue(value.Bool())
+ } else {
+ data.NeighborSendCommunityAttribute = types.BoolValue(false)
+ }
+ if value := res.Get("neighborAdvanced.nextHopSelf"); value.Exists() {
+ data.NeighborNexthopSelf = types.BoolValue(value.Bool())
+ } else {
+ data.NeighborNexthopSelf = types.BoolValue(false)
+ }
+ if value := res.Get("neighborAdvanced.neighborHops.disableConnectedCheck"); value.Exists() {
+ data.NeighborDisableConnectionVerification = types.BoolValue(value.Bool())
+ } else {
+ data.NeighborDisableConnectionVerification = types.BoolValue(false)
+ }
+ if value := res.Get("neighborAdvanced.neighborTransportPathMTUDiscovery.disable"); value.Exists() {
+ data.NeighborTcpMtuPathDiscovery = types.BoolValue(value.Bool())
+ } else {
+ data.NeighborTcpMtuPathDiscovery = types.BoolValue(false)
+ }
+ if value := res.Get("neighborAdvanced.neighborHops.maxHopCount"); value.Exists() {
+ data.NeighborMaxHopCount = types.Int64Value(value.Int())
+ } else {
+ data.NeighborMaxHopCount = types.Int64Value(1)
+ }
+ if value := res.Get("neighborAdvanced.neighborTransportConnectionMode.establishTCPSession"); value.Exists() {
+ data.NeighborTcpTransportMode = types.BoolValue(value.Bool())
+ } else {
+ data.NeighborTcpTransportMode = types.BoolValue(false)
+ }
+ if value := res.Get("neighborAdvanced.neighborWeight"); value.Exists() {
+ data.NeighborWeight = types.Int64Value(value.Int())
+ } else {
+ data.NeighborWeight = types.Int64Value(0)
+ }
+ if value := res.Get("neighborAdvanced.neighborVersion"); value.Exists() {
+ data.NeighborVersion = types.StringValue(value.String())
+ } else {
+ data.NeighborVersion = types.StringValue("0")
+ }
+ if value := res.Get("neighborLocalAs.asNumber"); value.Exists() {
+ data.NeighborCustomizedLocalAsNumber = types.StringValue(value.String())
+ } else {
+ data.NeighborCustomizedLocalAsNumber = types.StringNull()
+ }
+ if value := res.Get("neighborLocalAs.noPrepend"); value.Exists() {
+ data.NeighborCustomizedNoPrepend = types.BoolValue(value.Bool())
+ } else {
+ data.NeighborCustomizedNoPrepend = types.BoolNull()
+ }
+ if value := res.Get("neighborLocalAs.replaceAs"); value.Exists() {
+ data.NeighborCustomizedReplaceAs = types.BoolValue(value.Bool())
+ } else {
+ data.NeighborCustomizedReplaceAs = types.BoolNull()
+ }
+ if value := res.Get("neighborLocalAs.dualAs"); value.Exists() {
+ data.NeighborCustomizedAcceptBothAs = types.BoolValue(value.Bool())
+ } else {
+ data.NeighborCustomizedAcceptBothAs = types.BoolNull()
+ }
+ (*parent).Ipv4Neighbors = append((*parent).Ipv4Neighbors, data)
+ return true
+ })
+ }
+ if value := res.Get("addressFamilyIPv4.aggregateAddressesIPv4s"); value.Exists() {
+ data.Ipv4AggregateAddresses = make([]DeviceBGPIpv4AggregateAddresses, 0)
+ value.ForEach(func(k, res gjson.Result) bool {
+ parent := &data
+ data := DeviceBGPIpv4AggregateAddresses{}
+ if value := res.Get("asSet"); value.Exists() {
+ data.GenerateAs = types.BoolValue(value.Bool())
+ } else {
+ data.GenerateAs = types.BoolNull()
+ }
+ if value := res.Get("summaryOnly"); value.Exists() {
+ data.Filter = types.BoolValue(value.Bool())
+ } else {
+ data.Filter = types.BoolNull()
+ }
+ if value := res.Get("ipv4AggregateNetwork.id"); value.Exists() {
+ data.NetworkId = types.StringValue(value.String())
+ } else {
+ data.NetworkId = types.StringNull()
+ }
+ if value := res.Get("advertiseMap.id"); value.Exists() {
+ data.AdvertiseMapId = types.StringValue(value.String())
+ } else {
+ data.AdvertiseMapId = types.StringNull()
+ }
+ if value := res.Get("attributeMap.id"); value.Exists() {
+ data.AttributeMapId = types.StringValue(value.String())
+ } else {
+ data.AttributeMapId = types.StringNull()
+ }
+ if value := res.Get("suppressMap.id"); value.Exists() {
+ data.SuppressMapId = types.StringValue(value.String())
+ } else {
+ data.SuppressMapId = types.StringNull()
+ }
+ (*parent).Ipv4AggregateAddresses = append((*parent).Ipv4AggregateAddresses, data)
+ return true
+ })
+ }
+ if value := res.Get("addressFamilyIPv4.distributeLists"); value.Exists() {
+ data.Ipv4Filterings = make([]DeviceBGPIpv4Filterings, 0)
+ value.ForEach(func(k, res gjson.Result) bool {
+ parent := &data
+ data := DeviceBGPIpv4Filterings{}
+ if value := res.Get("ipv4AggregateNetwork.id"); value.Exists() {
+ data.AccessListId = types.StringValue(value.String())
+ } else {
+ data.AccessListId = types.StringNull()
+ }
+ if value := res.Get("type"); value.Exists() {
+ data.NetworkDirection = types.StringValue(value.String())
+ } else {
+ data.NetworkDirection = types.StringNull()
+ }
+ if value := res.Get("protocol.protocol"); value.Exists() {
+ data.Protocol = types.StringValue(value.String())
+ } else {
+ data.Protocol = types.StringNull()
+ }
+ if value := res.Get("protocol.processId"); value.Exists() {
+ data.ProrocolProcess = types.StringValue(value.String())
+ } else {
+ data.ProrocolProcess = types.StringNull()
+ }
+ (*parent).Ipv4Filterings = append((*parent).Ipv4Filterings, data)
+ return true
+ })
+ }
+ if value := res.Get("addressFamilyIPv4.networks"); value.Exists() {
+ data.Ipv4Networks = make([]DeviceBGPIpv4Networks, 0)
+ value.ForEach(func(k, res gjson.Result) bool {
+ parent := &data
+ data := DeviceBGPIpv4Networks{}
+ if value := res.Get("ipv4Address.id"); value.Exists() {
+ data.NetworkId = types.StringValue(value.String())
+ } else {
+ data.NetworkId = types.StringNull()
+ }
+ if value := res.Get("routeMap.id"); value.Exists() {
+ data.RouteMapId = types.StringValue(value.String())
+ } else {
+ data.RouteMapId = types.StringNull()
+ }
+ (*parent).Ipv4Networks = append((*parent).Ipv4Networks, data)
+ return true
+ })
+ }
+ if value := res.Get("addressFamilyIPv4.redistributeProtocols"); value.Exists() {
+ data.Ipv4Redistributions = make([]DeviceBGPIpv4Redistributions, 0)
+ value.ForEach(func(k, res gjson.Result) bool {
+ parent := &data
+ data := DeviceBGPIpv4Redistributions{}
+ if value := res.Get("type"); value.Exists() {
+ data.SourceProtocol = types.StringValue(value.String())
+ } else {
+ data.SourceProtocol = types.StringNull()
+ }
+ if value := res.Get("routeMap.id"); value.Exists() {
+ data.RouteMapId = types.StringValue(value.String())
+ } else {
+ data.RouteMapId = types.StringNull()
+ }
+ if value := res.Get("routeMetric.metricValue"); value.Exists() {
+ data.Metric = types.Int64Value(value.Int())
+ } else {
+ data.Metric = types.Int64Null()
+ }
+ if value := res.Get("processId"); value.Exists() {
+ data.ProcessId = types.StringValue(value.String())
+ } else {
+ data.ProcessId = types.StringNull()
+ }
+ if value := res.Get("matchExternal1"); value.Exists() {
+ data.MatchExternal1 = types.BoolValue(value.Bool())
+ } else {
+ data.MatchExternal1 = types.BoolNull()
+ }
+ if value := res.Get("matchExternal2"); value.Exists() {
+ data.MatchExternal2 = types.BoolValue(value.Bool())
+ } else {
+ data.MatchExternal2 = types.BoolNull()
+ }
+ if value := res.Get("matchInternal"); value.Exists() {
+ data.MatchInternal = types.BoolValue(value.Bool())
+ } else {
+ data.MatchInternal = types.BoolNull()
+ }
+ if value := res.Get("matchNssaExternal1"); value.Exists() {
+ data.MatchNssaExternal1 = types.BoolValue(value.Bool())
+ } else {
+ data.MatchNssaExternal1 = types.BoolNull()
+ }
+ if value := res.Get("matchNssaExternal2"); value.Exists() {
+ data.MatchNssaExternal2 = types.BoolValue(value.Bool())
+ } else {
+ data.MatchNssaExternal2 = types.BoolNull()
+ }
+ (*parent).Ipv4Redistributions = append((*parent).Ipv4Redistributions, data)
+ return true
+ })
+ }
+ if value := res.Get("addressFamilyIPv4.injectMaps"); value.Exists() {
+ data.Ipv4RouteInjections = make([]DeviceBGPIpv4RouteInjections, 0)
+ value.ForEach(func(k, res gjson.Result) bool {
+ parent := &data
+ data := DeviceBGPIpv4RouteInjections{}
+ if value := res.Get("injectMap.routeMap.id"); value.Exists() {
+ data.InjectRouteMapId = types.StringValue(value.String())
+ } else {
+ data.InjectRouteMapId = types.StringNull()
+ }
+ if value := res.Get("existMap.routeMap.id"); value.Exists() {
+ data.ExistRouteMapId = types.StringValue(value.String())
+ } else {
+ data.ExistRouteMapId = types.StringNull()
+ }
+ (*parent).Ipv4RouteInjections = append((*parent).Ipv4RouteInjections, data)
+ return true
+ })
+ }
+}
+
+// End of section. //template:end fromBody
+
+// Section below is generated&owned by "gen/generator.go". //template:begin fromBodyPartial
+
+// fromBodyPartial reads values from a gjson.Result into a tfstate model. It ignores null attributes in order to
+// uncouple the provider from the exact values that the backend API might summon to replace nulls. (Such behavior might
+// easily change across versions of the backend API.) For List/Set/Map attributes, the func only updates the
+// "managed" elements, instead of all elements.
+func (data *DeviceBGP) fromBodyPartial(ctx context.Context, res gjson.Result) {
+ if value := res.Get("name"); value.Exists() && !data.Name.IsNull() {
+ data.Name = types.StringValue(value.String())
+ } else {
+ data.Name = types.StringNull()
+ }
+ if value := res.Get("type"); value.Exists() && !data.Type.IsNull() {
+ data.Type = types.StringValue(value.String())
+ } else {
+ data.Type = types.StringNull()
+ }
+ if value := res.Get("asNumber"); value.Exists() && !data.AsNumber.IsNull() {
+ data.AsNumber = types.StringValue(value.String())
+ } else {
+ data.AsNumber = types.StringNull()
+ }
+ if value := res.Get("addressFamilyIPv4.type"); value.Exists() && !data.Ipv4AddressFamilyType.IsNull() {
+ data.Ipv4AddressFamilyType = types.StringValue(value.String())
+ } else {
+ data.Ipv4AddressFamilyType = types.StringNull()
+ }
+ if value := res.Get("addressFamilyIPv4.aftableMap.id"); value.Exists() && !data.Ipv4LearnedRouteMapId.IsNull() {
+ data.Ipv4LearnedRouteMapId = types.StringValue(value.String())
+ } else {
+ data.Ipv4LearnedRouteMapId = types.StringNull()
+ }
+ if value := res.Get("addressFamilyIPv4.defaultInformationOrginate"); value.Exists() && !data.Ipv4DefaultInformationOrginate.IsNull() {
+ data.Ipv4DefaultInformationOrginate = types.BoolValue(value.Bool())
+ } else {
+ data.Ipv4DefaultInformationOrginate = types.BoolNull()
+ }
+ if value := res.Get("addressFamilyIPv4.autoSummary"); value.Exists() && !data.Ipv4AutoAummary.IsNull() {
+ data.Ipv4AutoAummary = types.BoolValue(value.Bool())
+ } else {
+ data.Ipv4AutoAummary = types.BoolNull()
+ }
+ if value := res.Get("addressFamilyIPv4.bgpSupressInactive"); value.Exists() && !data.Ipv4BgpSupressInactive.IsNull() {
+ data.Ipv4BgpSupressInactive = types.BoolValue(value.Bool())
+ } else {
+ data.Ipv4BgpSupressInactive = types.BoolNull()
+ }
+ if value := res.Get("addressFamilyIPv4.synchronization"); value.Exists() && !data.Ipv4Synchronization.IsNull() {
+ data.Ipv4Synchronization = types.BoolValue(value.Bool())
+ } else {
+ data.Ipv4Synchronization = types.BoolNull()
+ }
+ if value := res.Get("addressFamilyIPv4.bgpRedistributeInternal"); value.Exists() && !data.Ipv4BgpRedistributeInternal.IsNull() {
+ data.Ipv4BgpRedistributeInternal = types.BoolValue(value.Bool())
+ } else {
+ data.Ipv4BgpRedistributeInternal = types.BoolNull()
+ }
+ if value := res.Get("addressFamilyIPv4.distance.externalDistance"); value.Exists() && !data.Ipv4ExternalDistance.IsNull() {
+ data.Ipv4ExternalDistance = types.Int64Value(value.Int())
+ } else if data.Ipv4ExternalDistance.ValueInt64() != 20 {
+ data.Ipv4ExternalDistance = types.Int64Null()
+ }
+ if value := res.Get("addressFamilyIPv4.distance.internalDistance"); value.Exists() && !data.Ipv4InternalDistance.IsNull() {
+ data.Ipv4InternalDistance = types.Int64Value(value.Int())
+ } else if data.Ipv4InternalDistance.ValueInt64() != 200 {
+ data.Ipv4InternalDistance = types.Int64Null()
+ }
+ if value := res.Get("addressFamilyIPv4.distance.localDistance"); value.Exists() && !data.Ipv4LocalDistance.IsNull() {
+ data.Ipv4LocalDistance = types.Int64Value(value.Int())
+ } else if data.Ipv4LocalDistance.ValueInt64() != 200 {
+ data.Ipv4LocalDistance = types.Int64Null()
+ }
+ if value := res.Get("addressFamilyIPv4.ibgp"); value.Exists() && !data.Ipv4ForwardPacketsOverMultipathIbgp.IsNull() {
+ data.Ipv4ForwardPacketsOverMultipathIbgp = types.Int64Value(value.Int())
+ } else if data.Ipv4ForwardPacketsOverMultipathIbgp.ValueInt64() != 1 {
+ data.Ipv4ForwardPacketsOverMultipathIbgp = types.Int64Null()
+ }
+ if value := res.Get("addressFamilyIPv4.ebgp"); value.Exists() && !data.Ipv4ForwardPacketsOverMultipathEbgp.IsNull() {
+ data.Ipv4ForwardPacketsOverMultipathEbgp = types.Int64Value(value.Int())
+ } else if data.Ipv4ForwardPacketsOverMultipathEbgp.ValueInt64() != 1 {
+ data.Ipv4ForwardPacketsOverMultipathEbgp = types.Int64Null()
+ }
+ for i := 0; i < len(data.Ipv4Neighbors); i++ {
+ keys := [...]string{"ipv4Address", "remoteAs", "neighborRoutes.neighborAdvertiseMaps.routeMap.id", "neighborRoutes.neighborAdvertiseMaps.existRouteMap.id"}
+ keyValues := [...]string{data.Ipv4Neighbors[i].NeighborAddress.ValueString(), data.Ipv4Neighbors[i].NeighborRemoteAs.ValueString(), data.Ipv4Neighbors[i].NeighborRoutesAdvertiseMapId.ValueString(), data.Ipv4Neighbors[i].NeighborRoutesAdvertiseExistNonexistMapId.ValueString()}
+
+ parent := &data
+ data := (*parent).Ipv4Neighbors[i]
+ parentRes := &res
+ var res gjson.Result
+
+ parentRes.Get("addressFamilyIPv4.neighbors").ForEach(
+ func(_, v gjson.Result) bool {
+ found := false
+ for ik := range keys {
+ if v.Get(keys[ik]).String() != keyValues[ik] {
+ found = false
+ break
+ }
+ found = true
+ }
+ if found {
+ res = v
+ return false
+ }
+ return true
+ },
+ )
+ if !res.Exists() {
+ tflog.Debug(ctx, fmt.Sprintf("removing Ipv4Neighbors[%d] = %+v",
+ i,
+ (*parent).Ipv4Neighbors[i],
+ ))
+ (*parent).Ipv4Neighbors = slices.Delete((*parent).Ipv4Neighbors, i, i+1)
+ i--
+
+ continue
+ }
+ if value := res.Get("ipv4Address"); value.Exists() && !data.NeighborAddress.IsNull() {
+ data.NeighborAddress = types.StringValue(value.String())
+ } else {
+ data.NeighborAddress = types.StringNull()
+ }
+ if value := res.Get("remoteAs"); value.Exists() && !data.NeighborRemoteAs.IsNull() {
+ data.NeighborRemoteAs = types.StringValue(value.String())
+ } else {
+ data.NeighborRemoteAs = types.StringNull()
+ }
+ if value := res.Get("neighborGeneral.fallOverBFD"); value.Exists() && !data.NeighborBfd.IsNull() {
+ data.NeighborBfd = types.StringValue(value.String())
+ } else if data.NeighborBfd.ValueString() != "NONE" {
+ data.NeighborBfd = types.StringNull()
+ }
+ if value := res.Get("neighborGeneral.updateSource.id"); value.Exists() && !data.UpdateSourceInterfaceId.IsNull() {
+ data.UpdateSourceInterfaceId = types.StringValue(value.String())
+ } else {
+ data.UpdateSourceInterfaceId = types.StringNull()
+ }
+ if value := res.Get("neighborGeneral.enableAddress"); value.Exists() && !data.EnableAddressFamily.IsNull() {
+ data.EnableAddressFamily = types.BoolValue(value.Bool())
+ } else if data.EnableAddressFamily.ValueBool() != false {
+ data.EnableAddressFamily = types.BoolNull()
+ }
+ if value := res.Get("neighborGeneral.shutdown"); value.Exists() && !data.NeighborShutdown.IsNull() {
+ data.NeighborShutdown = types.BoolValue(value.Bool())
+ } else if data.NeighborShutdown.ValueBool() != false {
+ data.NeighborShutdown = types.BoolNull()
+ }
+ if value := res.Get("neighborGeneral.description"); value.Exists() && !data.NeighborDescription.IsNull() {
+ data.NeighborDescription = types.StringValue(value.String())
+ } else {
+ data.NeighborDescription = types.StringNull()
+ }
+ for i := 0; i < len(data.NeighborFilterAccessLists); i++ {
+ keys := [...]string{"accessList.id", "filterUpdateAction"}
+ keyValues := [...]string{data.NeighborFilterAccessLists[i].AccessListId.ValueString(), data.NeighborFilterAccessLists[i].UpdateDirection.ValueString()}
+
+ parent := &data
+ data := (*parent).NeighborFilterAccessLists[i]
+ parentRes := &res
+ var res gjson.Result
+
+ parentRes.Get("neighborFiltering.neighborDistributeLists").ForEach(
+ func(_, v gjson.Result) bool {
+ found := false
+ for ik := range keys {
+ if v.Get(keys[ik]).String() != keyValues[ik] {
+ found = false
+ break
+ }
+ found = true
+ }
+ if found {
+ res = v
+ return false
+ }
+ return true
+ },
+ )
+ if !res.Exists() {
+ tflog.Debug(ctx, fmt.Sprintf("removing NeighborFilterAccessLists[%d] = %+v",
+ i,
+ (*parent).NeighborFilterAccessLists[i],
+ ))
+ (*parent).NeighborFilterAccessLists = slices.Delete((*parent).NeighborFilterAccessLists, i, i+1)
+ i--
+
+ continue
+ }
+ if value := res.Get("accessList.id"); value.Exists() && !data.AccessListId.IsNull() {
+ data.AccessListId = types.StringValue(value.String())
+ } else {
+ data.AccessListId = types.StringNull()
+ }
+ if value := res.Get("filterUpdateAction"); value.Exists() && !data.UpdateDirection.IsNull() {
+ data.UpdateDirection = types.StringValue(value.String())
+ } else {
+ data.UpdateDirection = types.StringNull()
+ }
+ (*parent).NeighborFilterAccessLists[i] = data
+ }
+ for i := 0; i < len(data.NeighborFilterRouteMapLists); i++ {
+ keys := [...]string{"RouteMap.id", "filterUpdateAction"}
+ keyValues := [...]string{data.NeighborFilterRouteMapLists[i].RouteMapId.ValueString(), data.NeighborFilterRouteMapLists[i].UpdateDirection.ValueString()}
+
+ parent := &data
+ data := (*parent).NeighborFilterRouteMapLists[i]
+ parentRes := &res
+ var res gjson.Result
+
+ parentRes.Get("neighborFiltering.neighborRouteMap").ForEach(
+ func(_, v gjson.Result) bool {
+ found := false
+ for ik := range keys {
+ if v.Get(keys[ik]).String() != keyValues[ik] {
+ found = false
+ break
+ }
+ found = true
+ }
+ if found {
+ res = v
+ return false
+ }
+ return true
+ },
+ )
+ if !res.Exists() {
+ tflog.Debug(ctx, fmt.Sprintf("removing NeighborFilterRouteMapLists[%d] = %+v",
+ i,
+ (*parent).NeighborFilterRouteMapLists[i],
+ ))
+ (*parent).NeighborFilterRouteMapLists = slices.Delete((*parent).NeighborFilterRouteMapLists, i, i+1)
+ i--
+
+ continue
+ }
+ if value := res.Get("RouteMap.id"); value.Exists() && !data.RouteMapId.IsNull() {
+ data.RouteMapId = types.StringValue(value.String())
+ } else {
+ data.RouteMapId = types.StringNull()
+ }
+ if value := res.Get("filterUpdateAction"); value.Exists() && !data.UpdateDirection.IsNull() {
+ data.UpdateDirection = types.StringValue(value.String())
+ } else {
+ data.UpdateDirection = types.StringNull()
+ }
+ (*parent).NeighborFilterRouteMapLists[i] = data
+ }
+ for i := 0; i < len(data.NeighborFilterPrefixLists); i++ {
+ keys := [...]string{"ipv4PrefixList.id", "filterUpdateAction"}
+ keyValues := [...]string{data.NeighborFilterPrefixLists[i].PrefixListId.ValueString(), data.NeighborFilterPrefixLists[i].UpdateDirection.ValueString()}
+
+ parent := &data
+ data := (*parent).NeighborFilterPrefixLists[i]
+ parentRes := &res
+ var res gjson.Result
+
+ parentRes.Get("neighborFiltering.ipv4PrefixListFilter").ForEach(
+ func(_, v gjson.Result) bool {
+ found := false
+ for ik := range keys {
+ if v.Get(keys[ik]).String() != keyValues[ik] {
+ found = false
+ break
+ }
+ found = true
+ }
+ if found {
+ res = v
+ return false
+ }
+ return true
+ },
+ )
+ if !res.Exists() {
+ tflog.Debug(ctx, fmt.Sprintf("removing NeighborFilterPrefixLists[%d] = %+v",
+ i,
+ (*parent).NeighborFilterPrefixLists[i],
+ ))
+ (*parent).NeighborFilterPrefixLists = slices.Delete((*parent).NeighborFilterPrefixLists, i, i+1)
+ i--
+
+ continue
+ }
+ if value := res.Get("ipv4PrefixList.id"); value.Exists() && !data.PrefixListId.IsNull() {
+ data.PrefixListId = types.StringValue(value.String())
+ } else {
+ data.PrefixListId = types.StringNull()
+ }
+ if value := res.Get("filterUpdateAction"); value.Exists() && !data.UpdateDirection.IsNull() {
+ data.UpdateDirection = types.StringValue(value.String())
+ } else {
+ data.UpdateDirection = types.StringNull()
+ }
+ (*parent).NeighborFilterPrefixLists[i] = data
+ }
+ for i := 0; i < len(data.NeighborFilterAsPathLists); i++ {
+ keys := [...]string{"filterUpdateAction", "asPathList.id"}
+ keyValues := [...]string{data.NeighborFilterAsPathLists[i].UpdateDirection.ValueString(), data.NeighborFilterAsPathLists[i].AsPathId.ValueString()}
+
+ parent := &data
+ data := (*parent).NeighborFilterAsPathLists[i]
+ parentRes := &res
+ var res gjson.Result
+
+ parentRes.Get("neighborFilterList.neighborFilterList").ForEach(
+ func(_, v gjson.Result) bool {
+ found := false
+ for ik := range keys {
+ if v.Get(keys[ik]).String() != keyValues[ik] {
+ found = false
+ break
+ }
+ found = true
+ }
+ if found {
+ res = v
+ return false
+ }
+ return true
+ },
+ )
+ if !res.Exists() {
+ tflog.Debug(ctx, fmt.Sprintf("removing NeighborFilterAsPathLists[%d] = %+v",
+ i,
+ (*parent).NeighborFilterAsPathLists[i],
+ ))
+ (*parent).NeighborFilterAsPathLists = slices.Delete((*parent).NeighborFilterAsPathLists, i, i+1)
+ i--
+
+ continue
+ }
+ if value := res.Get("filterUpdateAction"); value.Exists() && !data.UpdateDirection.IsNull() {
+ data.UpdateDirection = types.StringValue(value.String())
+ } else {
+ data.UpdateDirection = types.StringNull()
+ }
+ if value := res.Get("asPathList.id"); value.Exists() && !data.AsPathId.IsNull() {
+ data.AsPathId = types.StringValue(value.String())
+ } else {
+ data.AsPathId = types.StringNull()
+ }
+ (*parent).NeighborFilterAsPathLists[i] = data
+ }
+ if value := res.Get("neighborFiltering.neighborMaximumPrefix.maxPrefixLimit"); value.Exists() && !data.NeighborFilterMaxPrefix.IsNull() {
+ data.NeighborFilterMaxPrefix = types.Int64Value(value.Int())
+ } else {
+ data.NeighborFilterMaxPrefix = types.Int64Null()
+ }
+ if value := res.Get("neighborFiltering.neighborMaximumPrefix.warningOnly"); value.Exists() && !data.NeighborFilterWarningOnly.IsNull() {
+ data.NeighborFilterWarningOnly = types.BoolValue(value.Bool())
+ } else {
+ data.NeighborFilterWarningOnly = types.BoolNull()
+ }
+ if value := res.Get("neighborFiltering.neighborMaximumPrefix.thresholdValue"); value.Exists() && !data.NeighborFilterThresholdValue.IsNull() {
+ data.NeighborFilterThresholdValue = types.Int64Value(value.Int())
+ } else {
+ data.NeighborFilterThresholdValue = types.Int64Null()
+ }
+ if value := res.Get("neighborFiltering.neighborMaximumPrefix.restartInterval"); value.Exists() && !data.NeighborFilterRestartInterval.IsNull() {
+ data.NeighborFilterRestartInterval = types.Int64Value(value.Int())
+ } else {
+ data.NeighborFilterRestartInterval = types.Int64Null()
+ }
+ if value := res.Get("neighborRoutes.advertisementInterval"); value.Exists() && !data.NeighborRoutesAdvertisementInterval.IsNull() {
+ data.NeighborRoutesAdvertisementInterval = types.Int64Value(value.Int())
+ } else if data.NeighborRoutesAdvertisementInterval.ValueInt64() != 0 {
+ data.NeighborRoutesAdvertisementInterval = types.Int64Null()
+ }
+ if value := res.Get("neighborRoutes.removePrivateAs"); value.Exists() && !data.NeighborRoutesRemovePrivateAs.IsNull() {
+ data.NeighborRoutesRemovePrivateAs = types.BoolValue(value.Bool())
+ } else if data.NeighborRoutesRemovePrivateAs.ValueBool() != false {
+ data.NeighborRoutesRemovePrivateAs = types.BoolNull()
+ }
+ if value := res.Get("neighborFiltering.neighborDefaultOriginate.routeMap.id"); value.Exists() && !data.NeighborGenerateDefaultRouteMapId.IsNull() {
+ data.NeighborGenerateDefaultRouteMapId = types.StringValue(value.String())
+ } else {
+ data.NeighborGenerateDefaultRouteMapId = types.StringNull()
+ }
+ if value := res.Get("neighborRoutes.neighborAdvertiseMaps.existMap"); value.Exists() && !data.NeighborRoutesAdvertiseMapUseExist.IsNull() {
+ data.NeighborRoutesAdvertiseMapUseExist = types.BoolValue(value.Bool())
+ } else {
+ data.NeighborRoutesAdvertiseMapUseExist = types.BoolNull()
+ }
+ if value := res.Get("neighborRoutes.neighborAdvertiseMaps.routeMap.id"); value.Exists() && !data.NeighborRoutesAdvertiseMapId.IsNull() {
+ data.NeighborRoutesAdvertiseMapId = types.StringValue(value.String())
+ } else {
+ data.NeighborRoutesAdvertiseMapId = types.StringNull()
+ }
+ if value := res.Get("neighborRoutes.neighborAdvertiseMaps.existRouteMap.id"); value.Exists() && !data.NeighborRoutesAdvertiseExistNonexistMapId.IsNull() {
+ data.NeighborRoutesAdvertiseExistNonexistMapId = types.StringValue(value.String())
+ } else {
+ data.NeighborRoutesAdvertiseExistNonexistMapId = types.StringNull()
+ }
+ if value := res.Get("neighborTimers.keepAliveInterval"); value.Exists() && !data.NeighborKeepaliveInterval.IsNull() {
+ data.NeighborKeepaliveInterval = types.Int64Value(value.Int())
+ } else {
+ data.NeighborKeepaliveInterval = types.Int64Null()
+ }
+ if value := res.Get("neighborTimers.holdTime"); value.Exists() && !data.NeighborHoldTime.IsNull() {
+ data.NeighborHoldTime = types.Int64Value(value.Int())
+ } else {
+ data.NeighborHoldTime = types.Int64Null()
+ }
+ if value := res.Get("neighborTimers.minimumHoldTime"); value.Exists() && !data.NeighborMinHoldTime.IsNull() {
+ data.NeighborMinHoldTime = types.Int64Value(value.Int())
+ } else {
+ data.NeighborMinHoldTime = types.Int64Null()
+ }
+ if value := res.Get("neighborAdvanced.neighborSecret"); value.Exists() && !data.NeighborAuthenticationPassword.IsNull() {
+ data.NeighborAuthenticationPassword = types.StringValue(value.String())
+ } else {
+ data.NeighborAuthenticationPassword = types.StringNull()
+ }
+ if value := res.Get("neighborAdvanced.sendCommunity"); value.Exists() && !data.NeighborSendCommunityAttribute.IsNull() {
+ data.NeighborSendCommunityAttribute = types.BoolValue(value.Bool())
+ } else if data.NeighborSendCommunityAttribute.ValueBool() != false {
+ data.NeighborSendCommunityAttribute = types.BoolNull()
+ }
+ if value := res.Get("neighborAdvanced.nextHopSelf"); value.Exists() && !data.NeighborNexthopSelf.IsNull() {
+ data.NeighborNexthopSelf = types.BoolValue(value.Bool())
+ } else if data.NeighborNexthopSelf.ValueBool() != false {
+ data.NeighborNexthopSelf = types.BoolNull()
+ }
+ if value := res.Get("neighborAdvanced.neighborHops.disableConnectedCheck"); value.Exists() && !data.NeighborDisableConnectionVerification.IsNull() {
+ data.NeighborDisableConnectionVerification = types.BoolValue(value.Bool())
+ } else if data.NeighborDisableConnectionVerification.ValueBool() != false {
+ data.NeighborDisableConnectionVerification = types.BoolNull()
+ }
+ if value := res.Get("neighborAdvanced.neighborTransportPathMTUDiscovery.disable"); value.Exists() && !data.NeighborTcpMtuPathDiscovery.IsNull() {
+ data.NeighborTcpMtuPathDiscovery = types.BoolValue(value.Bool())
+ } else if data.NeighborTcpMtuPathDiscovery.ValueBool() != false {
+ data.NeighborTcpMtuPathDiscovery = types.BoolNull()
+ }
+ if value := res.Get("neighborAdvanced.neighborHops.maxHopCount"); value.Exists() && !data.NeighborMaxHopCount.IsNull() {
+ data.NeighborMaxHopCount = types.Int64Value(value.Int())
+ } else if data.NeighborMaxHopCount.ValueInt64() != 1 {
+ data.NeighborMaxHopCount = types.Int64Null()
+ }
+ if value := res.Get("neighborAdvanced.neighborTransportConnectionMode.establishTCPSession"); value.Exists() && !data.NeighborTcpTransportMode.IsNull() {
+ data.NeighborTcpTransportMode = types.BoolValue(value.Bool())
+ } else if data.NeighborTcpTransportMode.ValueBool() != false {
+ data.NeighborTcpTransportMode = types.BoolNull()
+ }
+ if value := res.Get("neighborAdvanced.neighborWeight"); value.Exists() && !data.NeighborWeight.IsNull() {
+ data.NeighborWeight = types.Int64Value(value.Int())
+ } else if data.NeighborWeight.ValueInt64() != 0 {
+ data.NeighborWeight = types.Int64Null()
+ }
+ if value := res.Get("neighborAdvanced.neighborVersion"); value.Exists() && !data.NeighborVersion.IsNull() {
+ data.NeighborVersion = types.StringValue(value.String())
+ } else if data.NeighborVersion.ValueString() != "0" {
+ data.NeighborVersion = types.StringNull()
+ }
+ if value := res.Get("neighborLocalAs.asNumber"); value.Exists() && !data.NeighborCustomizedLocalAsNumber.IsNull() {
+ data.NeighborCustomizedLocalAsNumber = types.StringValue(value.String())
+ } else {
+ data.NeighborCustomizedLocalAsNumber = types.StringNull()
+ }
+ if value := res.Get("neighborLocalAs.noPrepend"); value.Exists() && !data.NeighborCustomizedNoPrepend.IsNull() {
+ data.NeighborCustomizedNoPrepend = types.BoolValue(value.Bool())
+ } else {
+ data.NeighborCustomizedNoPrepend = types.BoolNull()
+ }
+ if value := res.Get("neighborLocalAs.replaceAs"); value.Exists() && !data.NeighborCustomizedReplaceAs.IsNull() {
+ data.NeighborCustomizedReplaceAs = types.BoolValue(value.Bool())
+ } else {
+ data.NeighborCustomizedReplaceAs = types.BoolNull()
+ }
+ if value := res.Get("neighborLocalAs.dualAs"); value.Exists() && !data.NeighborCustomizedAcceptBothAs.IsNull() {
+ data.NeighborCustomizedAcceptBothAs = types.BoolValue(value.Bool())
+ } else {
+ data.NeighborCustomizedAcceptBothAs = types.BoolNull()
+ }
+ (*parent).Ipv4Neighbors[i] = data
+ }
+ for i := 0; i < len(data.Ipv4AggregateAddresses); i++ {
+ keys := [...]string{"ipv4AggregateNetwork.id", "advertiseMap.id", "attributeMap.id", "suppressMap.id"}
+ keyValues := [...]string{data.Ipv4AggregateAddresses[i].NetworkId.ValueString(), data.Ipv4AggregateAddresses[i].AdvertiseMapId.ValueString(), data.Ipv4AggregateAddresses[i].AttributeMapId.ValueString(), data.Ipv4AggregateAddresses[i].SuppressMapId.ValueString()}
+
+ parent := &data
+ data := (*parent).Ipv4AggregateAddresses[i]
+ parentRes := &res
+ var res gjson.Result
+
+ parentRes.Get("addressFamilyIPv4.aggregateAddressesIPv4s").ForEach(
+ func(_, v gjson.Result) bool {
+ found := false
+ for ik := range keys {
+ if v.Get(keys[ik]).String() != keyValues[ik] {
+ found = false
+ break
+ }
+ found = true
+ }
+ if found {
+ res = v
+ return false
+ }
+ return true
+ },
+ )
+ if !res.Exists() {
+ tflog.Debug(ctx, fmt.Sprintf("removing Ipv4AggregateAddresses[%d] = %+v",
+ i,
+ (*parent).Ipv4AggregateAddresses[i],
+ ))
+ (*parent).Ipv4AggregateAddresses = slices.Delete((*parent).Ipv4AggregateAddresses, i, i+1)
+ i--
+
+ continue
+ }
+ if value := res.Get("asSet"); value.Exists() && !data.GenerateAs.IsNull() {
+ data.GenerateAs = types.BoolValue(value.Bool())
+ } else {
+ data.GenerateAs = types.BoolNull()
+ }
+ if value := res.Get("summaryOnly"); value.Exists() && !data.Filter.IsNull() {
+ data.Filter = types.BoolValue(value.Bool())
+ } else {
+ data.Filter = types.BoolNull()
+ }
+ if value := res.Get("ipv4AggregateNetwork.id"); value.Exists() && !data.NetworkId.IsNull() {
+ data.NetworkId = types.StringValue(value.String())
+ } else {
+ data.NetworkId = types.StringNull()
+ }
+ if value := res.Get("advertiseMap.id"); value.Exists() && !data.AdvertiseMapId.IsNull() {
+ data.AdvertiseMapId = types.StringValue(value.String())
+ } else {
+ data.AdvertiseMapId = types.StringNull()
+ }
+ if value := res.Get("attributeMap.id"); value.Exists() && !data.AttributeMapId.IsNull() {
+ data.AttributeMapId = types.StringValue(value.String())
+ } else {
+ data.AttributeMapId = types.StringNull()
+ }
+ if value := res.Get("suppressMap.id"); value.Exists() && !data.SuppressMapId.IsNull() {
+ data.SuppressMapId = types.StringValue(value.String())
+ } else {
+ data.SuppressMapId = types.StringNull()
+ }
+ (*parent).Ipv4AggregateAddresses[i] = data
+ }
+ for i := 0; i < len(data.Ipv4Filterings); i++ {
+ keys := [...]string{"ipv4AggregateNetwork.id"}
+ keyValues := [...]string{data.Ipv4Filterings[i].AccessListId.ValueString()}
+
+ parent := &data
+ data := (*parent).Ipv4Filterings[i]
+ parentRes := &res
+ var res gjson.Result
+
+ parentRes.Get("addressFamilyIPv4.distributeLists").ForEach(
+ func(_, v gjson.Result) bool {
+ found := false
+ for ik := range keys {
+ if v.Get(keys[ik]).String() != keyValues[ik] {
+ found = false
+ break
+ }
+ found = true
+ }
+ if found {
+ res = v
+ return false
+ }
+ return true
+ },
+ )
+ if !res.Exists() {
+ tflog.Debug(ctx, fmt.Sprintf("removing Ipv4Filterings[%d] = %+v",
+ i,
+ (*parent).Ipv4Filterings[i],
+ ))
+ (*parent).Ipv4Filterings = slices.Delete((*parent).Ipv4Filterings, i, i+1)
+ i--
+
+ continue
+ }
+ if value := res.Get("ipv4AggregateNetwork.id"); value.Exists() && !data.AccessListId.IsNull() {
+ data.AccessListId = types.StringValue(value.String())
+ } else {
+ data.AccessListId = types.StringNull()
+ }
+ if value := res.Get("type"); value.Exists() && !data.NetworkDirection.IsNull() {
+ data.NetworkDirection = types.StringValue(value.String())
+ } else {
+ data.NetworkDirection = types.StringNull()
+ }
+ if value := res.Get("protocol.protocol"); value.Exists() && !data.Protocol.IsNull() {
+ data.Protocol = types.StringValue(value.String())
+ } else {
+ data.Protocol = types.StringNull()
+ }
+ if value := res.Get("protocol.processId"); value.Exists() && !data.ProrocolProcess.IsNull() {
+ data.ProrocolProcess = types.StringValue(value.String())
+ } else {
+ data.ProrocolProcess = types.StringNull()
+ }
+ (*parent).Ipv4Filterings[i] = data
+ }
+ for i := 0; i < len(data.Ipv4Networks); i++ {
+ keys := [...]string{"ipv4Address.id", "routeMap.id"}
+ keyValues := [...]string{data.Ipv4Networks[i].NetworkId.ValueString(), data.Ipv4Networks[i].RouteMapId.ValueString()}
+
+ parent := &data
+ data := (*parent).Ipv4Networks[i]
+ parentRes := &res
+ var res gjson.Result
+
+ parentRes.Get("addressFamilyIPv4.networks").ForEach(
+ func(_, v gjson.Result) bool {
+ found := false
+ for ik := range keys {
+ if v.Get(keys[ik]).String() != keyValues[ik] {
+ found = false
+ break
+ }
+ found = true
+ }
+ if found {
+ res = v
+ return false
+ }
+ return true
+ },
+ )
+ if !res.Exists() {
+ tflog.Debug(ctx, fmt.Sprintf("removing Ipv4Networks[%d] = %+v",
+ i,
+ (*parent).Ipv4Networks[i],
+ ))
+ (*parent).Ipv4Networks = slices.Delete((*parent).Ipv4Networks, i, i+1)
+ i--
+
+ continue
+ }
+ if value := res.Get("ipv4Address.id"); value.Exists() && !data.NetworkId.IsNull() {
+ data.NetworkId = types.StringValue(value.String())
+ } else {
+ data.NetworkId = types.StringNull()
+ }
+ if value := res.Get("routeMap.id"); value.Exists() && !data.RouteMapId.IsNull() {
+ data.RouteMapId = types.StringValue(value.String())
+ } else {
+ data.RouteMapId = types.StringNull()
+ }
+ (*parent).Ipv4Networks[i] = data
+ }
+ for i := 0; i < len(data.Ipv4Redistributions); i++ {
+ keys := [...]string{"routeMap.id"}
+ keyValues := [...]string{data.Ipv4Redistributions[i].RouteMapId.ValueString()}
+
+ parent := &data
+ data := (*parent).Ipv4Redistributions[i]
+ parentRes := &res
+ var res gjson.Result
+
+ parentRes.Get("addressFamilyIPv4.redistributeProtocols").ForEach(
+ func(_, v gjson.Result) bool {
+ found := false
+ for ik := range keys {
+ if v.Get(keys[ik]).String() != keyValues[ik] {
+ found = false
+ break
+ }
+ found = true
+ }
+ if found {
+ res = v
+ return false
+ }
+ return true
+ },
+ )
+ if !res.Exists() {
+ tflog.Debug(ctx, fmt.Sprintf("removing Ipv4Redistributions[%d] = %+v",
+ i,
+ (*parent).Ipv4Redistributions[i],
+ ))
+ (*parent).Ipv4Redistributions = slices.Delete((*parent).Ipv4Redistributions, i, i+1)
+ i--
+
+ continue
+ }
+ if value := res.Get("type"); value.Exists() && !data.SourceProtocol.IsNull() {
+ data.SourceProtocol = types.StringValue(value.String())
+ } else {
+ data.SourceProtocol = types.StringNull()
+ }
+ if value := res.Get("routeMap.id"); value.Exists() && !data.RouteMapId.IsNull() {
+ data.RouteMapId = types.StringValue(value.String())
+ } else {
+ data.RouteMapId = types.StringNull()
+ }
+ if value := res.Get("routeMetric.metricValue"); value.Exists() && !data.Metric.IsNull() {
+ data.Metric = types.Int64Value(value.Int())
+ } else {
+ data.Metric = types.Int64Null()
+ }
+ if value := res.Get("processId"); value.Exists() && !data.ProcessId.IsNull() {
+ data.ProcessId = types.StringValue(value.String())
+ } else {
+ data.ProcessId = types.StringNull()
+ }
+ if value := res.Get("matchExternal1"); value.Exists() && !data.MatchExternal1.IsNull() {
+ data.MatchExternal1 = types.BoolValue(value.Bool())
+ } else {
+ data.MatchExternal1 = types.BoolNull()
+ }
+ if value := res.Get("matchExternal2"); value.Exists() && !data.MatchExternal2.IsNull() {
+ data.MatchExternal2 = types.BoolValue(value.Bool())
+ } else {
+ data.MatchExternal2 = types.BoolNull()
+ }
+ if value := res.Get("matchInternal"); value.Exists() && !data.MatchInternal.IsNull() {
+ data.MatchInternal = types.BoolValue(value.Bool())
+ } else {
+ data.MatchInternal = types.BoolNull()
+ }
+ if value := res.Get("matchNssaExternal1"); value.Exists() && !data.MatchNssaExternal1.IsNull() {
+ data.MatchNssaExternal1 = types.BoolValue(value.Bool())
+ } else {
+ data.MatchNssaExternal1 = types.BoolNull()
+ }
+ if value := res.Get("matchNssaExternal2"); value.Exists() && !data.MatchNssaExternal2.IsNull() {
+ data.MatchNssaExternal2 = types.BoolValue(value.Bool())
+ } else {
+ data.MatchNssaExternal2 = types.BoolNull()
+ }
+ (*parent).Ipv4Redistributions[i] = data
+ }
+ for i := 0; i < len(data.Ipv4RouteInjections); i++ {
+ keys := [...]string{"injectMap.routeMap.id", "existMap.routeMap.id"}
+ keyValues := [...]string{data.Ipv4RouteInjections[i].InjectRouteMapId.ValueString(), data.Ipv4RouteInjections[i].ExistRouteMapId.ValueString()}
+
+ parent := &data
+ data := (*parent).Ipv4RouteInjections[i]
+ parentRes := &res
+ var res gjson.Result
+
+ parentRes.Get("addressFamilyIPv4.injectMaps").ForEach(
+ func(_, v gjson.Result) bool {
+ found := false
+ for ik := range keys {
+ if v.Get(keys[ik]).String() != keyValues[ik] {
+ found = false
+ break
+ }
+ found = true
+ }
+ if found {
+ res = v
+ return false
+ }
+ return true
+ },
+ )
+ if !res.Exists() {
+ tflog.Debug(ctx, fmt.Sprintf("removing Ipv4RouteInjections[%d] = %+v",
+ i,
+ (*parent).Ipv4RouteInjections[i],
+ ))
+ (*parent).Ipv4RouteInjections = slices.Delete((*parent).Ipv4RouteInjections, i, i+1)
+ i--
+
+ continue
+ }
+ if value := res.Get("injectMap.routeMap.id"); value.Exists() && !data.InjectRouteMapId.IsNull() {
+ data.InjectRouteMapId = types.StringValue(value.String())
+ } else {
+ data.InjectRouteMapId = types.StringNull()
+ }
+ if value := res.Get("existMap.routeMap.id"); value.Exists() && !data.ExistRouteMapId.IsNull() {
+ data.ExistRouteMapId = types.StringValue(value.String())
+ } else {
+ data.ExistRouteMapId = types.StringNull()
+ }
+ (*parent).Ipv4RouteInjections[i] = data
+ }
+}
+
+// End of section. //template:end fromBodyPartial
+
+// Section below is generated&owned by "gen/generator.go". //template:begin fromBodyUnknowns
+
+// fromBodyUnknowns updates the Unknown Computed tfstate values from a JSON.
+// Known values are not changed (usual for Computed attributes with UseStateForUnknown or with Default).
+func (data *DeviceBGP) fromBodyUnknowns(ctx context.Context, res gjson.Result) {
+ if data.Name.IsUnknown() {
+ if value := res.Get("name"); value.Exists() {
+ data.Name = types.StringValue(value.String())
+ } else {
+ data.Name = types.StringNull()
+ }
+ }
+ if data.Type.IsUnknown() {
+ if value := res.Get("type"); value.Exists() {
+ data.Type = types.StringValue(value.String())
+ } else {
+ data.Type = types.StringNull()
+ }
+ }
+ if data.AsNumber.IsUnknown() {
+ if value := res.Get("asNumber"); value.Exists() {
+ data.AsNumber = types.StringValue(value.String())
+ } else {
+ data.AsNumber = types.StringNull()
+ }
+ }
+ if data.Ipv4AddressFamilyType.IsUnknown() {
+ if value := res.Get("addressFamilyIPv4.type"); value.Exists() {
+ data.Ipv4AddressFamilyType = types.StringValue(value.String())
+ } else {
+ data.Ipv4AddressFamilyType = types.StringNull()
+ }
+ }
+}
+
+// End of section. //template:end fromBodyUnknowns
+
+// Section below is generated&owned by "gen/generator.go". //template:begin Clone
+
+// End of section. //template:end Clone
+
+// Section below is generated&owned by "gen/generator.go". //template:begin toBodyNonBulk
+
+// End of section. //template:end toBodyNonBulk
diff --git a/internal/provider/model_fmc_device_bgp_general_settings.go b/internal/provider/model_fmc_device_bgp_general_settings.go
new file mode 100644
index 00000000..ce960e0b
--- /dev/null
+++ b/internal/provider/model_fmc_device_bgp_general_settings.go
@@ -0,0 +1,436 @@
+// Copyright © 2023 Cisco Systems, Inc. and its affiliates.
+// All rights reserved.
+//
+// Licensed under the Mozilla Public License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://mozilla.org/MPL/2.0/
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// SPDX-License-Identifier: MPL-2.0
+
+package provider
+
+// Section below is generated&owned by "gen/generator.go". //template:begin imports
+import (
+ "context"
+ "fmt"
+ "net/url"
+
+ "github.com/hashicorp/terraform-plugin-framework/types"
+ "github.com/tidwall/gjson"
+ "github.com/tidwall/sjson"
+)
+
+// End of section. //template:end imports
+
+// Section below is generated&owned by "gen/generator.go". //template:begin types
+
+type DeviceBGPGeneralSettings struct {
+ Id types.String `tfsdk:"id"`
+ Domain types.String `tfsdk:"domain"`
+ DeviceId types.String `tfsdk:"device_id"`
+ Name types.String `tfsdk:"name"`
+ AsNumber types.String `tfsdk:"as_number"`
+ RouterId types.String `tfsdk:"router_id"`
+ ScanningInterval types.Int64 `tfsdk:"scanning_interval"`
+ AsNumberInPathAttribute types.Int64 `tfsdk:"as_number_in_path_attribute"`
+ LogNeighborChanges types.Bool `tfsdk:"log_neighbor_changes"`
+ TcpPathMtuDiscovery types.Bool `tfsdk:"tcp_path_mtu_discovery"`
+ ResetSessionUponFailover types.Bool `tfsdk:"reset_session_upon_failover"`
+ EnforceFirstPeerAs types.Bool `tfsdk:"enforce_first_peer_as"`
+ UseDotNotation types.Bool `tfsdk:"use_dot_notation"`
+ AggregateTimer types.Int64 `tfsdk:"aggregate_timer"`
+ DefaultLocalPreference types.Int64 `tfsdk:"default_local_preference"`
+ CompareMedFromDifferentNeighbors types.Bool `tfsdk:"compare_med_from_different_neighbors"`
+ CompareRouterIdInPath types.Bool `tfsdk:"compare_router_id_in_path"`
+ PickBestMed types.Bool `tfsdk:"pick_best_med"`
+ MissingMedAsBest types.Bool `tfsdk:"missing_med_as_best"`
+ KeepaliveInterval types.Int64 `tfsdk:"keepalive_interval"`
+ HoldTime types.Int64 `tfsdk:"hold_time"`
+ MinHoldTime types.Int64 `tfsdk:"min_hold_time"`
+ NextHopAddressTracking types.Bool `tfsdk:"next_hop_address_tracking"`
+ NextHopDelayInterval types.Int64 `tfsdk:"next_hop_delay_interval"`
+ GracefulRestart types.Bool `tfsdk:"graceful_restart"`
+ GracefulRestartRestartTime types.Int64 `tfsdk:"graceful_restart_restart_time"`
+ GracefulRestartStalePathTime types.Int64 `tfsdk:"graceful_restart_stale_path_time"`
+}
+
+// End of section. //template:end types
+
+// Section below is generated&owned by "gen/generator.go". //template:begin getPath
+
+func (data DeviceBGPGeneralSettings) getPath() string {
+ return fmt.Sprintf("/api/fmc_config/v1/domain/{DOMAIN_UUID}/devices/devicerecords/%v/routing/bgpgeneralsettings", url.QueryEscape(data.DeviceId.ValueString()))
+}
+
+// End of section. //template:end getPath
+
+// Section below is generated&owned by "gen/generator.go". //template:begin toBody
+
+func (data DeviceBGPGeneralSettings) toBody(ctx context.Context, state DeviceBGPGeneralSettings) string {
+ body := ""
+ if data.Id.ValueString() != "" {
+ body, _ = sjson.Set(body, "id", data.Id.ValueString())
+ }
+ if !data.AsNumber.IsNull() {
+ body, _ = sjson.Set(body, "asNumber", data.AsNumber.ValueString())
+ }
+ if !data.RouterId.IsNull() {
+ body, _ = sjson.Set(body, "routerId", data.RouterId.ValueString())
+ }
+ if !data.ScanningInterval.IsNull() {
+ body, _ = sjson.Set(body, "scanTime", data.ScanningInterval.ValueInt64())
+ }
+ if !data.AsNumberInPathAttribute.IsNull() {
+ body, _ = sjson.Set(body, "maxasLimit", data.AsNumberInPathAttribute.ValueInt64())
+ }
+ if !data.LogNeighborChanges.IsNull() {
+ body, _ = sjson.Set(body, "logNeighborChanges", data.LogNeighborChanges.ValueBool())
+ }
+ if !data.TcpPathMtuDiscovery.IsNull() {
+ body, _ = sjson.Set(body, "transportPathMtuDiscovery", data.TcpPathMtuDiscovery.ValueBool())
+ }
+ if !data.ResetSessionUponFailover.IsNull() {
+ body, _ = sjson.Set(body, "fastExternalFallOver", data.ResetSessionUponFailover.ValueBool())
+ }
+ if !data.EnforceFirstPeerAs.IsNull() {
+ body, _ = sjson.Set(body, "enforceFirstAs", data.EnforceFirstPeerAs.ValueBool())
+ }
+ if !data.UseDotNotation.IsNull() {
+ body, _ = sjson.Set(body, "asnotationDot", data.UseDotNotation.ValueBool())
+ }
+ if !data.AggregateTimer.IsNull() {
+ body, _ = sjson.Set(body, "aggregateTimer", data.AggregateTimer.ValueInt64())
+ }
+ if !data.DefaultLocalPreference.IsNull() {
+ body, _ = sjson.Set(body, "bestPath.defaultLocalPreferenceValue", data.DefaultLocalPreference.ValueInt64())
+ }
+ if !data.CompareMedFromDifferentNeighbors.IsNull() {
+ body, _ = sjson.Set(body, "bestPath.alwaysCompareMed", data.CompareMedFromDifferentNeighbors.ValueBool())
+ }
+ if !data.CompareRouterIdInPath.IsNull() {
+ body, _ = sjson.Set(body, "bestPath.deterministicMed", data.CompareRouterIdInPath.ValueBool())
+ }
+ if !data.PickBestMed.IsNull() {
+ body, _ = sjson.Set(body, "bestPath.bestPathCompareRouterId", data.PickBestMed.ValueBool())
+ }
+ if !data.MissingMedAsBest.IsNull() {
+ body, _ = sjson.Set(body, "bestPath.bestPathMedMissingAsWorst", data.MissingMedAsBest.ValueBool())
+ }
+ if !data.KeepaliveInterval.IsNull() {
+ body, _ = sjson.Set(body, "bgptimers.keepAlive", data.KeepaliveInterval.ValueInt64())
+ }
+ if !data.HoldTime.IsNull() {
+ body, _ = sjson.Set(body, "bgptimers.holdTime", data.HoldTime.ValueInt64())
+ }
+ if !data.MinHoldTime.IsNull() {
+ body, _ = sjson.Set(body, "bgptimers.minHoldTime", data.MinHoldTime.ValueInt64())
+ }
+ if !data.NextHopAddressTracking.IsNull() {
+ body, _ = sjson.Set(body, "bgpNextHopTriggerEnable", data.NextHopAddressTracking.ValueBool())
+ }
+ if !data.NextHopDelayInterval.IsNull() {
+ body, _ = sjson.Set(body, "bgpNextHopTriggerDelay", data.NextHopDelayInterval.ValueInt64())
+ }
+ if !data.GracefulRestart.IsNull() {
+ body, _ = sjson.Set(body, "bgpGracefulRestart.gracefulRestart", data.GracefulRestart.ValueBool())
+ }
+ if !data.GracefulRestartRestartTime.IsNull() {
+ body, _ = sjson.Set(body, "bgpGracefulRestart.gracefulRestartRestartTime", data.GracefulRestartRestartTime.ValueInt64())
+ }
+ if !data.GracefulRestartStalePathTime.IsNull() {
+ body, _ = sjson.Set(body, "bgpGracefulRestart.gracefulRestartStalePathTime", data.GracefulRestartStalePathTime.ValueInt64())
+ }
+ return body
+}
+
+// End of section. //template:end toBody
+
+// Section below is generated&owned by "gen/generator.go". //template:begin fromBody
+
+func (data *DeviceBGPGeneralSettings) fromBody(ctx context.Context, res gjson.Result) {
+ if value := res.Get("name"); value.Exists() {
+ data.Name = types.StringValue(value.String())
+ } else {
+ data.Name = types.StringNull()
+ }
+ if value := res.Get("asNumber"); value.Exists() {
+ data.AsNumber = types.StringValue(value.String())
+ } else {
+ data.AsNumber = types.StringNull()
+ }
+ if value := res.Get("routerId"); value.Exists() {
+ data.RouterId = types.StringValue(value.String())
+ } else {
+ data.RouterId = types.StringNull()
+ }
+ if value := res.Get("scanTime"); value.Exists() {
+ data.ScanningInterval = types.Int64Value(value.Int())
+ } else {
+ data.ScanningInterval = types.Int64Null()
+ }
+ if value := res.Get("maxasLimit"); value.Exists() {
+ data.AsNumberInPathAttribute = types.Int64Value(value.Int())
+ } else {
+ data.AsNumberInPathAttribute = types.Int64Null()
+ }
+ if value := res.Get("logNeighborChanges"); value.Exists() {
+ data.LogNeighborChanges = types.BoolValue(value.Bool())
+ } else {
+ data.LogNeighborChanges = types.BoolNull()
+ }
+ if value := res.Get("transportPathMtuDiscovery"); value.Exists() {
+ data.TcpPathMtuDiscovery = types.BoolValue(value.Bool())
+ } else {
+ data.TcpPathMtuDiscovery = types.BoolNull()
+ }
+ if value := res.Get("fastExternalFallOver"); value.Exists() {
+ data.ResetSessionUponFailover = types.BoolValue(value.Bool())
+ } else {
+ data.ResetSessionUponFailover = types.BoolNull()
+ }
+ if value := res.Get("enforceFirstAs"); value.Exists() {
+ data.EnforceFirstPeerAs = types.BoolValue(value.Bool())
+ } else {
+ data.EnforceFirstPeerAs = types.BoolNull()
+ }
+ if value := res.Get("asnotationDot"); value.Exists() {
+ data.UseDotNotation = types.BoolValue(value.Bool())
+ } else {
+ data.UseDotNotation = types.BoolNull()
+ }
+ if value := res.Get("aggregateTimer"); value.Exists() {
+ data.AggregateTimer = types.Int64Value(value.Int())
+ } else {
+ data.AggregateTimer = types.Int64Null()
+ }
+ if value := res.Get("bestPath.defaultLocalPreferenceValue"); value.Exists() {
+ data.DefaultLocalPreference = types.Int64Value(value.Int())
+ } else {
+ data.DefaultLocalPreference = types.Int64Null()
+ }
+ if value := res.Get("bestPath.alwaysCompareMed"); value.Exists() {
+ data.CompareMedFromDifferentNeighbors = types.BoolValue(value.Bool())
+ } else {
+ data.CompareMedFromDifferentNeighbors = types.BoolNull()
+ }
+ if value := res.Get("bestPath.deterministicMed"); value.Exists() {
+ data.CompareRouterIdInPath = types.BoolValue(value.Bool())
+ } else {
+ data.CompareRouterIdInPath = types.BoolNull()
+ }
+ if value := res.Get("bestPath.bestPathCompareRouterId"); value.Exists() {
+ data.PickBestMed = types.BoolValue(value.Bool())
+ } else {
+ data.PickBestMed = types.BoolNull()
+ }
+ if value := res.Get("bestPath.bestPathMedMissingAsWorst"); value.Exists() {
+ data.MissingMedAsBest = types.BoolValue(value.Bool())
+ } else {
+ data.MissingMedAsBest = types.BoolNull()
+ }
+ if value := res.Get("bgptimers.keepAlive"); value.Exists() {
+ data.KeepaliveInterval = types.Int64Value(value.Int())
+ } else {
+ data.KeepaliveInterval = types.Int64Null()
+ }
+ if value := res.Get("bgptimers.holdTime"); value.Exists() {
+ data.HoldTime = types.Int64Value(value.Int())
+ } else {
+ data.HoldTime = types.Int64Null()
+ }
+ if value := res.Get("bgptimers.minHoldTime"); value.Exists() {
+ data.MinHoldTime = types.Int64Value(value.Int())
+ } else {
+ data.MinHoldTime = types.Int64Null()
+ }
+ if value := res.Get("bgpNextHopTriggerEnable"); value.Exists() {
+ data.NextHopAddressTracking = types.BoolValue(value.Bool())
+ } else {
+ data.NextHopAddressTracking = types.BoolNull()
+ }
+ if value := res.Get("bgpNextHopTriggerDelay"); value.Exists() {
+ data.NextHopDelayInterval = types.Int64Value(value.Int())
+ } else {
+ data.NextHopDelayInterval = types.Int64Null()
+ }
+ if value := res.Get("bgpGracefulRestart.gracefulRestart"); value.Exists() {
+ data.GracefulRestart = types.BoolValue(value.Bool())
+ } else {
+ data.GracefulRestart = types.BoolNull()
+ }
+ if value := res.Get("bgpGracefulRestart.gracefulRestartRestartTime"); value.Exists() {
+ data.GracefulRestartRestartTime = types.Int64Value(value.Int())
+ } else {
+ data.GracefulRestartRestartTime = types.Int64Null()
+ }
+ if value := res.Get("bgpGracefulRestart.gracefulRestartStalePathTime"); value.Exists() {
+ data.GracefulRestartStalePathTime = types.Int64Value(value.Int())
+ } else {
+ data.GracefulRestartStalePathTime = types.Int64Null()
+ }
+}
+
+// End of section. //template:end fromBody
+
+// Section below is generated&owned by "gen/generator.go". //template:begin fromBodyPartial
+
+// fromBodyPartial reads values from a gjson.Result into a tfstate model. It ignores null attributes in order to
+// uncouple the provider from the exact values that the backend API might summon to replace nulls. (Such behavior might
+// easily change across versions of the backend API.) For List/Set/Map attributes, the func only updates the
+// "managed" elements, instead of all elements.
+func (data *DeviceBGPGeneralSettings) fromBodyPartial(ctx context.Context, res gjson.Result) {
+ if value := res.Get("name"); value.Exists() && !data.Name.IsNull() {
+ data.Name = types.StringValue(value.String())
+ } else {
+ data.Name = types.StringNull()
+ }
+ if value := res.Get("asNumber"); value.Exists() && !data.AsNumber.IsNull() {
+ data.AsNumber = types.StringValue(value.String())
+ } else {
+ data.AsNumber = types.StringNull()
+ }
+ if value := res.Get("routerId"); value.Exists() && !data.RouterId.IsNull() {
+ data.RouterId = types.StringValue(value.String())
+ } else {
+ data.RouterId = types.StringNull()
+ }
+ if value := res.Get("scanTime"); value.Exists() && !data.ScanningInterval.IsNull() {
+ data.ScanningInterval = types.Int64Value(value.Int())
+ } else {
+ data.ScanningInterval = types.Int64Null()
+ }
+ if value := res.Get("maxasLimit"); value.Exists() && !data.AsNumberInPathAttribute.IsNull() {
+ data.AsNumberInPathAttribute = types.Int64Value(value.Int())
+ } else {
+ data.AsNumberInPathAttribute = types.Int64Null()
+ }
+ if value := res.Get("logNeighborChanges"); value.Exists() && !data.LogNeighborChanges.IsNull() {
+ data.LogNeighborChanges = types.BoolValue(value.Bool())
+ } else {
+ data.LogNeighborChanges = types.BoolNull()
+ }
+ if value := res.Get("transportPathMtuDiscovery"); value.Exists() && !data.TcpPathMtuDiscovery.IsNull() {
+ data.TcpPathMtuDiscovery = types.BoolValue(value.Bool())
+ } else {
+ data.TcpPathMtuDiscovery = types.BoolNull()
+ }
+ if value := res.Get("fastExternalFallOver"); value.Exists() && !data.ResetSessionUponFailover.IsNull() {
+ data.ResetSessionUponFailover = types.BoolValue(value.Bool())
+ } else {
+ data.ResetSessionUponFailover = types.BoolNull()
+ }
+ if value := res.Get("enforceFirstAs"); value.Exists() && !data.EnforceFirstPeerAs.IsNull() {
+ data.EnforceFirstPeerAs = types.BoolValue(value.Bool())
+ } else {
+ data.EnforceFirstPeerAs = types.BoolNull()
+ }
+ if value := res.Get("asnotationDot"); value.Exists() && !data.UseDotNotation.IsNull() {
+ data.UseDotNotation = types.BoolValue(value.Bool())
+ } else {
+ data.UseDotNotation = types.BoolNull()
+ }
+ if value := res.Get("aggregateTimer"); value.Exists() && !data.AggregateTimer.IsNull() {
+ data.AggregateTimer = types.Int64Value(value.Int())
+ } else {
+ data.AggregateTimer = types.Int64Null()
+ }
+ if value := res.Get("bestPath.defaultLocalPreferenceValue"); value.Exists() && !data.DefaultLocalPreference.IsNull() {
+ data.DefaultLocalPreference = types.Int64Value(value.Int())
+ } else {
+ data.DefaultLocalPreference = types.Int64Null()
+ }
+ if value := res.Get("bestPath.alwaysCompareMed"); value.Exists() && !data.CompareMedFromDifferentNeighbors.IsNull() {
+ data.CompareMedFromDifferentNeighbors = types.BoolValue(value.Bool())
+ } else {
+ data.CompareMedFromDifferentNeighbors = types.BoolNull()
+ }
+ if value := res.Get("bestPath.deterministicMed"); value.Exists() && !data.CompareRouterIdInPath.IsNull() {
+ data.CompareRouterIdInPath = types.BoolValue(value.Bool())
+ } else {
+ data.CompareRouterIdInPath = types.BoolNull()
+ }
+ if value := res.Get("bestPath.bestPathCompareRouterId"); value.Exists() && !data.PickBestMed.IsNull() {
+ data.PickBestMed = types.BoolValue(value.Bool())
+ } else {
+ data.PickBestMed = types.BoolNull()
+ }
+ if value := res.Get("bestPath.bestPathMedMissingAsWorst"); value.Exists() && !data.MissingMedAsBest.IsNull() {
+ data.MissingMedAsBest = types.BoolValue(value.Bool())
+ } else {
+ data.MissingMedAsBest = types.BoolNull()
+ }
+ if value := res.Get("bgptimers.keepAlive"); value.Exists() && !data.KeepaliveInterval.IsNull() {
+ data.KeepaliveInterval = types.Int64Value(value.Int())
+ } else {
+ data.KeepaliveInterval = types.Int64Null()
+ }
+ if value := res.Get("bgptimers.holdTime"); value.Exists() && !data.HoldTime.IsNull() {
+ data.HoldTime = types.Int64Value(value.Int())
+ } else {
+ data.HoldTime = types.Int64Null()
+ }
+ if value := res.Get("bgptimers.minHoldTime"); value.Exists() && !data.MinHoldTime.IsNull() {
+ data.MinHoldTime = types.Int64Value(value.Int())
+ } else {
+ data.MinHoldTime = types.Int64Null()
+ }
+ if value := res.Get("bgpNextHopTriggerEnable"); value.Exists() && !data.NextHopAddressTracking.IsNull() {
+ data.NextHopAddressTracking = types.BoolValue(value.Bool())
+ } else {
+ data.NextHopAddressTracking = types.BoolNull()
+ }
+ if value := res.Get("bgpNextHopTriggerDelay"); value.Exists() && !data.NextHopDelayInterval.IsNull() {
+ data.NextHopDelayInterval = types.Int64Value(value.Int())
+ } else {
+ data.NextHopDelayInterval = types.Int64Null()
+ }
+ if value := res.Get("bgpGracefulRestart.gracefulRestart"); value.Exists() && !data.GracefulRestart.IsNull() {
+ data.GracefulRestart = types.BoolValue(value.Bool())
+ } else {
+ data.GracefulRestart = types.BoolNull()
+ }
+ if value := res.Get("bgpGracefulRestart.gracefulRestartRestartTime"); value.Exists() && !data.GracefulRestartRestartTime.IsNull() {
+ data.GracefulRestartRestartTime = types.Int64Value(value.Int())
+ } else {
+ data.GracefulRestartRestartTime = types.Int64Null()
+ }
+ if value := res.Get("bgpGracefulRestart.gracefulRestartStalePathTime"); value.Exists() && !data.GracefulRestartStalePathTime.IsNull() {
+ data.GracefulRestartStalePathTime = types.Int64Value(value.Int())
+ } else {
+ data.GracefulRestartStalePathTime = types.Int64Null()
+ }
+}
+
+// End of section. //template:end fromBodyPartial
+
+// Section below is generated&owned by "gen/generator.go". //template:begin fromBodyUnknowns
+
+// fromBodyUnknowns updates the Unknown Computed tfstate values from a JSON.
+// Known values are not changed (usual for Computed attributes with UseStateForUnknown or with Default).
+func (data *DeviceBGPGeneralSettings) fromBodyUnknowns(ctx context.Context, res gjson.Result) {
+ if data.Name.IsUnknown() {
+ if value := res.Get("name"); value.Exists() {
+ data.Name = types.StringValue(value.String())
+ } else {
+ data.Name = types.StringNull()
+ }
+ }
+}
+
+// End of section. //template:end fromBodyUnknowns
+
+// Section below is generated&owned by "gen/generator.go". //template:begin Clone
+
+// End of section. //template:end Clone
+
+// Section below is generated&owned by "gen/generator.go". //template:begin toBodyNonBulk
+
+// End of section. //template:end toBodyNonBulk
diff --git a/internal/provider/model_fmc_device_bgp_generel_settings.go b/internal/provider/model_fmc_device_bgp_generel_settings.go
new file mode 100644
index 00000000..9b0b28a1
--- /dev/null
+++ b/internal/provider/model_fmc_device_bgp_generel_settings.go
@@ -0,0 +1,454 @@
+// Copyright © 2023 Cisco Systems, Inc. and its affiliates.
+// All rights reserved.
+//
+// Licensed under the Mozilla Public License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://mozilla.org/MPL/2.0/
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// SPDX-License-Identifier: MPL-2.0
+
+package provider
+
+// Section below is generated&owned by "gen/generator.go". //template:begin imports
+import (
+ "context"
+ "fmt"
+ "net/url"
+
+ "github.com/hashicorp/terraform-plugin-framework/types"
+ "github.com/tidwall/gjson"
+ "github.com/tidwall/sjson"
+)
+
+// End of section. //template:end imports
+
+// Section below is generated&owned by "gen/generator.go". //template:begin types
+
+type DeviceBGPGenerelSettings struct {
+ Id types.String `tfsdk:"id"`
+ Domain types.String `tfsdk:"domain"`
+ DeviceId types.String `tfsdk:"device_id"`
+ Name types.String `tfsdk:"name"`
+ Type types.String `tfsdk:"type"`
+ AsNumber types.String `tfsdk:"as_number"`
+ RouterId types.String `tfsdk:"router_id"`
+ ScanningInterval types.Int64 `tfsdk:"scanning_interval"`
+ AsNoInPathAttribute types.Int64 `tfsdk:"as_no_in_path_attribute"`
+ LogNeighborChanges types.Bool `tfsdk:"log_neighbor_changes"`
+ TcpPathMtuDiscovery types.Bool `tfsdk:"tcp_path_mtu_discovery"`
+ ResetSessionUponFailover types.Bool `tfsdk:"reset_session_upon_failover"`
+ EnforceFirstPeerAs types.Bool `tfsdk:"enforce_first_peer_as"`
+ UseDotNotation types.Bool `tfsdk:"use_dot_notation"`
+ AggregateTimer types.Int64 `tfsdk:"aggregate_timer"`
+ DefaultLocalPreference types.Int64 `tfsdk:"default_local_preference"`
+ CompareMedFromDifferentNeighbors types.Bool `tfsdk:"compare_med_from_different_neighbors"`
+ CompareRouterIdInPath types.Bool `tfsdk:"compare_router_id_in_path"`
+ PickBestMed types.Bool `tfsdk:"pick_best_med"`
+ MissingMedAsBest types.Bool `tfsdk:"missing_med_as_best"`
+ KeepaliveInterval types.Int64 `tfsdk:"keepalive_interval"`
+ HoldTime types.Int64 `tfsdk:"hold_time"`
+ MinHoldTime types.Int64 `tfsdk:"min_hold_time"`
+ NextHopAddressTracking types.Bool `tfsdk:"next_hop_address_tracking"`
+ NextHopDelayInterval types.Int64 `tfsdk:"next_hop_delay_interval"`
+ GracefulRestart types.Bool `tfsdk:"graceful_restart"`
+ GracefulRestartRestartTime types.Int64 `tfsdk:"graceful_restart_restart_time"`
+ GracefulRestartStalePathTime types.Int64 `tfsdk:"graceful_restart_stale_path_time"`
+}
+
+// End of section. //template:end types
+
+// Section below is generated&owned by "gen/generator.go". //template:begin getPath
+
+func (data DeviceBGPGenerelSettings) getPath() string {
+ return fmt.Sprintf("/api/fmc_config/v1/domain/{DOMAIN_UUID}/devices/devicerecords/%v/routing/bgpgeneralsettings", url.QueryEscape(data.DeviceId.ValueString()))
+}
+
+// End of section. //template:end getPath
+
+// Section below is generated&owned by "gen/generator.go". //template:begin toBody
+
+func (data DeviceBGPGenerelSettings) toBody(ctx context.Context, state DeviceBGPGenerelSettings) string {
+ body := ""
+ if data.Id.ValueString() != "" {
+ body, _ = sjson.Set(body, "id", data.Id.ValueString())
+ }
+ if !data.AsNumber.IsNull() {
+ body, _ = sjson.Set(body, "asNumber", data.AsNumber.ValueString())
+ }
+ if !data.RouterId.IsNull() {
+ body, _ = sjson.Set(body, "routerId", data.RouterId.ValueString())
+ }
+ if !data.ScanningInterval.IsNull() {
+ body, _ = sjson.Set(body, "scanTime", data.ScanningInterval.ValueInt64())
+ }
+ if !data.AsNoInPathAttribute.IsNull() {
+ body, _ = sjson.Set(body, "maxasLimit", data.AsNoInPathAttribute.ValueInt64())
+ }
+ if !data.LogNeighborChanges.IsNull() {
+ body, _ = sjson.Set(body, "logNeighborChanges", data.LogNeighborChanges.ValueBool())
+ }
+ if !data.TcpPathMtuDiscovery.IsNull() {
+ body, _ = sjson.Set(body, "transportPathMtuDiscovery", data.TcpPathMtuDiscovery.ValueBool())
+ }
+ if !data.ResetSessionUponFailover.IsNull() {
+ body, _ = sjson.Set(body, "fastExternalFallOver", data.ResetSessionUponFailover.ValueBool())
+ }
+ if !data.EnforceFirstPeerAs.IsNull() {
+ body, _ = sjson.Set(body, "enforceFirstAs", data.EnforceFirstPeerAs.ValueBool())
+ }
+ if !data.UseDotNotation.IsNull() {
+ body, _ = sjson.Set(body, "asnotationDot", data.UseDotNotation.ValueBool())
+ }
+ if !data.AggregateTimer.IsNull() {
+ body, _ = sjson.Set(body, "aggregateTimer", data.AggregateTimer.ValueInt64())
+ }
+ if !data.DefaultLocalPreference.IsNull() {
+ body, _ = sjson.Set(body, "bestPath.defaultLocalPreferenceValue", data.DefaultLocalPreference.ValueInt64())
+ }
+ if !data.CompareMedFromDifferentNeighbors.IsNull() {
+ body, _ = sjson.Set(body, "bestPath.alwaysCompareMed", data.CompareMedFromDifferentNeighbors.ValueBool())
+ }
+ if !data.CompareRouterIdInPath.IsNull() {
+ body, _ = sjson.Set(body, "bestPath.deterministicMed", data.CompareRouterIdInPath.ValueBool())
+ }
+ if !data.PickBestMed.IsNull() {
+ body, _ = sjson.Set(body, "bestPath.bestPathCompareRouterId", data.PickBestMed.ValueBool())
+ }
+ if !data.MissingMedAsBest.IsNull() {
+ body, _ = sjson.Set(body, "bestPath.bestPathMedMissingAsWorst", data.MissingMedAsBest.ValueBool())
+ }
+ if !data.KeepaliveInterval.IsNull() {
+ body, _ = sjson.Set(body, "bgptimers.keepAlive", data.KeepaliveInterval.ValueInt64())
+ }
+ if !data.HoldTime.IsNull() {
+ body, _ = sjson.Set(body, "bgptimers.holdTime", data.HoldTime.ValueInt64())
+ }
+ if !data.MinHoldTime.IsNull() {
+ body, _ = sjson.Set(body, "bgptimers.minHoldTime", data.MinHoldTime.ValueInt64())
+ }
+ if !data.NextHopAddressTracking.IsNull() {
+ body, _ = sjson.Set(body, "bgpNextHopTriggerEnable", data.NextHopAddressTracking.ValueBool())
+ }
+ if !data.NextHopDelayInterval.IsNull() {
+ body, _ = sjson.Set(body, "bgpNextHopTriggerDelay", data.NextHopDelayInterval.ValueInt64())
+ }
+ if !data.GracefulRestart.IsNull() {
+ body, _ = sjson.Set(body, "bgpGracefulRestart.gracefulRestart", data.GracefulRestart.ValueBool())
+ }
+ if !data.GracefulRestartRestartTime.IsNull() {
+ body, _ = sjson.Set(body, "bgpGracefulRestart.gracefulRestartRestartTime", data.GracefulRestartRestartTime.ValueInt64())
+ }
+ if !data.GracefulRestartStalePathTime.IsNull() {
+ body, _ = sjson.Set(body, "bgpGracefulRestart.gracefulRestartStalePathTime", data.GracefulRestartStalePathTime.ValueInt64())
+ }
+ return body
+}
+
+// End of section. //template:end toBody
+
+// Section below is generated&owned by "gen/generator.go". //template:begin fromBody
+
+func (data *DeviceBGPGenerelSettings) fromBody(ctx context.Context, res gjson.Result) {
+ if value := res.Get("name"); value.Exists() {
+ data.Name = types.StringValue(value.String())
+ } else {
+ data.Name = types.StringNull()
+ }
+ if value := res.Get("type"); value.Exists() {
+ data.Type = types.StringValue(value.String())
+ } else {
+ data.Type = types.StringNull()
+ }
+ if value := res.Get("asNumber"); value.Exists() {
+ data.AsNumber = types.StringValue(value.String())
+ } else {
+ data.AsNumber = types.StringNull()
+ }
+ if value := res.Get("routerId"); value.Exists() {
+ data.RouterId = types.StringValue(value.String())
+ } else {
+ data.RouterId = types.StringNull()
+ }
+ if value := res.Get("scanTime"); value.Exists() {
+ data.ScanningInterval = types.Int64Value(value.Int())
+ } else {
+ data.ScanningInterval = types.Int64Null()
+ }
+ if value := res.Get("maxasLimit"); value.Exists() {
+ data.AsNoInPathAttribute = types.Int64Value(value.Int())
+ } else {
+ data.AsNoInPathAttribute = types.Int64Null()
+ }
+ if value := res.Get("logNeighborChanges"); value.Exists() {
+ data.LogNeighborChanges = types.BoolValue(value.Bool())
+ } else {
+ data.LogNeighborChanges = types.BoolNull()
+ }
+ if value := res.Get("transportPathMtuDiscovery"); value.Exists() {
+ data.TcpPathMtuDiscovery = types.BoolValue(value.Bool())
+ } else {
+ data.TcpPathMtuDiscovery = types.BoolNull()
+ }
+ if value := res.Get("fastExternalFallOver"); value.Exists() {
+ data.ResetSessionUponFailover = types.BoolValue(value.Bool())
+ } else {
+ data.ResetSessionUponFailover = types.BoolNull()
+ }
+ if value := res.Get("enforceFirstAs"); value.Exists() {
+ data.EnforceFirstPeerAs = types.BoolValue(value.Bool())
+ } else {
+ data.EnforceFirstPeerAs = types.BoolNull()
+ }
+ if value := res.Get("asnotationDot"); value.Exists() {
+ data.UseDotNotation = types.BoolValue(value.Bool())
+ } else {
+ data.UseDotNotation = types.BoolNull()
+ }
+ if value := res.Get("aggregateTimer"); value.Exists() {
+ data.AggregateTimer = types.Int64Value(value.Int())
+ } else {
+ data.AggregateTimer = types.Int64Null()
+ }
+ if value := res.Get("bestPath.defaultLocalPreferenceValue"); value.Exists() {
+ data.DefaultLocalPreference = types.Int64Value(value.Int())
+ } else {
+ data.DefaultLocalPreference = types.Int64Null()
+ }
+ if value := res.Get("bestPath.alwaysCompareMed"); value.Exists() {
+ data.CompareMedFromDifferentNeighbors = types.BoolValue(value.Bool())
+ } else {
+ data.CompareMedFromDifferentNeighbors = types.BoolNull()
+ }
+ if value := res.Get("bestPath.deterministicMed"); value.Exists() {
+ data.CompareRouterIdInPath = types.BoolValue(value.Bool())
+ } else {
+ data.CompareRouterIdInPath = types.BoolNull()
+ }
+ if value := res.Get("bestPath.bestPathCompareRouterId"); value.Exists() {
+ data.PickBestMed = types.BoolValue(value.Bool())
+ } else {
+ data.PickBestMed = types.BoolNull()
+ }
+ if value := res.Get("bestPath.bestPathMedMissingAsWorst"); value.Exists() {
+ data.MissingMedAsBest = types.BoolValue(value.Bool())
+ } else {
+ data.MissingMedAsBest = types.BoolNull()
+ }
+ if value := res.Get("bgptimers.keepAlive"); value.Exists() {
+ data.KeepaliveInterval = types.Int64Value(value.Int())
+ } else {
+ data.KeepaliveInterval = types.Int64Null()
+ }
+ if value := res.Get("bgptimers.holdTime"); value.Exists() {
+ data.HoldTime = types.Int64Value(value.Int())
+ } else {
+ data.HoldTime = types.Int64Null()
+ }
+ if value := res.Get("bgptimers.minHoldTime"); value.Exists() {
+ data.MinHoldTime = types.Int64Value(value.Int())
+ } else {
+ data.MinHoldTime = types.Int64Null()
+ }
+ if value := res.Get("bgpNextHopTriggerEnable"); value.Exists() {
+ data.NextHopAddressTracking = types.BoolValue(value.Bool())
+ } else {
+ data.NextHopAddressTracking = types.BoolNull()
+ }
+ if value := res.Get("bgpNextHopTriggerDelay"); value.Exists() {
+ data.NextHopDelayInterval = types.Int64Value(value.Int())
+ } else {
+ data.NextHopDelayInterval = types.Int64Null()
+ }
+ if value := res.Get("bgpGracefulRestart.gracefulRestart"); value.Exists() {
+ data.GracefulRestart = types.BoolValue(value.Bool())
+ } else {
+ data.GracefulRestart = types.BoolNull()
+ }
+ if value := res.Get("bgpGracefulRestart.gracefulRestartRestartTime"); value.Exists() {
+ data.GracefulRestartRestartTime = types.Int64Value(value.Int())
+ } else {
+ data.GracefulRestartRestartTime = types.Int64Null()
+ }
+ if value := res.Get("bgpGracefulRestart.gracefulRestartStalePathTime"); value.Exists() {
+ data.GracefulRestartStalePathTime = types.Int64Value(value.Int())
+ } else {
+ data.GracefulRestartStalePathTime = types.Int64Null()
+ }
+}
+
+// End of section. //template:end fromBody
+
+// Section below is generated&owned by "gen/generator.go". //template:begin fromBodyPartial
+
+// fromBodyPartial reads values from a gjson.Result into a tfstate model. It ignores null attributes in order to
+// uncouple the provider from the exact values that the backend API might summon to replace nulls. (Such behavior might
+// easily change across versions of the backend API.) For List/Set/Map attributes, the func only updates the
+// "managed" elements, instead of all elements.
+func (data *DeviceBGPGenerelSettings) fromBodyPartial(ctx context.Context, res gjson.Result) {
+ if value := res.Get("name"); value.Exists() && !data.Name.IsNull() {
+ data.Name = types.StringValue(value.String())
+ } else {
+ data.Name = types.StringNull()
+ }
+ if value := res.Get("type"); value.Exists() && !data.Type.IsNull() {
+ data.Type = types.StringValue(value.String())
+ } else {
+ data.Type = types.StringNull()
+ }
+ if value := res.Get("asNumber"); value.Exists() && !data.AsNumber.IsNull() {
+ data.AsNumber = types.StringValue(value.String())
+ } else {
+ data.AsNumber = types.StringNull()
+ }
+ if value := res.Get("routerId"); value.Exists() && !data.RouterId.IsNull() {
+ data.RouterId = types.StringValue(value.String())
+ } else {
+ data.RouterId = types.StringNull()
+ }
+ if value := res.Get("scanTime"); value.Exists() && !data.ScanningInterval.IsNull() {
+ data.ScanningInterval = types.Int64Value(value.Int())
+ } else {
+ data.ScanningInterval = types.Int64Null()
+ }
+ if value := res.Get("maxasLimit"); value.Exists() && !data.AsNoInPathAttribute.IsNull() {
+ data.AsNoInPathAttribute = types.Int64Value(value.Int())
+ } else {
+ data.AsNoInPathAttribute = types.Int64Null()
+ }
+ if value := res.Get("logNeighborChanges"); value.Exists() && !data.LogNeighborChanges.IsNull() {
+ data.LogNeighborChanges = types.BoolValue(value.Bool())
+ } else {
+ data.LogNeighborChanges = types.BoolNull()
+ }
+ if value := res.Get("transportPathMtuDiscovery"); value.Exists() && !data.TcpPathMtuDiscovery.IsNull() {
+ data.TcpPathMtuDiscovery = types.BoolValue(value.Bool())
+ } else {
+ data.TcpPathMtuDiscovery = types.BoolNull()
+ }
+ if value := res.Get("fastExternalFallOver"); value.Exists() && !data.ResetSessionUponFailover.IsNull() {
+ data.ResetSessionUponFailover = types.BoolValue(value.Bool())
+ } else {
+ data.ResetSessionUponFailover = types.BoolNull()
+ }
+ if value := res.Get("enforceFirstAs"); value.Exists() && !data.EnforceFirstPeerAs.IsNull() {
+ data.EnforceFirstPeerAs = types.BoolValue(value.Bool())
+ } else {
+ data.EnforceFirstPeerAs = types.BoolNull()
+ }
+ if value := res.Get("asnotationDot"); value.Exists() && !data.UseDotNotation.IsNull() {
+ data.UseDotNotation = types.BoolValue(value.Bool())
+ } else {
+ data.UseDotNotation = types.BoolNull()
+ }
+ if value := res.Get("aggregateTimer"); value.Exists() && !data.AggregateTimer.IsNull() {
+ data.AggregateTimer = types.Int64Value(value.Int())
+ } else {
+ data.AggregateTimer = types.Int64Null()
+ }
+ if value := res.Get("bestPath.defaultLocalPreferenceValue"); value.Exists() && !data.DefaultLocalPreference.IsNull() {
+ data.DefaultLocalPreference = types.Int64Value(value.Int())
+ } else {
+ data.DefaultLocalPreference = types.Int64Null()
+ }
+ if value := res.Get("bestPath.alwaysCompareMed"); value.Exists() && !data.CompareMedFromDifferentNeighbors.IsNull() {
+ data.CompareMedFromDifferentNeighbors = types.BoolValue(value.Bool())
+ } else {
+ data.CompareMedFromDifferentNeighbors = types.BoolNull()
+ }
+ if value := res.Get("bestPath.deterministicMed"); value.Exists() && !data.CompareRouterIdInPath.IsNull() {
+ data.CompareRouterIdInPath = types.BoolValue(value.Bool())
+ } else {
+ data.CompareRouterIdInPath = types.BoolNull()
+ }
+ if value := res.Get("bestPath.bestPathCompareRouterId"); value.Exists() && !data.PickBestMed.IsNull() {
+ data.PickBestMed = types.BoolValue(value.Bool())
+ } else {
+ data.PickBestMed = types.BoolNull()
+ }
+ if value := res.Get("bestPath.bestPathMedMissingAsWorst"); value.Exists() && !data.MissingMedAsBest.IsNull() {
+ data.MissingMedAsBest = types.BoolValue(value.Bool())
+ } else {
+ data.MissingMedAsBest = types.BoolNull()
+ }
+ if value := res.Get("bgptimers.keepAlive"); value.Exists() && !data.KeepaliveInterval.IsNull() {
+ data.KeepaliveInterval = types.Int64Value(value.Int())
+ } else {
+ data.KeepaliveInterval = types.Int64Null()
+ }
+ if value := res.Get("bgptimers.holdTime"); value.Exists() && !data.HoldTime.IsNull() {
+ data.HoldTime = types.Int64Value(value.Int())
+ } else {
+ data.HoldTime = types.Int64Null()
+ }
+ if value := res.Get("bgptimers.minHoldTime"); value.Exists() && !data.MinHoldTime.IsNull() {
+ data.MinHoldTime = types.Int64Value(value.Int())
+ } else {
+ data.MinHoldTime = types.Int64Null()
+ }
+ if value := res.Get("bgpNextHopTriggerEnable"); value.Exists() && !data.NextHopAddressTracking.IsNull() {
+ data.NextHopAddressTracking = types.BoolValue(value.Bool())
+ } else {
+ data.NextHopAddressTracking = types.BoolNull()
+ }
+ if value := res.Get("bgpNextHopTriggerDelay"); value.Exists() && !data.NextHopDelayInterval.IsNull() {
+ data.NextHopDelayInterval = types.Int64Value(value.Int())
+ } else {
+ data.NextHopDelayInterval = types.Int64Null()
+ }
+ if value := res.Get("bgpGracefulRestart.gracefulRestart"); value.Exists() && !data.GracefulRestart.IsNull() {
+ data.GracefulRestart = types.BoolValue(value.Bool())
+ } else {
+ data.GracefulRestart = types.BoolNull()
+ }
+ if value := res.Get("bgpGracefulRestart.gracefulRestartRestartTime"); value.Exists() && !data.GracefulRestartRestartTime.IsNull() {
+ data.GracefulRestartRestartTime = types.Int64Value(value.Int())
+ } else {
+ data.GracefulRestartRestartTime = types.Int64Null()
+ }
+ if value := res.Get("bgpGracefulRestart.gracefulRestartStalePathTime"); value.Exists() && !data.GracefulRestartStalePathTime.IsNull() {
+ data.GracefulRestartStalePathTime = types.Int64Value(value.Int())
+ } else {
+ data.GracefulRestartStalePathTime = types.Int64Null()
+ }
+}
+
+// End of section. //template:end fromBodyPartial
+
+// Section below is generated&owned by "gen/generator.go". //template:begin fromBodyUnknowns
+
+// fromBodyUnknowns updates the Unknown Computed tfstate values from a JSON.
+// Known values are not changed (usual for Computed attributes with UseStateForUnknown or with Default).
+func (data *DeviceBGPGenerelSettings) fromBodyUnknowns(ctx context.Context, res gjson.Result) {
+ if data.Name.IsUnknown() {
+ if value := res.Get("name"); value.Exists() {
+ data.Name = types.StringValue(value.String())
+ } else {
+ data.Name = types.StringNull()
+ }
+ }
+ if data.Type.IsUnknown() {
+ if value := res.Get("type"); value.Exists() {
+ data.Type = types.StringValue(value.String())
+ } else {
+ data.Type = types.StringNull()
+ }
+ }
+}
+
+// End of section. //template:end fromBodyUnknowns
+
+// Section below is generated&owned by "gen/generator.go". //template:begin Clone
+
+// End of section. //template:end Clone
+
+// Section below is generated&owned by "gen/generator.go". //template:begin toBodyNonBulk
+
+// End of section. //template:end toBodyNonBulk
diff --git a/internal/provider/model_fmc_device_ha_pair_monitoring.go b/internal/provider/model_fmc_device_ha_pair_monitoring.go
new file mode 100644
index 00000000..3d219200
--- /dev/null
+++ b/internal/provider/model_fmc_device_ha_pair_monitoring.go
@@ -0,0 +1,308 @@
+// Copyright © 2023 Cisco Systems, Inc. and its affiliates.
+// All rights reserved.
+//
+// Licensed under the Mozilla Public License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://mozilla.org/MPL/2.0/
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// SPDX-License-Identifier: MPL-2.0
+
+package provider
+
+// Section below is generated&owned by "gen/generator.go". //template:begin imports
+import (
+ "context"
+ "fmt"
+ "net/url"
+ "slices"
+
+ "github.com/hashicorp/terraform-plugin-framework/types"
+ "github.com/hashicorp/terraform-plugin-log/tflog"
+ "github.com/tidwall/gjson"
+ "github.com/tidwall/sjson"
+)
+
+// End of section. //template:end imports
+
+// Section below is generated&owned by "gen/generator.go". //template:begin types
+
+type DeviceHAPairMonitoring struct {
+ Id types.String `tfsdk:"id"`
+ Domain types.String `tfsdk:"domain"`
+ DeviceId types.String `tfsdk:"device_id"`
+ Type types.String `tfsdk:"type"`
+ LogicalName types.String `tfsdk:"logical_name"`
+ MonitorInterface types.Bool `tfsdk:"monitor_interface"`
+ Ipv4ActiveAddress types.String `tfsdk:"ipv4_active_address"`
+ Ipv4StandbyAddress types.String `tfsdk:"ipv4_standby_address"`
+ Ipv4Netmask types.String `tfsdk:"ipv4_netmask"`
+ Ipv6Addresses []DeviceHAPairMonitoringIpv6Addresses `tfsdk:"ipv6_addresses"`
+}
+
+type DeviceHAPairMonitoringIpv6Addresses struct {
+ ActiveAddress types.String `tfsdk:"active_address"`
+ StandbyAddress types.String `tfsdk:"standby_address"`
+}
+
+// End of section. //template:end types
+
+// Section below is generated&owned by "gen/generator.go". //template:begin getPath
+
+func (data DeviceHAPairMonitoring) getPath() string {
+ return fmt.Sprintf("/api/fmc_config/v1/domain/{DOMAIN_UUID}/devicehapairs/ftddevicehapairs/%v/monitoredinterfaces", url.QueryEscape(data.DeviceId.ValueString()))
+}
+
+// End of section. //template:end getPath
+
+// Section below is generated&owned by "gen/generator.go". //template:begin toBody
+
+func (data DeviceHAPairMonitoring) toBody(ctx context.Context, state DeviceHAPairMonitoring) string {
+ body := ""
+ if data.Id.ValueString() != "" {
+ body, _ = sjson.Set(body, "id", data.Id.ValueString())
+ }
+ if !data.LogicalName.IsNull() {
+ body, _ = sjson.Set(body, "name", data.LogicalName.ValueString())
+ }
+ if !data.MonitorInterface.IsNull() {
+ body, _ = sjson.Set(body, "monitorForFailures", data.MonitorInterface.ValueBool())
+ }
+ if !data.Ipv4StandbyAddress.IsNull() {
+ body, _ = sjson.Set(body, "ipv4Configuration.standbyIPv4Address", data.Ipv4StandbyAddress.ValueString())
+ }
+ if len(data.Ipv6Addresses) > 0 {
+ body, _ = sjson.Set(body, "ipv6Configuration.ipv6ActiveStandbyPair", []interface{}{})
+ for _, item := range data.Ipv6Addresses {
+ itemBody := ""
+ if !item.ActiveAddress.IsNull() {
+ itemBody, _ = sjson.Set(itemBody, "activeIPv6", item.ActiveAddress.ValueString())
+ }
+ if !item.StandbyAddress.IsNull() {
+ itemBody, _ = sjson.Set(itemBody, "standbyIPv6", item.StandbyAddress.ValueString())
+ }
+ body, _ = sjson.SetRaw(body, "ipv6Configuration.ipv6ActiveStandbyPair.-1", itemBody)
+ }
+ }
+ return body
+}
+
+// End of section. //template:end toBody
+
+// Section below is generated&owned by "gen/generator.go". //template:begin fromBody
+
+func (data *DeviceHAPairMonitoring) fromBody(ctx context.Context, res gjson.Result) {
+ if value := res.Get("type"); value.Exists() {
+ data.Type = types.StringValue(value.String())
+ } else {
+ data.Type = types.StringNull()
+ }
+ if value := res.Get("name"); value.Exists() {
+ data.LogicalName = types.StringValue(value.String())
+ } else {
+ data.LogicalName = types.StringNull()
+ }
+ if value := res.Get("monitorForFailures"); value.Exists() {
+ data.MonitorInterface = types.BoolValue(value.Bool())
+ } else {
+ data.MonitorInterface = types.BoolNull()
+ }
+ if value := res.Get("ipv4Configuration.activeIPv4Address"); value.Exists() {
+ data.Ipv4ActiveAddress = types.StringValue(value.String())
+ } else {
+ data.Ipv4ActiveAddress = types.StringNull()
+ }
+ if value := res.Get("ipv4Configuration.standbyIPv4Address"); value.Exists() {
+ data.Ipv4StandbyAddress = types.StringValue(value.String())
+ } else {
+ data.Ipv4StandbyAddress = types.StringNull()
+ }
+ if value := res.Get("ipv4Configuration.activeIPv4Mask"); value.Exists() {
+ data.Ipv4Netmask = types.StringValue(value.String())
+ } else {
+ data.Ipv4Netmask = types.StringNull()
+ }
+ if value := res.Get("ipv6Configuration.ipv6ActiveStandbyPair"); value.Exists() {
+ data.Ipv6Addresses = make([]DeviceHAPairMonitoringIpv6Addresses, 0)
+ value.ForEach(func(k, res gjson.Result) bool {
+ parent := &data
+ data := DeviceHAPairMonitoringIpv6Addresses{}
+ if value := res.Get("activeIPv6"); value.Exists() {
+ data.ActiveAddress = types.StringValue(value.String())
+ } else {
+ data.ActiveAddress = types.StringNull()
+ }
+ if value := res.Get("standbyIPv6"); value.Exists() {
+ data.StandbyAddress = types.StringValue(value.String())
+ } else {
+ data.StandbyAddress = types.StringNull()
+ }
+ (*parent).Ipv6Addresses = append((*parent).Ipv6Addresses, data)
+ return true
+ })
+ }
+}
+
+// End of section. //template:end fromBody
+
+// Section below is generated&owned by "gen/generator.go". //template:begin fromBodyPartial
+
+// fromBodyPartial reads values from a gjson.Result into a tfstate model. It ignores null attributes in order to
+// uncouple the provider from the exact values that the backend API might summon to replace nulls. (Such behavior might
+// easily change across versions of the backend API.) For List/Set/Map attributes, the func only updates the
+// "managed" elements, instead of all elements.
+func (data *DeviceHAPairMonitoring) fromBodyPartial(ctx context.Context, res gjson.Result) {
+ if value := res.Get("type"); value.Exists() && !data.Type.IsNull() {
+ data.Type = types.StringValue(value.String())
+ } else {
+ data.Type = types.StringNull()
+ }
+ if value := res.Get("name"); value.Exists() && !data.LogicalName.IsNull() {
+ data.LogicalName = types.StringValue(value.String())
+ } else {
+ data.LogicalName = types.StringNull()
+ }
+ if value := res.Get("monitorForFailures"); value.Exists() && !data.MonitorInterface.IsNull() {
+ data.MonitorInterface = types.BoolValue(value.Bool())
+ } else {
+ data.MonitorInterface = types.BoolNull()
+ }
+ if value := res.Get("ipv4Configuration.activeIPv4Address"); value.Exists() && !data.Ipv4ActiveAddress.IsNull() {
+ data.Ipv4ActiveAddress = types.StringValue(value.String())
+ } else {
+ data.Ipv4ActiveAddress = types.StringNull()
+ }
+ if value := res.Get("ipv4Configuration.standbyIPv4Address"); value.Exists() && !data.Ipv4StandbyAddress.IsNull() {
+ data.Ipv4StandbyAddress = types.StringValue(value.String())
+ } else {
+ data.Ipv4StandbyAddress = types.StringNull()
+ }
+ if value := res.Get("ipv4Configuration.activeIPv4Mask"); value.Exists() && !data.Ipv4Netmask.IsNull() {
+ data.Ipv4Netmask = types.StringValue(value.String())
+ } else {
+ data.Ipv4Netmask = types.StringNull()
+ }
+ for i := 0; i < len(data.Ipv6Addresses); i++ {
+ keys := [...]string{"activeIPv6", "standbyIPv6"}
+ keyValues := [...]string{data.Ipv6Addresses[i].ActiveAddress.ValueString(), data.Ipv6Addresses[i].StandbyAddress.ValueString()}
+
+ parent := &data
+ data := (*parent).Ipv6Addresses[i]
+ parentRes := &res
+ var res gjson.Result
+
+ parentRes.Get("ipv6Configuration.ipv6ActiveStandbyPair").ForEach(
+ func(_, v gjson.Result) bool {
+ found := false
+ for ik := range keys {
+ if v.Get(keys[ik]).String() != keyValues[ik] {
+ found = false
+ break
+ }
+ found = true
+ }
+ if found {
+ res = v
+ return false
+ }
+ return true
+ },
+ )
+ if !res.Exists() {
+ tflog.Debug(ctx, fmt.Sprintf("removing Ipv6Addresses[%d] = %+v",
+ i,
+ (*parent).Ipv6Addresses[i],
+ ))
+ (*parent).Ipv6Addresses = slices.Delete((*parent).Ipv6Addresses, i, i+1)
+ i--
+
+ continue
+ }
+ if value := res.Get("activeIPv6"); value.Exists() && !data.ActiveAddress.IsNull() {
+ data.ActiveAddress = types.StringValue(value.String())
+ } else {
+ data.ActiveAddress = types.StringNull()
+ }
+ if value := res.Get("standbyIPv6"); value.Exists() && !data.StandbyAddress.IsNull() {
+ data.StandbyAddress = types.StringValue(value.String())
+ } else {
+ data.StandbyAddress = types.StringNull()
+ }
+ (*parent).Ipv6Addresses[i] = data
+ }
+}
+
+// End of section. //template:end fromBodyPartial
+
+// Section below is generated&owned by "gen/generator.go". //template:begin fromBodyUnknowns
+
+// fromBodyUnknowns updates the Unknown Computed tfstate values from a JSON.
+// Known values are not changed (usual for Computed attributes with UseStateForUnknown or with Default).
+func (data *DeviceHAPairMonitoring) fromBodyUnknowns(ctx context.Context, res gjson.Result) {
+ if data.Type.IsUnknown() {
+ if value := res.Get("type"); value.Exists() {
+ data.Type = types.StringValue(value.String())
+ } else {
+ data.Type = types.StringNull()
+ }
+ }
+ if data.Ipv4ActiveAddress.IsUnknown() {
+ if value := res.Get("ipv4Configuration.activeIPv4Address"); value.Exists() {
+ data.Ipv4ActiveAddress = types.StringValue(value.String())
+ } else {
+ data.Ipv4ActiveAddress = types.StringNull()
+ }
+ }
+ if data.Ipv4Netmask.IsUnknown() {
+ if value := res.Get("ipv4Configuration.activeIPv4Mask"); value.Exists() {
+ data.Ipv4Netmask = types.StringValue(value.String())
+ } else {
+ data.Ipv4Netmask = types.StringNull()
+ }
+ }
+}
+
+// End of section. //template:end fromBodyUnknowns
+
+// Section below is generated&owned by "gen/generator.go". //template:begin Clone
+
+// End of section. //template:end Clone
+
+// Section below is generated&owned by "gen/generator.go". //template:begin toBodyNonBulk
+
+// End of section. //template:end toBodyNonBulk
+
+// toBodyPutDelete generates minimal required body to reset the resource to its default state.
+func (data DeviceHAPairMonitoring) toBodyPutDelete(ctx context.Context, state DeviceHAPairMonitoring) string {
+ body := ""
+ body, _ = sjson.Set(body, "monitorForFailures", false)
+ if data.Ipv4ActiveAddress.ValueString() != "" {
+ body, _ = sjson.Set(body, "ipv4Configuration.activeIPv4Address", data.Ipv4ActiveAddress.ValueString())
+ }
+ // There is no way of removing standby IPv6 via API now
+ //if len(data.Ipv6Addresses) > 0 {
+ // body, _ = sjson.Set(body, "ipv6Configuration.ipv6ActiveStandbyPair", []interface{}{})
+ // for _, item := range data.Ipv6Addresses {
+ // itemBody := ""
+ // if !item.ActiveAddress.IsNull() {
+ // itemBody, _ = sjson.Set(itemBody, "activeIPv6", item.ActiveAddress.ValueString())
+ // itemBody, _ = sjson.Set(itemBody, "standbyIPv6", "")
+ // }
+ // body, _ = sjson.SetRaw(body, "ipv6Configuration.ipv6ActiveStandbyPair.-1", itemBody)
+ // }
+ //}
+ if data.Id.ValueString() != "" {
+ body, _ = sjson.Set(body, "id", data.Id.ValueString())
+ }
+ if !data.LogicalName.IsNull() {
+ body, _ = sjson.Set(body, "name", data.LogicalName.ValueString())
+ }
+ return body
+}
diff --git a/internal/provider/model_fmc_network.go b/internal/provider/model_fmc_network.go
index 67b5f6af..7db3644d 100644
--- a/internal/provider/model_fmc_network.go
+++ b/internal/provider/model_fmc_network.go
@@ -60,9 +60,6 @@ func (data Network) toBody(ctx context.Context, state Network) string {
if !data.Name.IsNull() {
body, _ = sjson.Set(body, "name", data.Name.ValueString())
}
- if !data.Type.IsNull() {
- body, _ = sjson.Set(body, "type", data.Type.ValueString())
- }
if !data.Description.IsNull() {
body, _ = sjson.Set(body, "description", data.Description.ValueString())
}
@@ -88,7 +85,7 @@ func (data *Network) fromBody(ctx context.Context, res gjson.Result) {
if value := res.Get("type"); value.Exists() {
data.Type = types.StringValue(value.String())
} else {
- data.Type = types.StringValue("Network")
+ data.Type = types.StringNull()
}
if value := res.Get("description"); value.Exists() {
data.Description = types.StringValue(value.String())
@@ -123,7 +120,7 @@ func (data *Network) fromBodyPartial(ctx context.Context, res gjson.Result) {
}
if value := res.Get("type"); value.Exists() && !data.Type.IsNull() {
data.Type = types.StringValue(value.String())
- } else if data.Type.ValueString() != "Network" {
+ } else {
data.Type = types.StringNull()
}
if value := res.Get("description"); value.Exists() && !data.Description.IsNull() {
@@ -150,6 +147,13 @@ func (data *Network) fromBodyPartial(ctx context.Context, res gjson.Result) {
// fromBodyUnknowns updates the Unknown Computed tfstate values from a JSON.
// Known values are not changed (usual for Computed attributes with UseStateForUnknown or with Default).
func (data *Network) fromBodyUnknowns(ctx context.Context, res gjson.Result) {
+ if data.Type.IsUnknown() {
+ if value := res.Get("type"); value.Exists() {
+ data.Type = types.StringValue(value.String())
+ } else {
+ data.Type = types.StringNull()
+ }
+ }
}
// End of section. //template:end fromBodyUnknowns
diff --git a/internal/provider/model_fmc_networks.go b/internal/provider/model_fmc_networks.go
index 50760ee2..863b7292 100644
--- a/internal/provider/model_fmc_networks.go
+++ b/internal/provider/model_fmc_networks.go
@@ -80,9 +80,6 @@ func (data Networks) toBody(ctx context.Context, state Networks) string {
if !item.Prefix.IsNull() {
itemBody, _ = sjson.Set(itemBody, "value", item.Prefix.ValueString())
}
- if !item.Type.IsNull() {
- itemBody, _ = sjson.Set(itemBody, "type", item.Type.ValueString())
- }
body, _ = sjson.SetRaw(body, "items.-1", itemBody)
}
}
@@ -137,7 +134,7 @@ func (data *Networks) fromBody(ctx context.Context, res gjson.Result) {
if value := res.Get("type"); value.Exists() {
data.Type = types.StringValue(value.String())
} else {
- data.Type = types.StringValue("Network")
+ data.Type = types.StringNull()
}
(*parent).Items[k] = data
}
@@ -189,7 +186,7 @@ func (data *Networks) fromBodyPartial(ctx context.Context, res gjson.Result) {
}
if value := res.Get("type"); value.Exists() && !data.Type.IsNull() {
data.Type = types.StringValue(value.String())
- } else if data.Type.ValueString() != "Network" {
+ } else {
data.Type = types.StringNull()
}
(*parent).Items[i] = data
@@ -230,6 +227,14 @@ func (data *Networks) fromBodyUnknowns(ctx context.Context, res gjson.Result) {
}
data.Items[i] = v
}
+ if v := data.Items[i]; v.Type.IsUnknown() {
+ if value := r.Get("type"); value.Exists() {
+ v.Type = types.StringValue(value.String())
+ } else {
+ v.Type = types.StringNull()
+ }
+ data.Items[i] = v
+ }
}
}
diff --git a/internal/provider/model_fmc_port_group.go b/internal/provider/model_fmc_port_group.go
index eac97b49..a3771e09 100644
--- a/internal/provider/model_fmc_port_group.go
+++ b/internal/provider/model_fmc_port_group.go
@@ -68,9 +68,6 @@ func (data PortGroup) toBody(ctx context.Context, state PortGroup) string {
if !data.Name.IsNull() {
body, _ = sjson.Set(body, "name", data.Name.ValueString())
}
- if !data.Type.IsNull() {
- body, _ = sjson.Set(body, "type", data.Type.ValueString())
- }
if !data.Description.IsNull() {
body, _ = sjson.Set(body, "description", data.Description.ValueString())
}
@@ -106,7 +103,7 @@ func (data *PortGroup) fromBody(ctx context.Context, res gjson.Result) {
if value := res.Get("type"); value.Exists() {
data.Type = types.StringValue(value.String())
} else {
- data.Type = types.StringValue("PortObjectGroup")
+ data.Type = types.StringNull()
}
if value := res.Get("description"); value.Exists() {
data.Description = types.StringValue(value.String())
@@ -155,7 +152,7 @@ func (data *PortGroup) fromBodyPartial(ctx context.Context, res gjson.Result) {
}
if value := res.Get("type"); value.Exists() && !data.Type.IsNull() {
data.Type = types.StringValue(value.String())
- } else if data.Type.ValueString() != "PortObjectGroup" {
+ } else {
data.Type = types.StringNull()
}
if value := res.Get("description"); value.Exists() && !data.Description.IsNull() {
@@ -225,6 +222,13 @@ func (data *PortGroup) fromBodyPartial(ctx context.Context, res gjson.Result) {
// fromBodyUnknowns updates the Unknown Computed tfstate values from a JSON.
// Known values are not changed (usual for Computed attributes with UseStateForUnknown or with Default).
func (data *PortGroup) fromBodyUnknowns(ctx context.Context, res gjson.Result) {
+ if data.Type.IsUnknown() {
+ if value := res.Get("type"); value.Exists() {
+ data.Type = types.StringValue(value.String())
+ } else {
+ data.Type = types.StringNull()
+ }
+ }
}
// End of section. //template:end fromBodyUnknowns
diff --git a/internal/provider/model_fmc_port_groups.go b/internal/provider/model_fmc_port_groups.go
index 9a6e74e3..c9dfc552 100644
--- a/internal/provider/model_fmc_port_groups.go
+++ b/internal/provider/model_fmc_port_groups.go
@@ -77,9 +77,6 @@ func (data PortGroups) toBody(ctx context.Context, state PortGroups) string {
if !item.Id.IsNull() && !item.Id.IsUnknown() {
itemBody, _ = sjson.Set(itemBody, "id", item.Id.ValueString())
}
- if !item.Type.IsNull() {
- itemBody, _ = sjson.Set(itemBody, "type", item.Type.ValueString())
- }
if !item.Description.IsNull() {
itemBody, _ = sjson.Set(itemBody, "description", item.Description.ValueString())
}
@@ -138,7 +135,7 @@ func (data *PortGroups) fromBody(ctx context.Context, res gjson.Result) {
if value := res.Get("type"); value.Exists() {
data.Type = types.StringValue(value.String())
} else {
- data.Type = types.StringValue("PortObjectGroup")
+ data.Type = types.StringNull()
}
if value := res.Get("description"); value.Exists() {
data.Description = types.StringValue(value.String())
@@ -204,7 +201,7 @@ func (data *PortGroups) fromBodyPartial(ctx context.Context, res gjson.Result) {
}
if value := res.Get("type"); value.Exists() && !data.Type.IsNull() {
data.Type = types.StringValue(value.String())
- } else if data.Type.ValueString() != "PortObjectGroup" {
+ } else {
data.Type = types.StringNull()
}
if value := res.Get("description"); value.Exists() && !data.Description.IsNull() {
@@ -303,6 +300,14 @@ func (data *PortGroups) fromBodyUnknowns(ctx context.Context, res gjson.Result)
}
data.Items[i] = v
}
+ if v := data.Items[i]; v.Type.IsUnknown() {
+ if value := r.Get("type"); value.Exists() {
+ v.Type = types.StringValue(value.String())
+ } else {
+ v.Type = types.StringNull()
+ }
+ data.Items[i] = v
+ }
}
}
diff --git a/internal/provider/model_fmc_security_zone.go b/internal/provider/model_fmc_security_zone.go
index 4aab8c0c..e551d103 100644
--- a/internal/provider/model_fmc_security_zone.go
+++ b/internal/provider/model_fmc_security_zone.go
@@ -34,7 +34,7 @@ type SecurityZone struct {
Id types.String `tfsdk:"id"`
Domain types.String `tfsdk:"domain"`
Name types.String `tfsdk:"name"`
- InterfaceMode types.String `tfsdk:"interface_mode"`
+ InterfaceType types.String `tfsdk:"interface_type"`
Type types.String `tfsdk:"type"`
}
@@ -58,11 +58,8 @@ func (data SecurityZone) toBody(ctx context.Context, state SecurityZone) string
if !data.Name.IsNull() {
body, _ = sjson.Set(body, "name", data.Name.ValueString())
}
- if !data.InterfaceMode.IsNull() {
- body, _ = sjson.Set(body, "interfaceMode", data.InterfaceMode.ValueString())
- }
- if !data.Type.IsNull() {
- body, _ = sjson.Set(body, "type", data.Type.ValueString())
+ if !data.InterfaceType.IsNull() {
+ body, _ = sjson.Set(body, "interfaceMode", data.InterfaceType.ValueString())
}
return body
}
@@ -78,14 +75,14 @@ func (data *SecurityZone) fromBody(ctx context.Context, res gjson.Result) {
data.Name = types.StringNull()
}
if value := res.Get("interfaceMode"); value.Exists() {
- data.InterfaceMode = types.StringValue(value.String())
+ data.InterfaceType = types.StringValue(value.String())
} else {
- data.InterfaceMode = types.StringNull()
+ data.InterfaceType = types.StringNull()
}
if value := res.Get("type"); value.Exists() {
data.Type = types.StringValue(value.String())
} else {
- data.Type = types.StringValue("SecurityZone")
+ data.Type = types.StringNull()
}
}
@@ -103,14 +100,14 @@ func (data *SecurityZone) fromBodyPartial(ctx context.Context, res gjson.Result)
} else {
data.Name = types.StringNull()
}
- if value := res.Get("interfaceMode"); value.Exists() && !data.InterfaceMode.IsNull() {
- data.InterfaceMode = types.StringValue(value.String())
+ if value := res.Get("interfaceMode"); value.Exists() && !data.InterfaceType.IsNull() {
+ data.InterfaceType = types.StringValue(value.String())
} else {
- data.InterfaceMode = types.StringNull()
+ data.InterfaceType = types.StringNull()
}
if value := res.Get("type"); value.Exists() && !data.Type.IsNull() {
data.Type = types.StringValue(value.String())
- } else if data.Type.ValueString() != "SecurityZone" {
+ } else {
data.Type = types.StringNull()
}
}
@@ -122,6 +119,13 @@ func (data *SecurityZone) fromBodyPartial(ctx context.Context, res gjson.Result)
// fromBodyUnknowns updates the Unknown Computed tfstate values from a JSON.
// Known values are not changed (usual for Computed attributes with UseStateForUnknown or with Default).
func (data *SecurityZone) fromBodyUnknowns(ctx context.Context, res gjson.Result) {
+ if data.Type.IsUnknown() {
+ if value := res.Get("type"); value.Exists() {
+ data.Type = types.StringValue(value.String())
+ } else {
+ data.Type = types.StringNull()
+ }
+ }
}
// End of section. //template:end fromBodyUnknowns
diff --git a/internal/provider/model_fmc_security_zones.go b/internal/provider/model_fmc_security_zones.go
index 457b8565..c40190ce 100644
--- a/internal/provider/model_fmc_security_zones.go
+++ b/internal/provider/model_fmc_security_zones.go
@@ -41,7 +41,7 @@ type SecurityZones struct {
type SecurityZonesItems struct {
Id types.String `tfsdk:"id"`
- InterfaceMode types.String `tfsdk:"interface_mode"`
+ InterfaceType types.String `tfsdk:"interface_type"`
Type types.String `tfsdk:"type"`
}
@@ -69,11 +69,8 @@ func (data SecurityZones) toBody(ctx context.Context, state SecurityZones) strin
if !item.Id.IsNull() && !item.Id.IsUnknown() {
itemBody, _ = sjson.Set(itemBody, "id", item.Id.ValueString())
}
- if !item.InterfaceMode.IsNull() {
- itemBody, _ = sjson.Set(itemBody, "interfaceMode", item.InterfaceMode.ValueString())
- }
- if !item.Type.IsNull() {
- itemBody, _ = sjson.Set(itemBody, "type", item.Type.ValueString())
+ if !item.InterfaceType.IsNull() {
+ itemBody, _ = sjson.Set(itemBody, "interfaceMode", item.InterfaceType.ValueString())
}
body, _ = sjson.SetRaw(body, "items.-1", itemBody)
}
@@ -112,14 +109,14 @@ func (data *SecurityZones) fromBody(ctx context.Context, res gjson.Result) {
data.Id = types.StringNull()
}
if value := res.Get("interfaceMode"); value.Exists() {
- data.InterfaceMode = types.StringValue(value.String())
+ data.InterfaceType = types.StringValue(value.String())
} else {
- data.InterfaceMode = types.StringNull()
+ data.InterfaceType = types.StringNull()
}
if value := res.Get("type"); value.Exists() {
data.Type = types.StringValue(value.String())
} else {
- data.Type = types.StringValue("SecurityZone")
+ data.Type = types.StringNull()
}
(*parent).Items[k] = data
}
@@ -154,14 +151,14 @@ func (data *SecurityZones) fromBodyPartial(ctx context.Context, res gjson.Result
} else {
data.Id = types.StringNull()
}
- if value := res.Get("interfaceMode"); value.Exists() && !data.InterfaceMode.IsNull() {
- data.InterfaceMode = types.StringValue(value.String())
+ if value := res.Get("interfaceMode"); value.Exists() && !data.InterfaceType.IsNull() {
+ data.InterfaceType = types.StringValue(value.String())
} else {
- data.InterfaceMode = types.StringNull()
+ data.InterfaceType = types.StringNull()
}
if value := res.Get("type"); value.Exists() && !data.Type.IsNull() {
data.Type = types.StringValue(value.String())
- } else if data.Type.ValueString() != "SecurityZone" {
+ } else {
data.Type = types.StringNull()
}
(*parent).Items[i] = data
@@ -202,6 +199,14 @@ func (data *SecurityZones) fromBodyUnknowns(ctx context.Context, res gjson.Resul
}
data.Items[i] = v
}
+ if v := data.Items[i]; v.Type.IsUnknown() {
+ if value := r.Get("type"); value.Exists() {
+ v.Type = types.StringValue(value.String())
+ } else {
+ v.Type = types.StringNull()
+ }
+ data.Items[i] = v
+ }
}
}
diff --git a/internal/provider/model_fmc_snmp_alert.go b/internal/provider/model_fmc_snmp_alert.go
index eae10335..b83f2e34 100644
--- a/internal/provider/model_fmc_snmp_alert.go
+++ b/internal/provider/model_fmc_snmp_alert.go
@@ -57,9 +57,6 @@ func (data SNMPAlert) toBody(ctx context.Context, state SNMPAlert) string {
if !data.Name.IsNull() {
body, _ = sjson.Set(body, "name", data.Name.ValueString())
}
- if !data.Type.IsNull() {
- body, _ = sjson.Set(body, "type", data.Type.ValueString())
- }
return body
}
@@ -76,7 +73,7 @@ func (data *SNMPAlert) fromBody(ctx context.Context, res gjson.Result) {
if value := res.Get("type"); value.Exists() {
data.Type = types.StringValue(value.String())
} else {
- data.Type = types.StringValue("SNMPAlert")
+ data.Type = types.StringNull()
}
}
@@ -96,7 +93,7 @@ func (data *SNMPAlert) fromBodyPartial(ctx context.Context, res gjson.Result) {
}
if value := res.Get("type"); value.Exists() && !data.Type.IsNull() {
data.Type = types.StringValue(value.String())
- } else if data.Type.ValueString() != "SNMPAlert" {
+ } else {
data.Type = types.StringNull()
}
}
@@ -108,6 +105,13 @@ func (data *SNMPAlert) fromBodyPartial(ctx context.Context, res gjson.Result) {
// fromBodyUnknowns updates the Unknown Computed tfstate values from a JSON.
// Known values are not changed (usual for Computed attributes with UseStateForUnknown or with Default).
func (data *SNMPAlert) fromBodyUnknowns(ctx context.Context, res gjson.Result) {
+ if data.Type.IsUnknown() {
+ if value := res.Get("type"); value.Exists() {
+ data.Type = types.StringValue(value.String())
+ } else {
+ data.Type = types.StringNull()
+ }
+ }
}
// End of section. //template:end fromBodyUnknowns
diff --git a/internal/provider/model_fmc_snmp_alerts.go b/internal/provider/model_fmc_snmp_alerts.go
index 17e7cc3c..b1e431b7 100644
--- a/internal/provider/model_fmc_snmp_alerts.go
+++ b/internal/provider/model_fmc_snmp_alerts.go
@@ -68,9 +68,6 @@ func (data SNMPAlerts) toBody(ctx context.Context, state SNMPAlerts) string {
if !item.Id.IsNull() && !item.Id.IsUnknown() {
itemBody, _ = sjson.Set(itemBody, "id", item.Id.ValueString())
}
- if !item.Type.IsNull() {
- itemBody, _ = sjson.Set(itemBody, "type", item.Type.ValueString())
- }
body, _ = sjson.SetRaw(body, "items.-1", itemBody)
}
}
@@ -110,7 +107,7 @@ func (data *SNMPAlerts) fromBody(ctx context.Context, res gjson.Result) {
if value := res.Get("type"); value.Exists() {
data.Type = types.StringValue(value.String())
} else {
- data.Type = types.StringValue("SNMPAlert")
+ data.Type = types.StringNull()
}
(*parent).Items[k] = data
}
@@ -147,7 +144,7 @@ func (data *SNMPAlerts) fromBodyPartial(ctx context.Context, res gjson.Result) {
}
if value := res.Get("type"); value.Exists() && !data.Type.IsNull() {
data.Type = types.StringValue(value.String())
- } else if data.Type.ValueString() != "SNMPAlert" {
+ } else {
data.Type = types.StringNull()
}
(*parent).Items[i] = data
@@ -188,6 +185,14 @@ func (data *SNMPAlerts) fromBodyUnknowns(ctx context.Context, res gjson.Result)
}
data.Items[i] = v
}
+ if v := data.Items[i]; v.Type.IsUnknown() {
+ if value := r.Get("type"); value.Exists() {
+ v.Type = types.StringValue(value.String())
+ } else {
+ v.Type = types.StringNull()
+ }
+ data.Items[i] = v
+ }
}
}
diff --git a/internal/provider/model_fmc_syslog_alert.go b/internal/provider/model_fmc_syslog_alert.go
index 0678f70e..d6a332c2 100644
--- a/internal/provider/model_fmc_syslog_alert.go
+++ b/internal/provider/model_fmc_syslog_alert.go
@@ -57,9 +57,6 @@ func (data SyslogAlert) toBody(ctx context.Context, state SyslogAlert) string {
if !data.Name.IsNull() {
body, _ = sjson.Set(body, "name", data.Name.ValueString())
}
- if !data.Type.IsNull() {
- body, _ = sjson.Set(body, "type", data.Type.ValueString())
- }
return body
}
@@ -76,7 +73,7 @@ func (data *SyslogAlert) fromBody(ctx context.Context, res gjson.Result) {
if value := res.Get("type"); value.Exists() {
data.Type = types.StringValue(value.String())
} else {
- data.Type = types.StringValue("SyslogAlert")
+ data.Type = types.StringNull()
}
}
@@ -96,7 +93,7 @@ func (data *SyslogAlert) fromBodyPartial(ctx context.Context, res gjson.Result)
}
if value := res.Get("type"); value.Exists() && !data.Type.IsNull() {
data.Type = types.StringValue(value.String())
- } else if data.Type.ValueString() != "SyslogAlert" {
+ } else {
data.Type = types.StringNull()
}
}
@@ -108,6 +105,13 @@ func (data *SyslogAlert) fromBodyPartial(ctx context.Context, res gjson.Result)
// fromBodyUnknowns updates the Unknown Computed tfstate values from a JSON.
// Known values are not changed (usual for Computed attributes with UseStateForUnknown or with Default).
func (data *SyslogAlert) fromBodyUnknowns(ctx context.Context, res gjson.Result) {
+ if data.Type.IsUnknown() {
+ if value := res.Get("type"); value.Exists() {
+ data.Type = types.StringValue(value.String())
+ } else {
+ data.Type = types.StringNull()
+ }
+ }
}
// End of section. //template:end fromBodyUnknowns
diff --git a/internal/provider/model_fmc_syslog_alerts.go b/internal/provider/model_fmc_syslog_alerts.go
index 00cbf6f0..7c57195d 100644
--- a/internal/provider/model_fmc_syslog_alerts.go
+++ b/internal/provider/model_fmc_syslog_alerts.go
@@ -68,9 +68,6 @@ func (data SyslogAlerts) toBody(ctx context.Context, state SyslogAlerts) string
if !item.Id.IsNull() && !item.Id.IsUnknown() {
itemBody, _ = sjson.Set(itemBody, "id", item.Id.ValueString())
}
- if !item.Type.IsNull() {
- itemBody, _ = sjson.Set(itemBody, "type", item.Type.ValueString())
- }
body, _ = sjson.SetRaw(body, "items.-1", itemBody)
}
}
@@ -110,7 +107,7 @@ func (data *SyslogAlerts) fromBody(ctx context.Context, res gjson.Result) {
if value := res.Get("type"); value.Exists() {
data.Type = types.StringValue(value.String())
} else {
- data.Type = types.StringValue("SyslogAlert")
+ data.Type = types.StringNull()
}
(*parent).Items[k] = data
}
@@ -147,7 +144,7 @@ func (data *SyslogAlerts) fromBodyPartial(ctx context.Context, res gjson.Result)
}
if value := res.Get("type"); value.Exists() && !data.Type.IsNull() {
data.Type = types.StringValue(value.String())
- } else if data.Type.ValueString() != "SyslogAlert" {
+ } else {
data.Type = types.StringNull()
}
(*parent).Items[i] = data
@@ -188,6 +185,14 @@ func (data *SyslogAlerts) fromBodyUnknowns(ctx context.Context, res gjson.Result
}
data.Items[i] = v
}
+ if v := data.Items[i]; v.Type.IsUnknown() {
+ if value := r.Get("type"); value.Exists() {
+ v.Type = types.StringValue(value.String())
+ } else {
+ v.Type = types.StringNull()
+ }
+ data.Items[i] = v
+ }
}
}
diff --git a/internal/provider/model_fmc_variable_set.go b/internal/provider/model_fmc_variable_set.go
index 5dbe90ae..270af1f6 100644
--- a/internal/provider/model_fmc_variable_set.go
+++ b/internal/provider/model_fmc_variable_set.go
@@ -61,9 +61,6 @@ func (data VariableSet) toBody(ctx context.Context, state VariableSet) string {
if !data.Description.IsNull() {
body, _ = sjson.Set(body, "description", data.Description.ValueString())
}
- if !data.Type.IsNull() {
- body, _ = sjson.Set(body, "type", data.Type.ValueString())
- }
return body
}
@@ -85,7 +82,7 @@ func (data *VariableSet) fromBody(ctx context.Context, res gjson.Result) {
if value := res.Get("type"); value.Exists() {
data.Type = types.StringValue(value.String())
} else {
- data.Type = types.StringValue("VariableSet")
+ data.Type = types.StringNull()
}
}
@@ -110,7 +107,7 @@ func (data *VariableSet) fromBodyPartial(ctx context.Context, res gjson.Result)
}
if value := res.Get("type"); value.Exists() && !data.Type.IsNull() {
data.Type = types.StringValue(value.String())
- } else if data.Type.ValueString() != "VariableSet" {
+ } else {
data.Type = types.StringNull()
}
}
@@ -122,6 +119,13 @@ func (data *VariableSet) fromBodyPartial(ctx context.Context, res gjson.Result)
// fromBodyUnknowns updates the Unknown Computed tfstate values from a JSON.
// Known values are not changed (usual for Computed attributes with UseStateForUnknown or with Default).
func (data *VariableSet) fromBodyUnknowns(ctx context.Context, res gjson.Result) {
+ if data.Type.IsUnknown() {
+ if value := res.Get("type"); value.Exists() {
+ data.Type = types.StringValue(value.String())
+ } else {
+ data.Type = types.StringNull()
+ }
+ }
}
// End of section. //template:end fromBodyUnknowns
diff --git a/internal/provider/provider.go b/internal/provider/provider.go
index da76c28d..ebc832df 100644
--- a/internal/provider/provider.go
+++ b/internal/provider/provider.go
@@ -293,8 +293,13 @@ func (p *FmcProvider) Configure(ctx context.Context, req provider.ConfigureReque
func (p *FmcProvider) Resources(ctx context.Context) []func() resource.Resource {
return []func() resource.Resource{
NewAccessControlPolicyResource,
+ NewBFDTemplateResource,
NewDeviceResource,
+ NewDeviceBFDResource,
+ NewDeviceBGPResource,
+ NewDeviceBGPGeneralSettingsResource,
NewDeviceEtherChannelInterfaceResource,
+ NewDeviceHAPairMonitoringResource,
NewDeviceIPv4StaticRouteResource,
NewDeviceIPv6StaticRouteResource,
NewDevicePhysicalInterfaceResource,
@@ -346,8 +351,13 @@ func (p *FmcProvider) Resources(ctx context.Context) []func() resource.Resource
func (p *FmcProvider) DataSources(ctx context.Context) []func() datasource.DataSource {
return []func() datasource.DataSource{
NewAccessControlPolicyDataSource,
+ NewBFDTemplateDataSource,
NewDeviceDataSource,
+ NewDeviceBFDDataSource,
+ NewDeviceBGPDataSource,
+ NewDeviceBGPGeneralSettingsDataSource,
NewDeviceEtherChannelInterfaceDataSource,
+ NewDeviceHAPairMonitoringDataSource,
NewDeviceIPv4StaticRouteDataSource,
NewDeviceIPv6StaticRouteDataSource,
NewDevicePhysicalInterfaceDataSource,
diff --git a/internal/provider/resource_fmc_bfd_template.go b/internal/provider/resource_fmc_bfd_template.go
new file mode 100644
index 00000000..90e51c46
--- /dev/null
+++ b/internal/provider/resource_fmc_bfd_template.go
@@ -0,0 +1,350 @@
+// Copyright © 2023 Cisco Systems, Inc. and its affiliates.
+// All rights reserved.
+//
+// Licensed under the Mozilla Public License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://mozilla.org/MPL/2.0/
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// SPDX-License-Identifier: MPL-2.0
+
+package provider
+
+// Section below is generated&owned by "gen/generator.go". //template:begin imports
+import (
+ "context"
+ "fmt"
+ "net/url"
+ "strings"
+
+ "github.com/hashicorp/terraform-plugin-framework-validators/int64validator"
+ "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
+ "github.com/hashicorp/terraform-plugin-framework/path"
+ "github.com/hashicorp/terraform-plugin-framework/resource"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
+ "github.com/hashicorp/terraform-plugin-framework/schema/validator"
+ "github.com/hashicorp/terraform-plugin-framework/types"
+ "github.com/hashicorp/terraform-plugin-log/tflog"
+ "github.com/netascode/go-fmc"
+ "github.com/netascode/terraform-provider-fmc/internal/provider/helpers"
+)
+
+// End of section. //template:end imports
+
+// Section below is generated&owned by "gen/generator.go". //template:begin model
+
+// Ensure provider defined types fully satisfy framework interfaces
+var (
+ _ resource.Resource = &BFDTemplateResource{}
+ _ resource.ResourceWithImportState = &BFDTemplateResource{}
+)
+
+func NewBFDTemplateResource() resource.Resource {
+ return &BFDTemplateResource{}
+}
+
+type BFDTemplateResource struct {
+ client *fmc.Client
+}
+
+func (r *BFDTemplateResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
+ resp.TypeName = req.ProviderTypeName + "_bfd_template"
+}
+
+func (r *BFDTemplateResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
+ resp.Schema = schema.Schema{
+ // This description is used by the documentation generator and the language server.
+ MarkdownDescription: helpers.NewAttributeDescription("This resource can manage a BFD Template.").String,
+
+ Attributes: map[string]schema.Attribute{
+ "id": schema.StringAttribute{
+ MarkdownDescription: "The id of the object",
+ Computed: true,
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.UseStateForUnknown(),
+ },
+ },
+ "domain": schema.StringAttribute{
+ MarkdownDescription: "The name of the FMC domain",
+ Optional: true,
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.RequiresReplace(),
+ },
+ },
+ "name": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("The name of the bfd template object.").String,
+ Required: true,
+ },
+ "type": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Type of the object; this value is always 'BFDTemplate'.").String,
+ Computed: true,
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.UseStateForUnknown(),
+ },
+ },
+ "hop_type": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("The hop type.").AddStringEnumDescription("SINGLE_HOP", "MULTI_HOP").String,
+ Required: true,
+ Validators: []validator.String{
+ stringvalidator.OneOf("SINGLE_HOP", "MULTI_HOP"),
+ },
+ },
+ "echo": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Enables/disables BFD echo.").AddStringEnumDescription("ENABLED", "DISABLED").String,
+ Required: true,
+ Validators: []validator.String{
+ stringvalidator.OneOf("ENABLED", "DISABLED"),
+ },
+ },
+ "interval_time": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Interval unit of measurement of time.").AddStringEnumDescription("MILLISECONDS", "MICROSECONDS", "NONE").String,
+ Optional: true,
+ Validators: []validator.String{
+ stringvalidator.OneOf("MILLISECONDS", "MICROSECONDS", "NONE"),
+ },
+ },
+ "min_transmit": schema.Int64Attribute{
+ MarkdownDescription: helpers.NewAttributeDescription("BFD Minimum Transmit unit value.").AddIntegerRangeDescription(50, 999000).String,
+ Optional: true,
+ Validators: []validator.Int64{
+ int64validator.Between(50, 999000),
+ },
+ },
+ "tx_rx_multiplier": schema.Int64Attribute{
+ MarkdownDescription: helpers.NewAttributeDescription("BFD Multipler value.").AddIntegerRangeDescription(3, 50).String,
+ Optional: true,
+ Validators: []validator.Int64{
+ int64validator.Between(3, 50),
+ },
+ },
+ "min_receive": schema.Int64Attribute{
+ MarkdownDescription: helpers.NewAttributeDescription("BFD Minimum Receive unit value in ranges: 50-999 miliseconds, 50000-999000 microseconds").AddIntegerRangeDescription(50, 999000).String,
+ Optional: true,
+ Validators: []validator.Int64{
+ int64validator.Between(50, 999000),
+ },
+ },
+ "authentication_password": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Password for BFD Authentication (1-24 characters)").String,
+ Optional: true,
+ },
+ "authentication_key_id": schema.Int64Attribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Authentication Key ID").AddIntegerRangeDescription(0, 255).String,
+ Optional: true,
+ Validators: []validator.Int64{
+ int64validator.Between(0, 255),
+ },
+ },
+ "authentication_type": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Authentication types").AddStringEnumDescription("MD5", "METICULOUSMD5", "METICULOUSSHA1", "SHA1", "NONE").String,
+ Optional: true,
+ Validators: []validator.String{
+ stringvalidator.OneOf("MD5", "METICULOUSMD5", "METICULOUSSHA1", "SHA1", "NONE"),
+ },
+ },
+ },
+ }
+}
+
+func (r *BFDTemplateResource) Configure(_ context.Context, req resource.ConfigureRequest, _ *resource.ConfigureResponse) {
+ if req.ProviderData == nil {
+ return
+ }
+
+ r.client = req.ProviderData.(*FmcProviderData).Client
+}
+
+// End of section. //template:end model
+
+// Section below is generated&owned by "gen/generator.go". //template:begin create
+
+func (r *BFDTemplateResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
+ var plan BFDTemplate
+
+ // Read plan
+ diags := req.Plan.Get(ctx, &plan)
+ if resp.Diagnostics.Append(diags...); resp.Diagnostics.HasError() {
+ return
+ }
+
+ // Set request domain if provided
+ reqMods := [](func(*fmc.Req)){}
+ if !plan.Domain.IsNull() && plan.Domain.ValueString() != "" {
+ reqMods = append(reqMods, fmc.DomainName(plan.Domain.ValueString()))
+ }
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Beginning Create", plan.Id.ValueString()))
+
+ // Create object
+ body := plan.toBody(ctx, BFDTemplate{})
+ res, err := r.client.Post(plan.getPath(), body, reqMods...)
+ if err != nil {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to configure object (POST/PUT), got error: %s, %s", err, res.String()))
+ return
+ }
+ plan.Id = types.StringValue(res.Get("id").String())
+ plan.fromBodyUnknowns(ctx, res)
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Create finished successfully", plan.Id.ValueString()))
+
+ diags = resp.State.Set(ctx, &plan)
+ resp.Diagnostics.Append(diags...)
+
+ helpers.SetFlagImporting(ctx, false, resp.Private, &resp.Diagnostics)
+}
+
+// End of section. //template:end create
+
+// Section below is generated&owned by "gen/generator.go". //template:begin read
+
+func (r *BFDTemplateResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
+ var state BFDTemplate
+
+ // Read state
+ diags := req.State.Get(ctx, &state)
+ if resp.Diagnostics.Append(diags...); resp.Diagnostics.HasError() {
+ return
+ }
+
+ // Set request domain if provided
+ reqMods := [](func(*fmc.Req)){}
+ if !state.Domain.IsNull() && state.Domain.ValueString() != "" {
+ reqMods = append(reqMods, fmc.DomainName(state.Domain.ValueString()))
+ }
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Beginning Read", state.Id.String()))
+
+ urlPath := state.getPath() + "/" + url.QueryEscape(state.Id.ValueString())
+ res, err := r.client.Get(urlPath, reqMods...)
+
+ if err != nil && strings.Contains(err.Error(), "StatusCode 404") {
+ resp.State.RemoveResource(ctx)
+ return
+ } else if err != nil {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to retrieve object (GET), got error: %s, %s", err, res.String()))
+ return
+ }
+
+ imp, diags := helpers.IsFlagImporting(ctx, req)
+ if resp.Diagnostics.Append(diags...); resp.Diagnostics.HasError() {
+ return
+ }
+
+ // After `terraform import` we switch to a full read.
+ if imp {
+ state.fromBody(ctx, res)
+ } else {
+ state.fromBodyPartial(ctx, res)
+ }
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Read finished successfully", state.Id.ValueString()))
+
+ diags = resp.State.Set(ctx, &state)
+ resp.Diagnostics.Append(diags...)
+
+ helpers.SetFlagImporting(ctx, false, resp.Private, &resp.Diagnostics)
+}
+
+// End of section. //template:end read
+
+// Section below is generated&owned by "gen/generator.go". //template:begin update
+
+func (r *BFDTemplateResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
+ var plan, state BFDTemplate
+
+ // Read plan
+ diags := req.Plan.Get(ctx, &plan)
+ if resp.Diagnostics.Append(diags...); resp.Diagnostics.HasError() {
+ return
+ }
+
+ // Read state
+ diags = req.State.Get(ctx, &state)
+ if resp.Diagnostics.Append(diags...); resp.Diagnostics.HasError() {
+ return
+ }
+
+ // Set request domain if provided
+ reqMods := [](func(*fmc.Req)){}
+ if !plan.Domain.IsNull() && plan.Domain.ValueString() != "" {
+ reqMods = append(reqMods, fmc.DomainName(plan.Domain.ValueString()))
+ }
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Beginning Update", plan.Id.ValueString()))
+
+ body := plan.toBody(ctx, state)
+ res, err := r.client.Put(plan.getPath()+"/"+url.QueryEscape(plan.Id.ValueString()), body, reqMods...)
+ if err != nil {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to configure object (PUT), got error: %s, %s", err, res.String()))
+ return
+ }
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Update finished successfully", plan.Id.ValueString()))
+
+ diags = resp.State.Set(ctx, &plan)
+ resp.Diagnostics.Append(diags...)
+}
+
+// End of section. //template:end update
+
+// Section below is generated&owned by "gen/generator.go". //template:begin delete
+
+func (r *BFDTemplateResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
+ var state BFDTemplate
+
+ // Read state
+ diags := req.State.Get(ctx, &state)
+ if resp.Diagnostics.Append(diags...); resp.Diagnostics.HasError() {
+ return
+ }
+
+ // Set request domain if provided
+ reqMods := [](func(*fmc.Req)){}
+ if !state.Domain.IsNull() && state.Domain.ValueString() != "" {
+ reqMods = append(reqMods, fmc.DomainName(state.Domain.ValueString()))
+ }
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Beginning Delete", state.Id.ValueString()))
+ res, err := r.client.Delete(state.getPath()+"/"+url.QueryEscape(state.Id.ValueString()), reqMods...)
+ if err != nil {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to delete object (DELETE), got error: %s, %s", err, res.String()))
+ return
+ }
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Delete finished successfully", state.Id.ValueString()))
+
+ resp.State.RemoveResource(ctx)
+}
+
+// End of section. //template:end delete
+
+// Section below is generated&owned by "gen/generator.go". //template:begin import
+
+func (r *BFDTemplateResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
+ resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp)
+
+ helpers.SetFlagImporting(ctx, true, resp.Private, &resp.Diagnostics)
+}
+
+// End of section. //template:end import
+
+// Section below is generated&owned by "gen/generator.go". //template:begin createSubresources
+
+// End of section. //template:end createSubresources
+
+// Section below is generated&owned by "gen/generator.go". //template:begin deleteSubresources
+
+// End of section. //template:end deleteSubresources
+
+// Section below is generated&owned by "gen/generator.go". //template:begin updateSubresources
+
+// End of section. //template:end updateSubresources
diff --git a/internal/provider/resource_fmc_bfd_template_test.go b/internal/provider/resource_fmc_bfd_template_test.go
new file mode 100644
index 00000000..6e89f67a
--- /dev/null
+++ b/internal/provider/resource_fmc_bfd_template_test.go
@@ -0,0 +1,105 @@
+// Copyright © 2023 Cisco Systems, Inc. and its affiliates.
+// All rights reserved.
+//
+// Licensed under the Mozilla Public License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://mozilla.org/MPL/2.0/
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// SPDX-License-Identifier: MPL-2.0
+
+package provider
+
+// Section below is generated&owned by "gen/generator.go". //template:begin imports
+import (
+ "os"
+ "testing"
+
+ "github.com/hashicorp/terraform-plugin-testing/helper/resource"
+)
+
+// End of section. //template:end imports
+
+// Section below is generated&owned by "gen/generator.go". //template:begin testAcc
+
+func TestAccFmcBFDTemplate(t *testing.T) {
+ var checks []resource.TestCheckFunc
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_bfd_template.test", "name", "BFD_Template1"))
+ checks = append(checks, resource.TestCheckResourceAttrSet("fmc_bfd_template.test", "type"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_bfd_template.test", "hop_type", "SINGLE_HOP"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_bfd_template.test", "echo", "ENABLED"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_bfd_template.test", "interval_time", "MILLISECONDS"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_bfd_template.test", "min_transmit", "300"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_bfd_template.test", "tx_rx_multiplier", "3"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_bfd_template.test", "min_receive", "300"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_bfd_template.test", "authentication_password", "Cisco123!"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_bfd_template.test", "authentication_key_id", "1"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_bfd_template.test", "authentication_type", "MD5"))
+
+ var steps []resource.TestStep
+ if os.Getenv("SKIP_MINIMUM_TEST") == "" {
+ steps = append(steps, resource.TestStep{
+ Config: testAccFmcBFDTemplateConfig_minimum(),
+ })
+ }
+ steps = append(steps, resource.TestStep{
+ Config: testAccFmcBFDTemplateConfig_all(),
+ Check: resource.ComposeTestCheckFunc(checks...),
+ })
+ steps = append(steps, resource.TestStep{
+ ResourceName: "fmc_bfd_template.test",
+ ImportState: true,
+ })
+
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { testAccPreCheck(t) },
+ ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
+ ErrorCheck: func(err error) error { return testAccErrorCheck(t, err) },
+ Steps: steps,
+ })
+}
+
+// End of section. //template:end testAcc
+
+// Section below is generated&owned by "gen/generator.go". //template:begin testPrerequisites
+// End of section. //template:end testPrerequisites
+
+// Section below is generated&owned by "gen/generator.go". //template:begin testAccConfigMinimal
+
+func testAccFmcBFDTemplateConfig_minimum() string {
+ config := `resource "fmc_bfd_template" "test" {` + "\n"
+ config += ` name = "BFD_Template1"` + "\n"
+ config += ` hop_type = "SINGLE_HOP"` + "\n"
+ config += ` echo = "ENABLED"` + "\n"
+ config += `}` + "\n"
+ return config
+}
+
+// End of section. //template:end testAccConfigMinimal
+
+// Section below is generated&owned by "gen/generator.go". //template:begin testAccConfigAll
+
+func testAccFmcBFDTemplateConfig_all() string {
+ config := `resource "fmc_bfd_template" "test" {` + "\n"
+ config += ` name = "BFD_Template1"` + "\n"
+ config += ` hop_type = "SINGLE_HOP"` + "\n"
+ config += ` echo = "ENABLED"` + "\n"
+ config += ` interval_time = "MILLISECONDS"` + "\n"
+ config += ` min_transmit = 300` + "\n"
+ config += ` tx_rx_multiplier = 3` + "\n"
+ config += ` min_receive = 300` + "\n"
+ config += ` authentication_password = "Cisco123!"` + "\n"
+ config += ` authentication_key_id = 1` + "\n"
+ config += ` authentication_type = "MD5"` + "\n"
+ config += `}` + "\n"
+ return config
+}
+
+// End of section. //template:end testAccConfigAll
diff --git a/internal/provider/resource_fmc_bgd_template.go b/internal/provider/resource_fmc_bgd_template.go
new file mode 100644
index 00000000..dce160a8
--- /dev/null
+++ b/internal/provider/resource_fmc_bgd_template.go
@@ -0,0 +1,329 @@
+// Copyright © 2023 Cisco Systems, Inc. and its affiliates.
+// All rights reserved.
+//
+// Licensed under the Mozilla Public License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://mozilla.org/MPL/2.0/
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// SPDX-License-Identifier: MPL-2.0
+
+package provider
+
+// Section below is generated&owned by "gen/generator.go". //template:begin imports
+import (
+ "context"
+ "fmt"
+ "net/url"
+ "strings"
+
+ "github.com/hashicorp/terraform-plugin-framework-validators/int64validator"
+ "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/int64default"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
+ "github.com/hashicorp/terraform-plugin-framework/schema/validator"
+ "github.com/hashicorp/terraform-plugin-framework/types"
+ "github.com/hashicorp/terraform-plugin-log/tflog"
+ "github.com/netascode/go-fmc"
+ "github.com/netascode/terraform-provider-fmc/internal/provider/helpers"
+)
+
+// End of section. //template:end imports
+
+// Section below is generated&owned by "gen/generator.go". //template:begin model
+
+// Ensure provider defined types fully satisfy framework interfaces
+var (
+ _ resource.Resource = &BGDTemplateResource{}
+ _ resource.ResourceWithImportState = &BGDTemplateResource{}
+)
+
+func NewBGDTemplateResource() resource.Resource {
+ return &BGDTemplateResource{}
+}
+
+type BGDTemplateResource struct {
+ client *fmc.Client
+}
+
+func (r *BGDTemplateResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
+ resp.TypeName = req.ProviderTypeName + "_bgd_template"
+}
+
+func (r *BGDTemplateResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
+ resp.Schema = schema.Schema{
+ // This description is used by the documentation generator and the language server.
+ MarkdownDescription: helpers.NewAttributeDescription("This resource can manage a BGD Template.").String,
+
+ Attributes: map[string]schema.Attribute{
+ "id": schema.StringAttribute{
+ MarkdownDescription: "The id of the object",
+ Computed: true,
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.UseStateForUnknown(),
+ },
+ },
+ "domain": schema.StringAttribute{
+ MarkdownDescription: "The name of the FMC domain",
+ Optional: true,
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.RequiresReplace(),
+ },
+ },
+ "name": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("The name of the host object.").String,
+ Required: true,
+ },
+ "type": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Type of the object; this value is always 'BFDTemplate'.").String,
+ Computed: true,
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.UseStateForUnknown(),
+ },
+ },
+ "hop_type": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("SINGLE_HOP | MULTI_HOP").String,
+ Required: true,
+ },
+ "echo": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("(ENABLED | DISABLED)").String,
+ Required: true,
+ },
+ "interval_time": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("(MILLISECONDS | MICROSECONDS | NONE)").String,
+ Required: true,
+ },
+ "min_transmit": schema.Int64Attribute{
+ MarkdownDescription: helpers.NewAttributeDescription("BFD Minimum Transmit").AddIntegerRangeDescription(50000, 999000).AddDefaultValueDescription("100000").String,
+ Optional: true,
+ Computed: true,
+ Validators: []validator.Int64{
+ int64validator.Between(50000, 999000),
+ },
+ Default: int64default.StaticInt64(100000),
+ },
+ "tx_rx_multiplier": schema.Int64Attribute{
+ MarkdownDescription: helpers.NewAttributeDescription("BFD Multipler").AddIntegerRangeDescription(3, 50).AddDefaultValueDescription("3").String,
+ Optional: true,
+ Computed: true,
+ Validators: []validator.Int64{
+ int64validator.Between(3, 50),
+ },
+ Default: int64default.StaticInt64(3),
+ },
+ "min_receive": schema.Int64Attribute{
+ MarkdownDescription: helpers.NewAttributeDescription("BFD Minimum Receive").AddIntegerRangeDescription(50000, 999000).AddDefaultValueDescription("100000").String,
+ Optional: true,
+ Computed: true,
+ Validators: []validator.Int64{
+ int64validator.Between(50000, 999000),
+ },
+ Default: int64default.StaticInt64(100000),
+ },
+ },
+ }
+}
+
+func (r *BGDTemplateResource) Configure(_ context.Context, req resource.ConfigureRequest, _ *resource.ConfigureResponse) {
+ if req.ProviderData == nil {
+ return
+ }
+
+ r.client = req.ProviderData.(*FmcProviderData).Client
+}
+
+// End of section. //template:end model
+
+// Section below is generated&owned by "gen/generator.go". //template:begin create
+
+func (r *BGDTemplateResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
+ var plan BGDTemplate
+
+ // Read plan
+ diags := req.Plan.Get(ctx, &plan)
+ if resp.Diagnostics.Append(diags...); resp.Diagnostics.HasError() {
+ return
+ }
+
+ // Set request domain if provided
+ reqMods := [](func(*fmc.Req)){}
+ if !plan.Domain.IsNull() && plan.Domain.ValueString() != "" {
+ reqMods = append(reqMods, fmc.DomainName(plan.Domain.ValueString()))
+ }
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Beginning Create", plan.Id.ValueString()))
+
+ // Create object
+ body := plan.toBody(ctx, BGDTemplate{})
+ res, err := r.client.Post(plan.getPath(), body, reqMods...)
+ if err != nil {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to configure object (POST/PUT), got error: %s, %s", err, res.String()))
+ return
+ }
+ plan.Id = types.StringValue(res.Get("id").String())
+ plan.fromBodyUnknowns(ctx, res)
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Create finished successfully", plan.Id.ValueString()))
+
+ diags = resp.State.Set(ctx, &plan)
+ resp.Diagnostics.Append(diags...)
+
+ helpers.SetFlagImporting(ctx, false, resp.Private, &resp.Diagnostics)
+}
+
+// End of section. //template:end create
+
+// Section below is generated&owned by "gen/generator.go". //template:begin read
+
+func (r *BGDTemplateResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
+ var state BGDTemplate
+
+ // Read state
+ diags := req.State.Get(ctx, &state)
+ if resp.Diagnostics.Append(diags...); resp.Diagnostics.HasError() {
+ return
+ }
+
+ // Set request domain if provided
+ reqMods := [](func(*fmc.Req)){}
+ if !state.Domain.IsNull() && state.Domain.ValueString() != "" {
+ reqMods = append(reqMods, fmc.DomainName(state.Domain.ValueString()))
+ }
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Beginning Read", state.Id.String()))
+
+ urlPath := state.getPath() + "/" + url.QueryEscape(state.Id.ValueString())
+ res, err := r.client.Get(urlPath, reqMods...)
+
+ if err != nil && strings.Contains(err.Error(), "StatusCode 404") {
+ resp.State.RemoveResource(ctx)
+ return
+ } else if err != nil {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to retrieve object (GET), got error: %s, %s", err, res.String()))
+ return
+ }
+
+ imp, diags := helpers.IsFlagImporting(ctx, req)
+ if resp.Diagnostics.Append(diags...); resp.Diagnostics.HasError() {
+ return
+ }
+
+ // After `terraform import` we switch to a full read.
+ if imp {
+ state.fromBody(ctx, res)
+ } else {
+ state.fromBodyPartial(ctx, res)
+ }
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Read finished successfully", state.Id.ValueString()))
+
+ diags = resp.State.Set(ctx, &state)
+ resp.Diagnostics.Append(diags...)
+
+ helpers.SetFlagImporting(ctx, false, resp.Private, &resp.Diagnostics)
+}
+
+// End of section. //template:end read
+
+// Section below is generated&owned by "gen/generator.go". //template:begin update
+
+func (r *BGDTemplateResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
+ var plan, state BGDTemplate
+
+ // Read plan
+ diags := req.Plan.Get(ctx, &plan)
+ if resp.Diagnostics.Append(diags...); resp.Diagnostics.HasError() {
+ return
+ }
+
+ // Read state
+ diags = req.State.Get(ctx, &state)
+ if resp.Diagnostics.Append(diags...); resp.Diagnostics.HasError() {
+ return
+ }
+
+ // Set request domain if provided
+ reqMods := [](func(*fmc.Req)){}
+ if !plan.Domain.IsNull() && plan.Domain.ValueString() != "" {
+ reqMods = append(reqMods, fmc.DomainName(plan.Domain.ValueString()))
+ }
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Beginning Update", plan.Id.ValueString()))
+
+ body := plan.toBody(ctx, state)
+ res, err := r.client.Put(plan.getPath()+"/"+url.QueryEscape(plan.Id.ValueString()), body, reqMods...)
+ if err != nil {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to configure object (PUT), got error: %s, %s", err, res.String()))
+ return
+ }
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Update finished successfully", plan.Id.ValueString()))
+
+ diags = resp.State.Set(ctx, &plan)
+ resp.Diagnostics.Append(diags...)
+}
+
+// End of section. //template:end update
+
+// Section below is generated&owned by "gen/generator.go". //template:begin delete
+
+func (r *BGDTemplateResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
+ var state BGDTemplate
+
+ // Read state
+ diags := req.State.Get(ctx, &state)
+ if resp.Diagnostics.Append(diags...); resp.Diagnostics.HasError() {
+ return
+ }
+
+ // Set request domain if provided
+ reqMods := [](func(*fmc.Req)){}
+ if !state.Domain.IsNull() && state.Domain.ValueString() != "" {
+ reqMods = append(reqMods, fmc.DomainName(state.Domain.ValueString()))
+ }
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Beginning Delete", state.Id.ValueString()))
+ res, err := r.client.Delete(state.getPath()+"/"+url.QueryEscape(state.Id.ValueString()), reqMods...)
+ if err != nil {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to delete object (DELETE), got error: %s, %s", err, res.String()))
+ return
+ }
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Delete finished successfully", state.Id.ValueString()))
+
+ resp.State.RemoveResource(ctx)
+}
+
+// End of section. //template:end delete
+
+// Section below is generated&owned by "gen/generator.go". //template:begin import
+
+func (r *BGDTemplateResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
+ resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp)
+
+ helpers.SetFlagImporting(ctx, true, resp.Private, &resp.Diagnostics)
+}
+
+// End of section. //template:end import
+
+// Section below is generated&owned by "gen/generator.go". //template:begin createSubresources
+
+// End of section. //template:end createSubresources
+
+// Section below is generated&owned by "gen/generator.go". //template:begin deleteSubresources
+
+// End of section. //template:end deleteSubresources
+
+// Section below is generated&owned by "gen/generator.go". //template:begin updateSubresources
+
+// End of section. //template:end updateSubresources
diff --git a/internal/provider/resource_fmc_bgd_template_test.go b/internal/provider/resource_fmc_bgd_template_test.go
new file mode 100644
index 00000000..dde82b68
--- /dev/null
+++ b/internal/provider/resource_fmc_bgd_template_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
+
+package provider
+
+// Section below is generated&owned by "gen/generator.go". //template:begin imports
+import (
+ "os"
+ "testing"
+
+ "github.com/hashicorp/terraform-plugin-testing/helper/resource"
+)
+
+// End of section. //template:end imports
+
+// Section below is generated&owned by "gen/generator.go". //template:begin testAcc
+
+func TestAccFmcBGDTemplate(t *testing.T) {
+ var checks []resource.TestCheckFunc
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_bgd_template.test", "name", "BFD_Template1"))
+ checks = append(checks, resource.TestCheckResourceAttrSet("fmc_bgd_template.test", "type"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_bgd_template.test", "hop_type", "SINGLE_HOP"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_bgd_template.test", "echo", "ENABLED"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_bgd_template.test", "interval_time", "MILLISECONDS"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_bgd_template.test", "min_transmit", "100000"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_bgd_template.test", "tx_rx_multiplier", "3"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_bgd_template.test", "min_receive", "100000"))
+
+ var steps []resource.TestStep
+ if os.Getenv("SKIP_MINIMUM_TEST") == "" {
+ steps = append(steps, resource.TestStep{
+ Config: testAccFmcBGDTemplateConfig_minimum(),
+ })
+ }
+ steps = append(steps, resource.TestStep{
+ Config: testAccFmcBGDTemplateConfig_all(),
+ Check: resource.ComposeTestCheckFunc(checks...),
+ })
+ steps = append(steps, resource.TestStep{
+ ResourceName: "fmc_bgd_template.test",
+ ImportState: true,
+ })
+
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { testAccPreCheck(t) },
+ ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
+ Steps: steps,
+ })
+}
+
+// End of section. //template:end testAcc
+
+// Section below is generated&owned by "gen/generator.go". //template:begin testPrerequisites
+// End of section. //template:end testPrerequisites
+
+// Section below is generated&owned by "gen/generator.go". //template:begin testAccConfigMinimal
+
+func testAccFmcBGDTemplateConfig_minimum() string {
+ config := `resource "fmc_bgd_template" "test" {` + "\n"
+ config += ` name = "BFD_Template1"` + "\n"
+ config += ` hop_type = "SINGLE_HOP"` + "\n"
+ config += ` echo = "ENABLED"` + "\n"
+ config += ` interval_time = "MILLISECONDS"` + "\n"
+ config += `}` + "\n"
+ return config
+}
+
+// End of section. //template:end testAccConfigMinimal
+
+// Section below is generated&owned by "gen/generator.go". //template:begin testAccConfigAll
+
+func testAccFmcBGDTemplateConfig_all() string {
+ config := `resource "fmc_bgd_template" "test" {` + "\n"
+ config += ` name = "BFD_Template1"` + "\n"
+ config += ` hop_type = "SINGLE_HOP"` + "\n"
+ config += ` echo = "ENABLED"` + "\n"
+ config += ` interval_time = "MILLISECONDS"` + "\n"
+ config += ` min_transmit = 100000` + "\n"
+ config += ` tx_rx_multiplier = 3` + "\n"
+ config += ` min_receive = 100000` + "\n"
+ config += `}` + "\n"
+ return config
+}
+
+// End of section. //template:end testAccConfigAll
diff --git a/internal/provider/resource_fmc_device.go b/internal/provider/resource_fmc_device.go
index 754b9f39..07fc1326 100644
--- a/internal/provider/resource_fmc_device.go
+++ b/internal/provider/resource_fmc_device.go
@@ -113,9 +113,6 @@ func (r *DeviceResource) Schema(ctx context.Context, req resource.SchemaRequest,
Optional: true,
Computed: true,
Default: stringdefault.StaticString("Device"),
- PlanModifiers: []planmodifier.String{
- stringplanmodifier.RequiresReplace(),
- },
},
"access_policy_id": schema.StringAttribute{
MarkdownDescription: helpers.NewAttributeDescription("The UUID of the assigned access control policy. For example `fmc_access_control_policy.example.id`.").String,
diff --git a/internal/provider/resource_fmc_device_bfd.go b/internal/provider/resource_fmc_device_bfd.go
new file mode 100644
index 00000000..8a3b2f14
--- /dev/null
+++ b/internal/provider/resource_fmc_device_bfd.go
@@ -0,0 +1,340 @@
+// Copyright © 2023 Cisco Systems, Inc. and its affiliates.
+// All rights reserved.
+//
+// Licensed under the Mozilla Public License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://mozilla.org/MPL/2.0/
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// SPDX-License-Identifier: MPL-2.0
+
+package provider
+
+// Section below is generated&owned by "gen/generator.go". //template:begin imports
+import (
+ "context"
+ "fmt"
+ "net/url"
+ "strings"
+
+ "github.com/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/int64default"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
+ "github.com/hashicorp/terraform-plugin-framework/schema/validator"
+ "github.com/hashicorp/terraform-plugin-framework/types"
+ "github.com/hashicorp/terraform-plugin-log/tflog"
+ "github.com/netascode/go-fmc"
+ "github.com/netascode/terraform-provider-fmc/internal/provider/helpers"
+)
+
+// End of section. //template:end imports
+
+// Section below is generated&owned by "gen/generator.go". //template:begin model
+
+// Ensure provider defined types fully satisfy framework interfaces
+var (
+ _ resource.Resource = &DeviceBFDResource{}
+ _ resource.ResourceWithImportState = &DeviceBFDResource{}
+)
+
+func NewDeviceBFDResource() resource.Resource {
+ return &DeviceBFDResource{}
+}
+
+type DeviceBFDResource struct {
+ client *fmc.Client
+}
+
+func (r *DeviceBFDResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
+ resp.TypeName = req.ProviderTypeName + "_device_bfd"
+}
+
+func (r *DeviceBFDResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
+ resp.Schema = schema.Schema{
+ // This description is used by the documentation generator and the language server.
+ MarkdownDescription: helpers.NewAttributeDescription("This resource can manage a Device BFD.").String,
+
+ Attributes: map[string]schema.Attribute{
+ "id": schema.StringAttribute{
+ MarkdownDescription: "The id of the object",
+ Computed: true,
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.UseStateForUnknown(),
+ },
+ },
+ "domain": schema.StringAttribute{
+ MarkdownDescription: "The name of the FMC domain",
+ Optional: true,
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.RequiresReplace(),
+ },
+ },
+ "device_id": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("UUID of the parent device (fmc_device.example.id).").String,
+ Required: true,
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.RequiresReplace(),
+ },
+ },
+ "type": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Type of the object; this value is always 'BFDPolicy'").String,
+ Computed: true,
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.UseStateForUnknown(),
+ },
+ },
+ "hop_type": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("BFD Hop type.").AddStringEnumDescription("SINGLE_HOP", "MULTI_HOP").String,
+ Required: true,
+ Validators: []validator.String{
+ stringvalidator.OneOf("SINGLE_HOP", "MULTI_HOP"),
+ },
+ },
+ "bfd_template_id": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("ID of the BFD Template").String,
+ Required: true,
+ },
+ "interface_logical_name": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Logical Name of the interface of BFD assignment if SINGLE_HOP selected.").String,
+ Optional: true,
+ },
+ "destination_host_object_id": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("The ID of the destination host object if MULTI_HOP selected.").String,
+ Optional: true,
+ },
+ "source_host_object_id": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("The ID of the source host object if MULTI_HOP selected.").String,
+ Optional: true,
+ },
+ "interface_id": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("ID of the interface of BFD assignment if SINGLE_HOP selected.").String,
+ Optional: true,
+ },
+ "slow_timer": schema.Int64Attribute{
+ MarkdownDescription: helpers.NewAttributeDescription("BFD Slow Timer value in range: 1000-30000, default: 1000").AddIntegerRangeDescription(1000, 30000).AddDefaultValueDescription("1000").String,
+ Optional: true,
+ Computed: true,
+ Validators: []validator.Int64{
+ int64validator.Between(1000, 30000),
+ },
+ Default: int64default.StaticInt64(1000),
+ },
+ },
+ }
+}
+
+func (r *DeviceBFDResource) Configure(_ context.Context, req resource.ConfigureRequest, _ *resource.ConfigureResponse) {
+ if req.ProviderData == nil {
+ return
+ }
+
+ r.client = req.ProviderData.(*FmcProviderData).Client
+}
+
+// End of section. //template:end model
+
+// Section below is generated&owned by "gen/generator.go". //template:begin create
+
+func (r *DeviceBFDResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
+ var plan DeviceBFD
+
+ // Read plan
+ diags := req.Plan.Get(ctx, &plan)
+ if resp.Diagnostics.Append(diags...); resp.Diagnostics.HasError() {
+ return
+ }
+
+ // Set request domain if provided
+ reqMods := [](func(*fmc.Req)){}
+ if !plan.Domain.IsNull() && plan.Domain.ValueString() != "" {
+ reqMods = append(reqMods, fmc.DomainName(plan.Domain.ValueString()))
+ }
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Beginning Create", plan.Id.ValueString()))
+
+ // Create object
+ body := plan.toBody(ctx, DeviceBFD{})
+ res, err := r.client.Post(plan.getPath(), body, reqMods...)
+ if err != nil {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to configure object (POST/PUT), got error: %s, %s", err, res.String()))
+ return
+ }
+ plan.Id = types.StringValue(res.Get("id").String())
+ plan.fromBodyUnknowns(ctx, res)
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Create finished successfully", plan.Id.ValueString()))
+
+ diags = resp.State.Set(ctx, &plan)
+ resp.Diagnostics.Append(diags...)
+
+ helpers.SetFlagImporting(ctx, false, resp.Private, &resp.Diagnostics)
+}
+
+// End of section. //template:end create
+
+// Section below is generated&owned by "gen/generator.go". //template:begin read
+
+func (r *DeviceBFDResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
+ var state DeviceBFD
+
+ // Read state
+ diags := req.State.Get(ctx, &state)
+ if resp.Diagnostics.Append(diags...); resp.Diagnostics.HasError() {
+ return
+ }
+
+ // Set request domain if provided
+ reqMods := [](func(*fmc.Req)){}
+ if !state.Domain.IsNull() && state.Domain.ValueString() != "" {
+ reqMods = append(reqMods, fmc.DomainName(state.Domain.ValueString()))
+ }
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Beginning Read", state.Id.String()))
+
+ urlPath := state.getPath() + "/" + url.QueryEscape(state.Id.ValueString())
+ res, err := r.client.Get(urlPath, reqMods...)
+
+ if err != nil && strings.Contains(err.Error(), "StatusCode 404") {
+ resp.State.RemoveResource(ctx)
+ return
+ } else if err != nil {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to retrieve object (GET), got error: %s, %s", err, res.String()))
+ return
+ }
+
+ imp, diags := helpers.IsFlagImporting(ctx, req)
+ if resp.Diagnostics.Append(diags...); resp.Diagnostics.HasError() {
+ return
+ }
+
+ // After `terraform import` we switch to a full read.
+ if imp {
+ state.fromBody(ctx, res)
+ } else {
+ state.fromBodyPartial(ctx, res)
+ }
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Read finished successfully", state.Id.ValueString()))
+
+ diags = resp.State.Set(ctx, &state)
+ resp.Diagnostics.Append(diags...)
+
+ helpers.SetFlagImporting(ctx, false, resp.Private, &resp.Diagnostics)
+}
+
+// End of section. //template:end read
+
+// Section below is generated&owned by "gen/generator.go". //template:begin update
+
+func (r *DeviceBFDResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
+ var plan, state DeviceBFD
+
+ // Read plan
+ diags := req.Plan.Get(ctx, &plan)
+ if resp.Diagnostics.Append(diags...); resp.Diagnostics.HasError() {
+ return
+ }
+
+ // Read state
+ diags = req.State.Get(ctx, &state)
+ if resp.Diagnostics.Append(diags...); resp.Diagnostics.HasError() {
+ return
+ }
+
+ // Set request domain if provided
+ reqMods := [](func(*fmc.Req)){}
+ if !plan.Domain.IsNull() && plan.Domain.ValueString() != "" {
+ reqMods = append(reqMods, fmc.DomainName(plan.Domain.ValueString()))
+ }
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Beginning Update", plan.Id.ValueString()))
+
+ body := plan.toBody(ctx, state)
+ res, err := r.client.Put(plan.getPath()+"/"+url.QueryEscape(plan.Id.ValueString()), body, reqMods...)
+ if err != nil {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to configure object (PUT), got error: %s, %s", err, res.String()))
+ return
+ }
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Update finished successfully", plan.Id.ValueString()))
+
+ diags = resp.State.Set(ctx, &plan)
+ resp.Diagnostics.Append(diags...)
+}
+
+// End of section. //template:end update
+
+// Section below is generated&owned by "gen/generator.go". //template:begin delete
+
+func (r *DeviceBFDResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
+ var state DeviceBFD
+
+ // Read state
+ diags := req.State.Get(ctx, &state)
+ if resp.Diagnostics.Append(diags...); resp.Diagnostics.HasError() {
+ return
+ }
+
+ // Set request domain if provided
+ reqMods := [](func(*fmc.Req)){}
+ if !state.Domain.IsNull() && state.Domain.ValueString() != "" {
+ reqMods = append(reqMods, fmc.DomainName(state.Domain.ValueString()))
+ }
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Beginning Delete", state.Id.ValueString()))
+ res, err := r.client.Delete(state.getPath()+"/"+url.QueryEscape(state.Id.ValueString()), reqMods...)
+ if err != nil {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to delete object (DELETE), got error: %s, %s", err, res.String()))
+ return
+ }
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Delete finished successfully", state.Id.ValueString()))
+
+ resp.State.RemoveResource(ctx)
+}
+
+// End of section. //template:end delete
+
+// Section below is generated&owned by "gen/generator.go". //template:begin import
+
+func (r *DeviceBFDResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
+ idParts := strings.Split(req.ID, ",")
+
+ if len(idParts) != 2 || idParts[0] == "" || idParts[1] == "" {
+ resp.Diagnostics.AddError(
+ "Unexpected Import Identifier",
+ fmt.Sprintf("Expected import identifier with format: ,. Got: %q", req.ID),
+ )
+ return
+ }
+ resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("device_id"), idParts[0])...)
+ resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("id"), idParts[1])...)
+
+ helpers.SetFlagImporting(ctx, true, resp.Private, &resp.Diagnostics)
+}
+
+// End of section. //template:end import
+
+// Section below is generated&owned by "gen/generator.go". //template:begin createSubresources
+
+// End of section. //template:end createSubresources
+
+// Section below is generated&owned by "gen/generator.go". //template:begin deleteSubresources
+
+// End of section. //template:end deleteSubresources
+
+// Section below is generated&owned by "gen/generator.go". //template:begin updateSubresources
+
+// End of section. //template:end updateSubresources
diff --git a/internal/provider/resource_fmc_device_bfd_test.go b/internal/provider/resource_fmc_device_bfd_test.go
new file mode 100644
index 00000000..5646ad9e
--- /dev/null
+++ b/internal/provider/resource_fmc_device_bfd_test.go
@@ -0,0 +1,104 @@
+// Copyright © 2023 Cisco Systems, Inc. and its affiliates.
+// All rights reserved.
+//
+// Licensed under the Mozilla Public License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://mozilla.org/MPL/2.0/
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// SPDX-License-Identifier: MPL-2.0
+
+package provider
+
+// Section below is generated&owned by "gen/generator.go". //template:begin imports
+import (
+ "os"
+ "testing"
+
+ "github.com/hashicorp/terraform-plugin-testing/helper/resource"
+)
+
+// End of section. //template:end imports
+
+// Section below is generated&owned by "gen/generator.go". //template:begin testAcc
+
+func TestAccFmcDeviceBFD(t *testing.T) {
+ if os.Getenv("TF_VAR_device_id") == "" {
+ t.Skip("skipping test, set environment variable TF_VAR_device_id")
+ }
+ var checks []resource.TestCheckFunc
+ checks = append(checks, resource.TestCheckResourceAttrSet("fmc_device_bfd.test", "type"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_bfd.test", "hop_type", "SINGLE_HOP"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_bfd.test", "bfd_template_id", "76d24097-41c4-4558-a4d0-a8c07ac08470"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_bfd.test", "interface_logical_name", "outside"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_bfd.test", "destination_host_object_id", "76d24097-41c4-4558-a4d0-a8c07ac08470"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_bfd.test", "source_host_object_id", "76d24097-41c4-4558-a4d0-a8c07ac08470"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_bfd.test", "interface_id", "76d24097-41c4-4558-a4d0-a8c07ac08470"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_bfd.test", "slow_timer", ""))
+
+ var steps []resource.TestStep
+ if os.Getenv("SKIP_MINIMUM_TEST") == "" {
+ steps = append(steps, resource.TestStep{
+ Config: testAccFmcDeviceBFDPrerequisitesConfig + testAccFmcDeviceBFDConfig_minimum(),
+ })
+ }
+ steps = append(steps, resource.TestStep{
+ Config: testAccFmcDeviceBFDPrerequisitesConfig + testAccFmcDeviceBFDConfig_all(),
+ Check: resource.ComposeTestCheckFunc(checks...),
+ })
+
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { testAccPreCheck(t) },
+ ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
+ ErrorCheck: func(err error) error { return testAccErrorCheck(t, err) },
+ Steps: steps,
+ })
+}
+
+// End of section. //template:end testAcc
+
+// Section below is generated&owned by "gen/generator.go". //template:begin testPrerequisites
+
+const testAccFmcDeviceBFDPrerequisitesConfig = `
+variable "device_id" { default = null } // tests will set $TF_VAR_device_id
+`
+
+// End of section. //template:end testPrerequisites
+
+// Section below is generated&owned by "gen/generator.go". //template:begin testAccConfigMinimal
+
+func testAccFmcDeviceBFDConfig_minimum() string {
+ config := `resource "fmc_device_bfd" "test" {` + "\n"
+ config += ` device_id = var.device_id` + "\n"
+ config += ` hop_type = "SINGLE_HOP"` + "\n"
+ config += ` bfd_template_id = "76d24097-41c4-4558-a4d0-a8c07ac08470"` + "\n"
+ config += `}` + "\n"
+ return config
+}
+
+// End of section. //template:end testAccConfigMinimal
+
+// Section below is generated&owned by "gen/generator.go". //template:begin testAccConfigAll
+
+func testAccFmcDeviceBFDConfig_all() string {
+ config := `resource "fmc_device_bfd" "test" {` + "\n"
+ config += ` device_id = var.device_id` + "\n"
+ config += ` hop_type = "SINGLE_HOP"` + "\n"
+ config += ` bfd_template_id = "76d24097-41c4-4558-a4d0-a8c07ac08470"` + "\n"
+ config += ` interface_logical_name = "outside"` + "\n"
+ config += ` destination_host_object_id = "76d24097-41c4-4558-a4d0-a8c07ac08470"` + "\n"
+ config += ` source_host_object_id = "76d24097-41c4-4558-a4d0-a8c07ac08470"` + "\n"
+ config += ` interface_id = "76d24097-41c4-4558-a4d0-a8c07ac08470"` + "\n"
+ config += ` slow_timer = ` + "\n"
+ config += `}` + "\n"
+ return config
+}
+
+// End of section. //template:end testAccConfigAll
diff --git a/internal/provider/resource_fmc_device_bgp.go b/internal/provider/resource_fmc_device_bgp.go
new file mode 100644
index 00000000..548352f3
--- /dev/null
+++ b/internal/provider/resource_fmc_device_bgp.go
@@ -0,0 +1,812 @@
+// Copyright © 2023 Cisco Systems, Inc. and its affiliates.
+// All rights reserved.
+//
+// Licensed under the Mozilla Public License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://mozilla.org/MPL/2.0/
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// SPDX-License-Identifier: MPL-2.0
+
+package provider
+
+// Section below is generated&owned by "gen/generator.go". //template:begin imports
+import (
+ "context"
+ "fmt"
+ "net/url"
+ "strings"
+
+ "github.com/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/booldefault"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/int64default"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringdefault"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
+ "github.com/hashicorp/terraform-plugin-framework/schema/validator"
+ "github.com/hashicorp/terraform-plugin-framework/types"
+ "github.com/hashicorp/terraform-plugin-log/tflog"
+ "github.com/netascode/go-fmc"
+ "github.com/netascode/terraform-provider-fmc/internal/provider/helpers"
+)
+
+// End of section. //template:end imports
+
+// Section below is generated&owned by "gen/generator.go". //template:begin model
+
+// Ensure provider defined types fully satisfy framework interfaces
+var (
+ _ resource.Resource = &DeviceBGPResource{}
+ _ resource.ResourceWithImportState = &DeviceBGPResource{}
+)
+
+func NewDeviceBGPResource() resource.Resource {
+ return &DeviceBGPResource{}
+}
+
+type DeviceBGPResource struct {
+ client *fmc.Client
+}
+
+func (r *DeviceBGPResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
+ resp.TypeName = req.ProviderTypeName + "_device_bgp"
+}
+
+func (r *DeviceBGPResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
+ resp.Schema = schema.Schema{
+ // This description is used by the documentation generator and the language server.
+ MarkdownDescription: helpers.NewAttributeDescription("Under BGP General Settings, BGP has to be enabled and AS Number assigned first.").String,
+
+ Attributes: map[string]schema.Attribute{
+ "id": schema.StringAttribute{
+ MarkdownDescription: "The id of the object",
+ Computed: true,
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.UseStateForUnknown(),
+ },
+ },
+ "domain": schema.StringAttribute{
+ MarkdownDescription: "The name of the FMC domain",
+ Optional: true,
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.RequiresReplace(),
+ },
+ },
+ "device_id": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("UUID of the parent device (fmc_device.example.id).").String,
+ Required: true,
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.RequiresReplace(),
+ },
+ },
+ "name": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Name of the object; this is always 'bgp'").String,
+ Computed: true,
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.UseStateForUnknown(),
+ },
+ },
+ "type": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Type of the object; this is always 'bgp'").String,
+ Computed: true,
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.UseStateForUnknown(),
+ },
+ },
+ "as_number": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Autonomus System (AS) Number").String,
+ Computed: true,
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.UseStateForUnknown(),
+ },
+ },
+ "ipv4_address_family_type": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("").String,
+ Computed: true,
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.UseStateForUnknown(),
+ },
+ },
+ "ipv4_learned_route_map_id": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Learned Route Map ID").String,
+ Optional: true,
+ },
+ "ipv4_default_information_orginate": schema.BoolAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Generate default routes").String,
+ Optional: true,
+ },
+ "ipv4_auto_aummary": schema.BoolAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Summarize subnet routes into network level routes").String,
+ Optional: true,
+ },
+ "ipv4_bgp_supress_inactive": schema.BoolAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Suppresing advertise inactive routes").String,
+ Optional: true,
+ },
+ "ipv4_synchronization": schema.BoolAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Synchronize between BGP and IGP systems").String,
+ Optional: true,
+ },
+ "ipv4_bgp_redistribute_internal": schema.BoolAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Redistribute IBGP into IGP. (Use filtering to limit the number of prefixes that are redistributed)").String,
+ Optional: true,
+ },
+ "ipv4_external_distance": schema.Int64Attribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Administrative route distance for external routes").AddIntegerRangeDescription(1, 255).AddDefaultValueDescription("20").String,
+ Optional: true,
+ Computed: true,
+ Validators: []validator.Int64{
+ int64validator.Between(1, 255),
+ },
+ Default: int64default.StaticInt64(20),
+ },
+ "ipv4_internal_distance": schema.Int64Attribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Administrative route distance for internal routes").AddIntegerRangeDescription(1, 255).AddDefaultValueDescription("200").String,
+ Optional: true,
+ Computed: true,
+ Validators: []validator.Int64{
+ int64validator.Between(1, 255),
+ },
+ Default: int64default.StaticInt64(200),
+ },
+ "ipv4_local_distance": schema.Int64Attribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Administrative route distance for local routes").AddIntegerRangeDescription(1, 255).AddDefaultValueDescription("200").String,
+ Optional: true,
+ Computed: true,
+ Validators: []validator.Int64{
+ int64validator.Between(1, 255),
+ },
+ Default: int64default.StaticInt64(200),
+ },
+ "ipv4_forward_packets_over_multipath_ibgp": schema.Int64Attribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Number of paths to use for IBGP").AddIntegerRangeDescription(1, 8).AddDefaultValueDescription("1").String,
+ Optional: true,
+ Computed: true,
+ Validators: []validator.Int64{
+ int64validator.Between(1, 8),
+ },
+ Default: int64default.StaticInt64(1),
+ },
+ "ipv4_forward_packets_over_multipath_ebgp": schema.Int64Attribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Number of paths to use for EBGP").AddIntegerRangeDescription(1, 8).AddDefaultValueDescription("1").String,
+ Optional: true,
+ Computed: true,
+ Validators: []validator.Int64{
+ int64validator.Between(1, 8),
+ },
+ Default: int64default.StaticInt64(1),
+ },
+ "ipv4_neighbors": schema.ListNestedAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("").String,
+ Optional: true,
+ NestedObject: schema.NestedAttributeObject{
+ Attributes: map[string]schema.Attribute{
+ "neighbor_address": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("IP address of the BGP neighbor").String,
+ Optional: true,
+ },
+ "neighbor_remote_as": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("AS number of the BGP neighbor").String,
+ Optional: true,
+ },
+ "neighbor_bfd": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("BFD Fallover").AddStringEnumDescription("SINGLE_HOP", "MULTI_HOP", "AUTO_DETECT_HOP", "NONE").AddDefaultValueDescription("NONE").String,
+ Optional: true,
+ Computed: true,
+ Validators: []validator.String{
+ stringvalidator.OneOf("SINGLE_HOP", "MULTI_HOP", "AUTO_DETECT_HOP", "NONE"),
+ },
+ Default: stringdefault.StaticString("NONE"),
+ },
+ "update_source_interface_id": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Interface ID for the update source").String,
+ Optional: true,
+ },
+ "enable_address_family": schema.BoolAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Enable IPv4 address family").AddDefaultValueDescription("false").String,
+ Optional: true,
+ Computed: true,
+ Default: booldefault.StaticBool(false),
+ },
+ "neighbor_shutdown": schema.BoolAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Shutdown administratively").AddDefaultValueDescription("false").String,
+ Optional: true,
+ Computed: true,
+ Default: booldefault.StaticBool(false),
+ },
+ "neighbor_description": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Description of the neighbor").String,
+ Optional: true,
+ },
+ "neighbor_filter_access_lists": schema.ListNestedAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("").String,
+ Optional: true,
+ NestedObject: schema.NestedAttributeObject{
+ Attributes: map[string]schema.Attribute{
+ "access_list_id": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Access List ID").String,
+ Optional: true,
+ },
+ "update_direction": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Filter direction").AddStringEnumDescription("IN", "OUT").String,
+ Optional: true,
+ Validators: []validator.String{
+ stringvalidator.OneOf("IN", "OUT"),
+ },
+ },
+ },
+ },
+ },
+ "neighbor_filter_route_map_lists": schema.ListNestedAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("").String,
+ Optional: true,
+ NestedObject: schema.NestedAttributeObject{
+ Attributes: map[string]schema.Attribute{
+ "route_map_id": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Route Map ID").String,
+ Optional: true,
+ },
+ "update_direction": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Filter direction").AddStringEnumDescription("IN", "OUT").String,
+ Optional: true,
+ Validators: []validator.String{
+ stringvalidator.OneOf("IN", "OUT"),
+ },
+ },
+ },
+ },
+ },
+ "neighbor_filter_prefix_lists": schema.ListNestedAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("").String,
+ Optional: true,
+ NestedObject: schema.NestedAttributeObject{
+ Attributes: map[string]schema.Attribute{
+ "prefix_list_id": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Route Map ID").String,
+ Optional: true,
+ },
+ "update_direction": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Filter direction").AddStringEnumDescription("IN", "OUT").String,
+ Optional: true,
+ Validators: []validator.String{
+ stringvalidator.OneOf("IN", "OUT"),
+ },
+ },
+ },
+ },
+ },
+ "neighbor_filter_as_path_lists": schema.ListNestedAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("").String,
+ Optional: true,
+ NestedObject: schema.NestedAttributeObject{
+ Attributes: map[string]schema.Attribute{
+ "update_direction": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Filter direction").AddStringEnumDescription("IN", "OUT").String,
+ Optional: true,
+ Validators: []validator.String{
+ stringvalidator.OneOf("IN", "OUT"),
+ },
+ },
+ "as_path_id": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("AS Path ID").String,
+ Optional: true,
+ },
+ },
+ },
+ },
+ "neighbor_filter_max_prefix": schema.Int64Attribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Maximum number of prefixes allowed from the neighbor").AddIntegerRangeDescription(1, 2147483647).String,
+ Optional: true,
+ Validators: []validator.Int64{
+ int64validator.Between(1, 2147483647),
+ },
+ },
+ "neighbor_filter_warning_only": schema.BoolAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Give only warning message when prefix limit exceeded or terminate peering when prefix limit is exceeded.").String,
+ Optional: true,
+ },
+ "neighbor_filter_threshold_value": schema.Int64Attribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Threshold value for the maximum number of prefixes allowed from the neighbor").AddIntegerRangeDescription(1, 100).String,
+ Optional: true,
+ Validators: []validator.Int64{
+ int64validator.Between(1, 100),
+ },
+ },
+ "neighbor_filter_restart_interval": schema.Int64Attribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Time interval to restart the maximum prefix limit in Minutes").AddIntegerRangeDescription(1, 65535).String,
+ Optional: true,
+ Validators: []validator.Int64{
+ int64validator.Between(1, 65535),
+ },
+ },
+ "neighbor_routes_advertisement_interval": schema.Int64Attribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Time interval to advertise routes in seconds").AddIntegerRangeDescription(0, 600).AddDefaultValueDescription("0").String,
+ Optional: true,
+ Computed: true,
+ Validators: []validator.Int64{
+ int64validator.Between(0, 600),
+ },
+ Default: int64default.StaticInt64(0),
+ },
+ "neighbor_routes_remove_private_as": schema.BoolAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Remove private AS numbers from outgoing routing updates").AddDefaultValueDescription("false").String,
+ Optional: true,
+ Computed: true,
+ Default: booldefault.StaticBool(false),
+ },
+ "neighbor_generate_default_route_map_id": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Generate default routes - Route Map").String,
+ Optional: true,
+ },
+ "neighbor_routes_advertise_map_use_exist": schema.BoolAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Use Exist Map or Non-Exist Map").String,
+ Optional: true,
+ },
+ "neighbor_routes_advertise_map_id": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Specified route maps are advertised when the prefix exists in the Advertise Map and Exist Map.").String,
+ Optional: true,
+ },
+ "neighbor_routes_advertise_exist_nonexist_map_id": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Specified route maps are advertised when the prefix exists only in the Advertise Map.").String,
+ Optional: true,
+ },
+ "neighbor_keepalive_interval": schema.Int64Attribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Time interval to send keepalive messages in seconds").AddIntegerRangeDescription(0, 65535).String,
+ Optional: true,
+ Validators: []validator.Int64{
+ int64validator.Between(0, 65535),
+ },
+ },
+ "neighbor_hold_time": schema.Int64Attribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Time interval to hold the neighbor in seconds").AddIntegerRangeDescription(3, 65535).String,
+ Optional: true,
+ Validators: []validator.Int64{
+ int64validator.Between(3, 65535),
+ },
+ },
+ "neighbor_min_hold_time": schema.Int64Attribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Minimum hold time in seconds").AddIntegerRangeDescription(3, 65535).String,
+ Optional: true,
+ Validators: []validator.Int64{
+ int64validator.Between(3, 65535),
+ },
+ },
+ "neighbor_authentication_password": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Setting password enables authentication.").String,
+ Optional: true,
+ },
+ "neighbor_send_community_attribute": schema.BoolAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Send Community attribute to this neighbor").AddDefaultValueDescription("false").String,
+ Optional: true,
+ Computed: true,
+ Default: booldefault.StaticBool(false),
+ },
+ "neighbor_nexthop_self": schema.BoolAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Use itself as next hop for this neighbor").AddDefaultValueDescription("false").String,
+ Optional: true,
+ Computed: true,
+ Default: booldefault.StaticBool(false),
+ },
+ "neighbor_disable_connection_verification": schema.BoolAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Disable Connection Verification").AddDefaultValueDescription("false").String,
+ Optional: true,
+ Computed: true,
+ Default: booldefault.StaticBool(false),
+ },
+ "neighbor_tcp_mtu_path_discovery": schema.BoolAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Use TCP path MTU discovery.").AddDefaultValueDescription("false").String,
+ Optional: true,
+ Computed: true,
+ Default: booldefault.StaticBool(false),
+ },
+ "neighbor_max_hop_count": schema.Int64Attribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Maximum number of hops to reach the neighbor").AddIntegerRangeDescription(1, 255).AddDefaultValueDescription("1").String,
+ Optional: true,
+ Computed: true,
+ Validators: []validator.Int64{
+ int64validator.Between(1, 255),
+ },
+ Default: int64default.StaticInt64(1),
+ },
+ "neighbor_tcp_transport_mode": schema.BoolAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("True set it to active, False to passive.").AddDefaultValueDescription("false").String,
+ Optional: true,
+ Computed: true,
+ Default: booldefault.StaticBool(false),
+ },
+ "neighbor_weight": schema.Int64Attribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Weight of the neighbor").AddIntegerRangeDescription(0, 65535).AddDefaultValueDescription("0").String,
+ Optional: true,
+ Computed: true,
+ Validators: []validator.Int64{
+ int64validator.Between(0, 65535),
+ },
+ Default: int64default.StaticInt64(0),
+ },
+ "neighbor_version": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Set BPG version: 0 - default, 4 - IPv4").AddStringEnumDescription("0", "4").AddDefaultValueDescription("0").String,
+ Optional: true,
+ Computed: true,
+ Validators: []validator.String{
+ stringvalidator.OneOf("0", "4"),
+ },
+ Default: stringdefault.StaticString("0"),
+ },
+ "neighbor_customized_local_as_number": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Customize the AS number for the routes received from neighbor").String,
+ Optional: true,
+ },
+ "neighbor_customized_no_prepend": schema.BoolAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Do not prepend local AS number to routes received from neighbor").String,
+ Optional: true,
+ },
+ "neighbor_customized_replace_as": schema.BoolAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Replace real AS number with local AS number in routes received from neighbor").String,
+ Optional: true,
+ },
+ "neighbor_customized_accept_both_as": schema.BoolAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Accept either real AS number or local AS number in routes experienced from neighbor").String,
+ Optional: true,
+ },
+ },
+ },
+ },
+ "ipv4_aggregate_addresses": schema.ListNestedAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("").String,
+ Optional: true,
+ NestedObject: schema.NestedAttributeObject{
+ Attributes: map[string]schema.Attribute{
+ "generate_as": schema.BoolAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Generate AS set path information").String,
+ Optional: true,
+ },
+ "filter": schema.BoolAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Filter all routes from updates (summary only)").String,
+ Optional: true,
+ },
+ "network_id": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Network ID").String,
+ Optional: true,
+ },
+ "advertise_map_id": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Advertise Map ID").String,
+ Optional: true,
+ },
+ "attribute_map_id": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Attribute Map ID").String,
+ Optional: true,
+ },
+ "suppress_map_id": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Suppress Map ID").String,
+ Optional: true,
+ },
+ },
+ },
+ },
+ "ipv4_filterings": schema.ListNestedAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("").String,
+ Optional: true,
+ NestedObject: schema.NestedAttributeObject{
+ Attributes: map[string]schema.Attribute{
+ "access_list_id": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Standard Access List ID").String,
+ Optional: true,
+ },
+ "network_direction": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Filtering directrion").AddStringEnumDescription("incomingroutefilter", "outgoingroutefilter").String,
+ Optional: true,
+ Validators: []validator.String{
+ stringvalidator.OneOf("incomingroutefilter", "outgoingroutefilter"),
+ },
+ },
+ "protocol": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Protocol").String,
+ Optional: true,
+ },
+ "prorocol_process": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Process ID").String,
+ Optional: true,
+ },
+ },
+ },
+ },
+ "ipv4_networks": schema.ListNestedAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("").String,
+ Optional: true,
+ NestedObject: schema.NestedAttributeObject{
+ Attributes: map[string]schema.Attribute{
+ "network_id": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Network object ID").String,
+ Optional: true,
+ },
+ "route_map_id": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Route Map ID").String,
+ Optional: true,
+ },
+ },
+ },
+ },
+ "ipv4_redistributions": schema.ListNestedAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("").String,
+ Optional: true,
+ NestedObject: schema.NestedAttributeObject{
+ Attributes: map[string]schema.Attribute{
+ "source_protocol": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Protocol to redistribute").AddStringEnumDescription("RedistributeConnected", "RedistributeStatic", "RedistributeOSPF", "RedistributeEIGRP").String,
+ Optional: true,
+ Validators: []validator.String{
+ stringvalidator.OneOf("RedistributeConnected", "RedistributeStatic", "RedistributeOSPF", "RedistributeEIGRP"),
+ },
+ },
+ "route_map_id": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Route Map ID").String,
+ Optional: true,
+ },
+ "metric": schema.Int64Attribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Metric value").AddIntegerRangeDescription(0, 4294967295).String,
+ Optional: true,
+ Validators: []validator.Int64{
+ int64validator.Between(0, 4294967295),
+ },
+ },
+ "process_id": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("process ID").String,
+ Optional: true,
+ },
+ "match_external1": schema.BoolAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Match OSPF External 1 metrics").String,
+ Optional: true,
+ },
+ "match_external2": schema.BoolAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Match OSPF External 2 metrics").String,
+ Optional: true,
+ },
+ "match_internal": schema.BoolAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Match OSPF Internal metrics").String,
+ Optional: true,
+ },
+ "match_nssa_external1": schema.BoolAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Match OSPF NSSA External 1 metrics").String,
+ Optional: true,
+ },
+ "match_nssa_external2": schema.BoolAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Match OSPF NSSA External 2 metrics").String,
+ Optional: true,
+ },
+ },
+ },
+ },
+ "ipv4_route_injections": schema.ListNestedAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("").String,
+ Optional: true,
+ NestedObject: schema.NestedAttributeObject{
+ Attributes: map[string]schema.Attribute{
+ "inject_route_map_id": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Inject Route Map ID").String,
+ Optional: true,
+ },
+ "exist_route_map_id": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Exist Route Map ID").String,
+ Optional: true,
+ },
+ },
+ },
+ },
+ },
+ }
+}
+
+func (r *DeviceBGPResource) Configure(_ context.Context, req resource.ConfigureRequest, _ *resource.ConfigureResponse) {
+ if req.ProviderData == nil {
+ return
+ }
+
+ r.client = req.ProviderData.(*FmcProviderData).Client
+}
+
+// End of section. //template:end model
+
+// Section below is generated&owned by "gen/generator.go". //template:begin create
+
+func (r *DeviceBGPResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
+ var plan DeviceBGP
+
+ // Read plan
+ diags := req.Plan.Get(ctx, &plan)
+ if resp.Diagnostics.Append(diags...); resp.Diagnostics.HasError() {
+ return
+ }
+
+ // Set request domain if provided
+ reqMods := [](func(*fmc.Req)){}
+ if !plan.Domain.IsNull() && plan.Domain.ValueString() != "" {
+ reqMods = append(reqMods, fmc.DomainName(plan.Domain.ValueString()))
+ }
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Beginning Create", plan.Id.ValueString()))
+
+ // Create object
+ body := plan.toBody(ctx, DeviceBGP{})
+ res, err := r.client.Post(plan.getPath(), body, reqMods...)
+ if err != nil {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to configure object (POST/PUT), got error: %s, %s", err, res.String()))
+ return
+ }
+ plan.Id = types.StringValue(res.Get("id").String())
+ plan.fromBodyUnknowns(ctx, res)
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Create finished successfully", plan.Id.ValueString()))
+
+ diags = resp.State.Set(ctx, &plan)
+ resp.Diagnostics.Append(diags...)
+
+ helpers.SetFlagImporting(ctx, false, resp.Private, &resp.Diagnostics)
+}
+
+// End of section. //template:end create
+
+// Section below is generated&owned by "gen/generator.go". //template:begin read
+
+func (r *DeviceBGPResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
+ var state DeviceBGP
+
+ // Read state
+ diags := req.State.Get(ctx, &state)
+ if resp.Diagnostics.Append(diags...); resp.Diagnostics.HasError() {
+ return
+ }
+
+ // Set request domain if provided
+ reqMods := [](func(*fmc.Req)){}
+ if !state.Domain.IsNull() && state.Domain.ValueString() != "" {
+ reqMods = append(reqMods, fmc.DomainName(state.Domain.ValueString()))
+ }
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Beginning Read", state.Id.String()))
+
+ urlPath := state.getPath() + "/" + url.QueryEscape(state.Id.ValueString())
+ res, err := r.client.Get(urlPath, reqMods...)
+
+ if err != nil && strings.Contains(err.Error(), "StatusCode 404") {
+ resp.State.RemoveResource(ctx)
+ return
+ } else if err != nil {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to retrieve object (GET), got error: %s, %s", err, res.String()))
+ return
+ }
+
+ imp, diags := helpers.IsFlagImporting(ctx, req)
+ if resp.Diagnostics.Append(diags...); resp.Diagnostics.HasError() {
+ return
+ }
+
+ // After `terraform import` we switch to a full read.
+ if imp {
+ state.fromBody(ctx, res)
+ } else {
+ state.fromBodyPartial(ctx, res)
+ }
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Read finished successfully", state.Id.ValueString()))
+
+ diags = resp.State.Set(ctx, &state)
+ resp.Diagnostics.Append(diags...)
+
+ helpers.SetFlagImporting(ctx, false, resp.Private, &resp.Diagnostics)
+}
+
+// End of section. //template:end read
+
+// Section below is generated&owned by "gen/generator.go". //template:begin update
+
+func (r *DeviceBGPResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
+ var plan, state DeviceBGP
+
+ // Read plan
+ diags := req.Plan.Get(ctx, &plan)
+ if resp.Diagnostics.Append(diags...); resp.Diagnostics.HasError() {
+ return
+ }
+
+ // Read state
+ diags = req.State.Get(ctx, &state)
+ if resp.Diagnostics.Append(diags...); resp.Diagnostics.HasError() {
+ return
+ }
+
+ // Set request domain if provided
+ reqMods := [](func(*fmc.Req)){}
+ if !plan.Domain.IsNull() && plan.Domain.ValueString() != "" {
+ reqMods = append(reqMods, fmc.DomainName(plan.Domain.ValueString()))
+ }
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Beginning Update", plan.Id.ValueString()))
+
+ body := plan.toBody(ctx, state)
+ res, err := r.client.Put(plan.getPath()+"/"+url.QueryEscape(plan.Id.ValueString()), body, reqMods...)
+ if err != nil {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to configure object (PUT), got error: %s, %s", err, res.String()))
+ return
+ }
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Update finished successfully", plan.Id.ValueString()))
+
+ diags = resp.State.Set(ctx, &plan)
+ resp.Diagnostics.Append(diags...)
+}
+
+// End of section. //template:end update
+
+// Section below is generated&owned by "gen/generator.go". //template:begin delete
+
+func (r *DeviceBGPResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
+ var state DeviceBGP
+
+ // Read state
+ diags := req.State.Get(ctx, &state)
+ if resp.Diagnostics.Append(diags...); resp.Diagnostics.HasError() {
+ return
+ }
+
+ // Set request domain if provided
+ reqMods := [](func(*fmc.Req)){}
+ if !state.Domain.IsNull() && state.Domain.ValueString() != "" {
+ reqMods = append(reqMods, fmc.DomainName(state.Domain.ValueString()))
+ }
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Beginning Delete", state.Id.ValueString()))
+ res, err := r.client.Delete(state.getPath()+"/"+url.QueryEscape(state.Id.ValueString()), reqMods...)
+ if err != nil {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to delete object (DELETE), got error: %s, %s", err, res.String()))
+ return
+ }
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Delete finished successfully", state.Id.ValueString()))
+
+ resp.State.RemoveResource(ctx)
+}
+
+// End of section. //template:end delete
+
+// Section below is generated&owned by "gen/generator.go". //template:begin import
+
+func (r *DeviceBGPResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
+ idParts := strings.Split(req.ID, ",")
+
+ if len(idParts) != 2 || idParts[0] == "" || idParts[1] == "" {
+ resp.Diagnostics.AddError(
+ "Unexpected Import Identifier",
+ fmt.Sprintf("Expected import identifier with format: ,. Got: %q", req.ID),
+ )
+ return
+ }
+ resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("device_id"), idParts[0])...)
+ resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("id"), idParts[1])...)
+
+ helpers.SetFlagImporting(ctx, true, resp.Private, &resp.Diagnostics)
+}
+
+// End of section. //template:end import
+
+// Section below is generated&owned by "gen/generator.go". //template:begin createSubresources
+
+// End of section. //template:end createSubresources
+
+// Section below is generated&owned by "gen/generator.go". //template:begin deleteSubresources
+
+// End of section. //template:end deleteSubresources
+
+// Section below is generated&owned by "gen/generator.go". //template:begin updateSubresources
+
+// End of section. //template:end updateSubresources
diff --git a/internal/provider/resource_fmc_device_bgp_general_settings.go b/internal/provider/resource_fmc_device_bgp_general_settings.go
new file mode 100644
index 00000000..c5516b13
--- /dev/null
+++ b/internal/provider/resource_fmc_device_bgp_general_settings.go
@@ -0,0 +1,424 @@
+// Copyright © 2023 Cisco Systems, Inc. and its affiliates.
+// All rights reserved.
+//
+// Licensed under the Mozilla Public License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://mozilla.org/MPL/2.0/
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// SPDX-License-Identifier: MPL-2.0
+
+package provider
+
+// Section below is generated&owned by "gen/generator.go". //template:begin imports
+import (
+ "context"
+ "fmt"
+ "net/url"
+ "strings"
+
+ "github.com/hashicorp/terraform-plugin-framework-validators/int64validator"
+ "github.com/hashicorp/terraform-plugin-framework/path"
+ "github.com/hashicorp/terraform-plugin-framework/resource"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
+ "github.com/hashicorp/terraform-plugin-framework/schema/validator"
+ "github.com/hashicorp/terraform-plugin-framework/types"
+ "github.com/hashicorp/terraform-plugin-log/tflog"
+ "github.com/netascode/go-fmc"
+ "github.com/netascode/terraform-provider-fmc/internal/provider/helpers"
+)
+
+// End of section. //template:end imports
+
+// Section below is generated&owned by "gen/generator.go". //template:begin model
+
+// Ensure provider defined types fully satisfy framework interfaces
+var (
+ _ resource.Resource = &DeviceBGPGeneralSettingsResource{}
+ _ resource.ResourceWithImportState = &DeviceBGPGeneralSettingsResource{}
+)
+
+func NewDeviceBGPGeneralSettingsResource() resource.Resource {
+ return &DeviceBGPGeneralSettingsResource{}
+}
+
+type DeviceBGPGeneralSettingsResource struct {
+ client *fmc.Client
+}
+
+func (r *DeviceBGPGeneralSettingsResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
+ resp.TypeName = req.ProviderTypeName + "_device_bgp_general_settings"
+}
+
+func (r *DeviceBGPGeneralSettingsResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
+ resp.Schema = schema.Schema{
+ // This description is used by the documentation generator and the language server.
+ MarkdownDescription: helpers.NewAttributeDescription("This resource can manage a Device BGP General Settings.").String,
+
+ Attributes: map[string]schema.Attribute{
+ "id": schema.StringAttribute{
+ MarkdownDescription: "The id of the object",
+ Computed: true,
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.UseStateForUnknown(),
+ },
+ },
+ "domain": schema.StringAttribute{
+ MarkdownDescription: "The name of the FMC domain",
+ Optional: true,
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.RequiresReplace(),
+ },
+ },
+ "device_id": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("UUID of the parent device (fmc_device.example.id).").String,
+ Required: true,
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.RequiresReplace(),
+ },
+ },
+ "name": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Object name; Always set to 'AsaBGPGeneralTable'").String,
+ Computed: true,
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.UseStateForUnknown(),
+ },
+ },
+ "as_number": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Autonomous System (AS) number in asplain or asdot format").String,
+ Required: true,
+ },
+ "router_id": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("String value for the routerID. Possible values can be 'AUTOMATIC' or valid ipv4 address").String,
+ Optional: true,
+ },
+ "scanning_interval": schema.Int64Attribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Scanning interval of BGP routers for next hop validation in Seconds.").AddIntegerRangeDescription(5, 60).String,
+ Optional: true,
+ Validators: []validator.Int64{
+ int64validator.Between(5, 60),
+ },
+ },
+ "as_number_in_path_attribute": schema.Int64Attribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Range to discard routes that have as-path segments that exceed a specified value.").AddIntegerRangeDescription(1, 254).String,
+ Optional: true,
+ Validators: []validator.Int64{
+ int64validator.Between(1, 254),
+ },
+ },
+ "log_neighbor_changes": schema.BoolAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Enable logging of BGP neighbor status changes.").String,
+ Optional: true,
+ },
+ "tcp_path_mtu_discovery": schema.BoolAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Use TCP path MTU discovery.").String,
+ Optional: true,
+ },
+ "reset_session_upon_failover": schema.BoolAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Reset session upon failover").String,
+ Optional: true,
+ },
+ "enforce_first_peer_as": schema.BoolAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Discard updates received from an external BGP (eBGP) peers that do not list their autonomous system (AS) number.").String,
+ Optional: true,
+ },
+ "use_dot_notation": schema.BoolAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Change format of BGP 4-byte autonomous system numbers from asplain (decimal values) to dot notation.").String,
+ Optional: true,
+ },
+ "aggregate_timer": schema.Int64Attribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Interval at which BGP routes will be aggregated or to disable timer-based router aggregation (in seconds).").AddIntegerRangeDescription(6, 60).String,
+ Optional: true,
+ Validators: []validator.Int64{
+ int64validator.Between(6, 60),
+ },
+ },
+ "default_local_preference": schema.Int64Attribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Default local preference").AddIntegerRangeDescription(0, 4294967295).String,
+ Optional: true,
+ Validators: []validator.Int64{
+ int64validator.Between(0, 4294967295),
+ },
+ },
+ "compare_med_from_different_neighbors": schema.BoolAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Allow comparing MED from different neighbors").String,
+ Optional: true,
+ },
+ "compare_router_id_in_path": schema.BoolAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Compare Router ID for identical EBGP paths").String,
+ Optional: true,
+ },
+ "pick_best_med": schema.BoolAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Pick the best-MED path among paths advertised by neighbor AS").String,
+ Optional: true,
+ },
+ "missing_med_as_best": schema.BoolAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Treat missing MED as the best preferred path").String,
+ Optional: true,
+ },
+ "keepalive_interval": schema.Int64Attribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Keepalive interval in seconds").AddIntegerRangeDescription(0, 65535).String,
+ Optional: true,
+ Validators: []validator.Int64{
+ int64validator.Between(0, 65535),
+ },
+ },
+ "hold_time": schema.Int64Attribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Hold time in seconds").AddIntegerRangeDescription(0, 65535).String,
+ Optional: true,
+ Validators: []validator.Int64{
+ int64validator.Between(0, 65535),
+ },
+ },
+ "min_hold_time": schema.Int64Attribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Minimum hold time (0 or 3-65535 seconds)").AddIntegerRangeDescription(0, 65535).String,
+ Optional: true,
+ Validators: []validator.Int64{
+ int64validator.Between(0, 65535),
+ },
+ },
+ "next_hop_address_tracking": schema.BoolAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Enable next hop address tracking").String,
+ Optional: true,
+ },
+ "next_hop_delay_interval": schema.Int64Attribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Next hop delay interval in seconds").AddIntegerRangeDescription(0, 100).String,
+ Optional: true,
+ Validators: []validator.Int64{
+ int64validator.Between(0, 100),
+ },
+ },
+ "graceful_restart": schema.BoolAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Enable graceful restart").String,
+ Optional: true,
+ },
+ "graceful_restart_restart_time": schema.Int64Attribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Graceful Restart Time in seconds").AddIntegerRangeDescription(1, 3600).String,
+ Optional: true,
+ Validators: []validator.Int64{
+ int64validator.Between(1, 3600),
+ },
+ },
+ "graceful_restart_stale_path_time": schema.Int64Attribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Stalepath Time in seconds").AddIntegerRangeDescription(1, 3600).String,
+ Optional: true,
+ Validators: []validator.Int64{
+ int64validator.Between(1, 3600),
+ },
+ },
+ },
+ }
+}
+
+func (r *DeviceBGPGeneralSettingsResource) Configure(_ context.Context, req resource.ConfigureRequest, _ *resource.ConfigureResponse) {
+ if req.ProviderData == nil {
+ return
+ }
+
+ r.client = req.ProviderData.(*FmcProviderData).Client
+}
+
+// End of section. //template:end model
+
+// Section below is generated&owned by "gen/generator.go". //template:begin create
+
+func (r *DeviceBGPGeneralSettingsResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
+ var plan DeviceBGPGeneralSettings
+
+ // Read plan
+ diags := req.Plan.Get(ctx, &plan)
+ if resp.Diagnostics.Append(diags...); resp.Diagnostics.HasError() {
+ return
+ }
+
+ // Set request domain if provided
+ reqMods := [](func(*fmc.Req)){}
+ if !plan.Domain.IsNull() && plan.Domain.ValueString() != "" {
+ reqMods = append(reqMods, fmc.DomainName(plan.Domain.ValueString()))
+ }
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Beginning Create", plan.Id.ValueString()))
+
+ // Create object
+ body := plan.toBody(ctx, DeviceBGPGeneralSettings{})
+ res, err := r.client.Post(plan.getPath(), body, reqMods...)
+ if err != nil {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to configure object (POST/PUT), got error: %s, %s", err, res.String()))
+ return
+ }
+ plan.Id = types.StringValue(res.Get("id").String())
+ plan.fromBodyUnknowns(ctx, res)
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Create finished successfully", plan.Id.ValueString()))
+
+ diags = resp.State.Set(ctx, &plan)
+ resp.Diagnostics.Append(diags...)
+
+ helpers.SetFlagImporting(ctx, false, resp.Private, &resp.Diagnostics)
+}
+
+// End of section. //template:end create
+
+// Section below is generated&owned by "gen/generator.go". //template:begin read
+
+func (r *DeviceBGPGeneralSettingsResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
+ var state DeviceBGPGeneralSettings
+
+ // Read state
+ diags := req.State.Get(ctx, &state)
+ if resp.Diagnostics.Append(diags...); resp.Diagnostics.HasError() {
+ return
+ }
+
+ // Set request domain if provided
+ reqMods := [](func(*fmc.Req)){}
+ if !state.Domain.IsNull() && state.Domain.ValueString() != "" {
+ reqMods = append(reqMods, fmc.DomainName(state.Domain.ValueString()))
+ }
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Beginning Read", state.Id.String()))
+
+ urlPath := state.getPath() + "/" + url.QueryEscape(state.Id.ValueString())
+ res, err := r.client.Get(urlPath, reqMods...)
+
+ if err != nil && strings.Contains(err.Error(), "StatusCode 404") {
+ resp.State.RemoveResource(ctx)
+ return
+ } else if err != nil {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to retrieve object (GET), got error: %s, %s", err, res.String()))
+ return
+ }
+
+ imp, diags := helpers.IsFlagImporting(ctx, req)
+ if resp.Diagnostics.Append(diags...); resp.Diagnostics.HasError() {
+ return
+ }
+
+ // After `terraform import` we switch to a full read.
+ if imp {
+ state.fromBody(ctx, res)
+ } else {
+ state.fromBodyPartial(ctx, res)
+ }
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Read finished successfully", state.Id.ValueString()))
+
+ diags = resp.State.Set(ctx, &state)
+ resp.Diagnostics.Append(diags...)
+
+ helpers.SetFlagImporting(ctx, false, resp.Private, &resp.Diagnostics)
+}
+
+// End of section. //template:end read
+
+// Section below is generated&owned by "gen/generator.go". //template:begin update
+
+func (r *DeviceBGPGeneralSettingsResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
+ var plan, state DeviceBGPGeneralSettings
+
+ // Read plan
+ diags := req.Plan.Get(ctx, &plan)
+ if resp.Diagnostics.Append(diags...); resp.Diagnostics.HasError() {
+ return
+ }
+
+ // Read state
+ diags = req.State.Get(ctx, &state)
+ if resp.Diagnostics.Append(diags...); resp.Diagnostics.HasError() {
+ return
+ }
+
+ // Set request domain if provided
+ reqMods := [](func(*fmc.Req)){}
+ if !plan.Domain.IsNull() && plan.Domain.ValueString() != "" {
+ reqMods = append(reqMods, fmc.DomainName(plan.Domain.ValueString()))
+ }
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Beginning Update", plan.Id.ValueString()))
+
+ body := plan.toBody(ctx, state)
+ res, err := r.client.Put(plan.getPath()+"/"+url.QueryEscape(plan.Id.ValueString()), body, reqMods...)
+ if err != nil {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to configure object (PUT), got error: %s, %s", err, res.String()))
+ return
+ }
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Update finished successfully", plan.Id.ValueString()))
+
+ diags = resp.State.Set(ctx, &plan)
+ resp.Diagnostics.Append(diags...)
+}
+
+// End of section. //template:end update
+
+// Section below is generated&owned by "gen/generator.go". //template:begin delete
+
+func (r *DeviceBGPGeneralSettingsResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
+ var state DeviceBGPGeneralSettings
+
+ // Read state
+ diags := req.State.Get(ctx, &state)
+ if resp.Diagnostics.Append(diags...); resp.Diagnostics.HasError() {
+ return
+ }
+
+ // Set request domain if provided
+ reqMods := [](func(*fmc.Req)){}
+ if !state.Domain.IsNull() && state.Domain.ValueString() != "" {
+ reqMods = append(reqMods, fmc.DomainName(state.Domain.ValueString()))
+ }
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Beginning Delete", state.Id.ValueString()))
+ res, err := r.client.Delete(state.getPath()+"/"+url.QueryEscape(state.Id.ValueString()), reqMods...)
+ if err != nil {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to delete object (DELETE), got error: %s, %s", err, res.String()))
+ return
+ }
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Delete finished successfully", state.Id.ValueString()))
+
+ resp.State.RemoveResource(ctx)
+}
+
+// End of section. //template:end delete
+
+// Section below is generated&owned by "gen/generator.go". //template:begin import
+
+func (r *DeviceBGPGeneralSettingsResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
+ idParts := strings.Split(req.ID, ",")
+
+ if len(idParts) != 2 || idParts[0] == "" || idParts[1] == "" {
+ resp.Diagnostics.AddError(
+ "Unexpected Import Identifier",
+ fmt.Sprintf("Expected import identifier with format: ,. Got: %q", req.ID),
+ )
+ return
+ }
+ resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("device_id"), idParts[0])...)
+ resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("id"), idParts[1])...)
+
+ helpers.SetFlagImporting(ctx, true, resp.Private, &resp.Diagnostics)
+}
+
+// End of section. //template:end import
+
+// Section below is generated&owned by "gen/generator.go". //template:begin createSubresources
+
+// End of section. //template:end createSubresources
+
+// Section below is generated&owned by "gen/generator.go". //template:begin deleteSubresources
+
+// End of section. //template:end deleteSubresources
+
+// Section below is generated&owned by "gen/generator.go". //template:begin updateSubresources
+
+// End of section. //template:end updateSubresources
diff --git a/internal/provider/resource_fmc_device_bgp_general_settings_test.go b/internal/provider/resource_fmc_device_bgp_general_settings_test.go
new file mode 100644
index 00000000..65d284f4
--- /dev/null
+++ b/internal/provider/resource_fmc_device_bgp_general_settings_test.go
@@ -0,0 +1,127 @@
+// Copyright © 2023 Cisco Systems, Inc. and its affiliates.
+// All rights reserved.
+//
+// Licensed under the Mozilla Public License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://mozilla.org/MPL/2.0/
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// SPDX-License-Identifier: MPL-2.0
+
+package provider
+
+// Section below is generated&owned by "gen/generator.go". //template:begin imports
+import (
+ "os"
+ "testing"
+
+ "github.com/hashicorp/terraform-plugin-testing/helper/resource"
+)
+
+// End of section. //template:end imports
+
+// Section below is generated&owned by "gen/generator.go". //template:begin testAcc
+
+func TestAccFmcDeviceBGPGeneralSettings(t *testing.T) {
+ if os.Getenv("TF_VAR_device_id") == "" {
+ t.Skip("skipping test, set environment variable TF_VAR_device_id")
+ }
+ var checks []resource.TestCheckFunc
+ checks = append(checks, resource.TestCheckResourceAttrSet("fmc_device_bgp_general_settings.test", "name"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_bgp_general_settings.test", "as_number", "65535"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_bgp_general_settings.test", "router_id", "AUTOMATIC"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_bgp_general_settings.test", "scanning_interval", "60"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_bgp_general_settings.test", "as_number_in_path_attribute", "50"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_bgp_general_settings.test", "log_neighbor_changes", "false"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_bgp_general_settings.test", "tcp_path_mtu_discovery", "true"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_bgp_general_settings.test", "reset_session_upon_failover", "true"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_bgp_general_settings.test", "enforce_first_peer_as", "true"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_bgp_general_settings.test", "use_dot_notation", "false"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_bgp_general_settings.test", "aggregate_timer", "30"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_bgp_general_settings.test", "default_local_preference", "100"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_bgp_general_settings.test", "compare_med_from_different_neighbors", "true"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_bgp_general_settings.test", "compare_router_id_in_path", "true"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_bgp_general_settings.test", "pick_best_med", "true"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_bgp_general_settings.test", "missing_med_as_best", "false"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_bgp_general_settings.test", "keepalive_interval", "60"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_bgp_general_settings.test", "hold_time", "180"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_bgp_general_settings.test", "min_hold_time", "0"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_bgp_general_settings.test", "next_hop_delay_interval", "5"))
+
+ var steps []resource.TestStep
+ if os.Getenv("SKIP_MINIMUM_TEST") == "" {
+ steps = append(steps, resource.TestStep{
+ Config: testAccFmcDeviceBGPGeneralSettingsPrerequisitesConfig + testAccFmcDeviceBGPGeneralSettingsConfig_minimum(),
+ })
+ }
+ steps = append(steps, resource.TestStep{
+ Config: testAccFmcDeviceBGPGeneralSettingsPrerequisitesConfig + testAccFmcDeviceBGPGeneralSettingsConfig_all(),
+ Check: resource.ComposeTestCheckFunc(checks...),
+ })
+
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { testAccPreCheck(t) },
+ ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
+ ErrorCheck: func(err error) error { return testAccErrorCheck(t, err) },
+ Steps: steps,
+ })
+}
+
+// End of section. //template:end testAcc
+
+// Section below is generated&owned by "gen/generator.go". //template:begin testPrerequisites
+
+const testAccFmcDeviceBGPGeneralSettingsPrerequisitesConfig = `
+variable "device_id" { default = null } // tests will set $TF_VAR_device_id
+`
+
+// End of section. //template:end testPrerequisites
+
+// Section below is generated&owned by "gen/generator.go". //template:begin testAccConfigMinimal
+
+func testAccFmcDeviceBGPGeneralSettingsConfig_minimum() string {
+ config := `resource "fmc_device_bgp_general_settings" "test" {` + "\n"
+ config += ` device_id = var.device_id` + "\n"
+ config += ` as_number = "65535"` + "\n"
+ config += `}` + "\n"
+ return config
+}
+
+// End of section. //template:end testAccConfigMinimal
+
+// Section below is generated&owned by "gen/generator.go". //template:begin testAccConfigAll
+
+func testAccFmcDeviceBGPGeneralSettingsConfig_all() string {
+ config := `resource "fmc_device_bgp_general_settings" "test" {` + "\n"
+ config += ` device_id = var.device_id` + "\n"
+ config += ` as_number = "65535"` + "\n"
+ config += ` router_id = "AUTOMATIC"` + "\n"
+ config += ` scanning_interval = 60` + "\n"
+ config += ` as_number_in_path_attribute = 50` + "\n"
+ config += ` log_neighbor_changes = false` + "\n"
+ config += ` tcp_path_mtu_discovery = true` + "\n"
+ config += ` reset_session_upon_failover = true` + "\n"
+ config += ` enforce_first_peer_as = true` + "\n"
+ config += ` use_dot_notation = false` + "\n"
+ config += ` aggregate_timer = 30` + "\n"
+ config += ` default_local_preference = 100` + "\n"
+ config += ` compare_med_from_different_neighbors = true` + "\n"
+ config += ` compare_router_id_in_path = true` + "\n"
+ config += ` pick_best_med = true` + "\n"
+ config += ` missing_med_as_best = false` + "\n"
+ config += ` keepalive_interval = 60` + "\n"
+ config += ` hold_time = 180` + "\n"
+ config += ` min_hold_time = 0` + "\n"
+ config += ` next_hop_delay_interval = 5` + "\n"
+ config += `}` + "\n"
+ return config
+}
+
+// End of section. //template:end testAccConfigAll
diff --git a/internal/provider/resource_fmc_device_bgp_test.go b/internal/provider/resource_fmc_device_bgp_test.go
new file mode 100644
index 00000000..006fe904
--- /dev/null
+++ b/internal/provider/resource_fmc_device_bgp_test.go
@@ -0,0 +1,164 @@
+// Copyright © 2023 Cisco Systems, Inc. and its affiliates.
+// All rights reserved.
+//
+// Licensed under the Mozilla Public License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://mozilla.org/MPL/2.0/
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// SPDX-License-Identifier: MPL-2.0
+
+package provider
+
+// Section below is generated&owned by "gen/generator.go". //template:begin imports
+import (
+ "os"
+ "testing"
+
+ "github.com/hashicorp/terraform-plugin-testing/helper/resource"
+)
+
+// End of section. //template:end imports
+
+// Section below is generated&owned by "gen/generator.go". //template:begin testAcc
+
+func TestAccFmcDeviceBGP(t *testing.T) {
+ if os.Getenv("TF_VAR_device_id") == "" {
+ t.Skip("skipping test, set environment variable TF_VAR_device_id")
+ }
+ var checks []resource.TestCheckFunc
+ checks = append(checks, resource.TestCheckResourceAttrSet("fmc_device_bgp.test", "name"))
+ checks = append(checks, resource.TestCheckResourceAttrSet("fmc_device_bgp.test", "type"))
+ checks = append(checks, resource.TestCheckResourceAttrSet("fmc_device_bgp.test", "as_number"))
+ checks = append(checks, resource.TestCheckResourceAttrSet("fmc_device_bgp.test", "ipv4_address_family_type"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_bgp.test", "ipv4_default_information_orginate", "false"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_bgp.test", "ipv4_auto_aummary", "false"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_bgp.test", "ipv4_bgp_supress_inactive", "false"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_bgp.test", "ipv4_synchronization", "false"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_bgp.test", "ipv4_bgp_redistribute_internal", "false"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_bgp.test", "ipv4_external_distance", "20"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_bgp.test", "ipv4_internal_distance", "200"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_bgp.test", "ipv4_local_distance", "200"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_bgp.test", "ipv4_forward_packets_over_multipath_ibgp", "1"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_bgp.test", "ipv4_forward_packets_over_multipath_ebgp", "1"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_bgp.test", "ipv4_neighbors.0.neighbor_address", "10.1.1.1"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_bgp.test", "ipv4_neighbors.0.neighbor_remote_as", "65534"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_bgp.test", "ipv4_neighbors.0.neighbor_bfd", "SINGLE_HOP"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_bgp.test", "ipv4_neighbors.0.enable_address_family", "true"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_bgp.test", "ipv4_neighbors.0.neighbor_shutdown", "false"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_bgp.test", "ipv4_neighbors.0.neighbor_description", "My BGP Peer"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_bgp.test", "ipv4_neighbors.0.neighbor_filter_max_prefix", "1"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_bgp.test", "ipv4_neighbors.0.neighbor_filter_warning_only", "true"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_bgp.test", "ipv4_neighbors.0.neighbor_filter_threshold_value", "1"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_bgp.test", "ipv4_neighbors.0.neighbor_filter_restart_interval", "1"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_bgp.test", "ipv4_neighbors.0.neighbor_routes_advertisement_interval", "1"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_bgp.test", "ipv4_neighbors.0.neighbor_routes_remove_private_as", "false"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_bgp.test", "ipv4_neighbors.0.neighbor_keepalive_interval", "60"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_bgp.test", "ipv4_neighbors.0.neighbor_hold_time", "180"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_bgp.test", "ipv4_neighbors.0.neighbor_min_hold_time", "3"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_bgp.test", "ipv4_neighbors.0.neighbor_send_community_attribute", "false"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_bgp.test", "ipv4_neighbors.0.neighbor_nexthop_self", "false"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_bgp.test", "ipv4_neighbors.0.neighbor_disable_connection_verification", "false"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_bgp.test", "ipv4_neighbors.0.neighbor_tcp_mtu_path_discovery", "false"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_bgp.test", "ipv4_neighbors.0.neighbor_max_hop_count", "1"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_bgp.test", "ipv4_neighbors.0.neighbor_tcp_transport_mode", "false"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_bgp.test", "ipv4_neighbors.0.neighbor_weight", "0"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_bgp.test", "ipv4_neighbors.0.neighbor_version", "0"))
+
+ var steps []resource.TestStep
+ if os.Getenv("SKIP_MINIMUM_TEST") == "" {
+ steps = append(steps, resource.TestStep{
+ Config: testAccFmcDeviceBGPPrerequisitesConfig + testAccFmcDeviceBGPConfig_minimum(),
+ })
+ }
+ steps = append(steps, resource.TestStep{
+ Config: testAccFmcDeviceBGPPrerequisitesConfig + testAccFmcDeviceBGPConfig_all(),
+ Check: resource.ComposeTestCheckFunc(checks...),
+ })
+
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { testAccPreCheck(t) },
+ ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
+ ErrorCheck: func(err error) error { return testAccErrorCheck(t, err) },
+ Steps: steps,
+ })
+}
+
+// End of section. //template:end testAcc
+
+// Section below is generated&owned by "gen/generator.go". //template:begin testPrerequisites
+
+const testAccFmcDeviceBGPPrerequisitesConfig = `
+variable "device_id" { default = null } // tests will set $TF_VAR_device_id
+
+resource "fmc_device_bgp_general_settings" "test" {
+ device_id = var.device_id
+ as_number = "6353"
+}
+`
+
+// End of section. //template:end testPrerequisites
+
+// Section below is generated&owned by "gen/generator.go". //template:begin testAccConfigMinimal
+
+func testAccFmcDeviceBGPConfig_minimum() string {
+ config := `resource "fmc_device_bgp" "test" {` + "\n"
+ config += ` device_id = var.device_id` + "\n"
+ config += `}` + "\n"
+ return config
+}
+
+// End of section. //template:end testAccConfigMinimal
+
+// Section below is generated&owned by "gen/generator.go". //template:begin testAccConfigAll
+
+func testAccFmcDeviceBGPConfig_all() string {
+ config := `resource "fmc_device_bgp" "test" {` + "\n"
+ config += ` device_id = var.device_id` + "\n"
+ config += ` ipv4_default_information_orginate = false` + "\n"
+ config += ` ipv4_auto_aummary = false` + "\n"
+ config += ` ipv4_bgp_supress_inactive = false` + "\n"
+ config += ` ipv4_synchronization = false` + "\n"
+ config += ` ipv4_bgp_redistribute_internal = false` + "\n"
+ config += ` ipv4_external_distance = 20` + "\n"
+ config += ` ipv4_internal_distance = 200` + "\n"
+ config += ` ipv4_local_distance = 200` + "\n"
+ config += ` ipv4_forward_packets_over_multipath_ibgp = 1` + "\n"
+ config += ` ipv4_forward_packets_over_multipath_ebgp = 1` + "\n"
+ config += ` ipv4_neighbors = [{` + "\n"
+ config += ` neighbor_address = "10.1.1.1"` + "\n"
+ config += ` neighbor_remote_as = "65534"` + "\n"
+ config += ` neighbor_bfd = "SINGLE_HOP"` + "\n"
+ config += ` enable_address_family = true` + "\n"
+ config += ` neighbor_shutdown = false` + "\n"
+ config += ` neighbor_description = "My BGP Peer"` + "\n"
+ config += ` neighbor_filter_max_prefix = 1` + "\n"
+ config += ` neighbor_filter_warning_only = true` + "\n"
+ config += ` neighbor_filter_threshold_value = 1` + "\n"
+ config += ` neighbor_filter_restart_interval = 1` + "\n"
+ config += ` neighbor_routes_advertisement_interval = 1` + "\n"
+ config += ` neighbor_routes_remove_private_as = false` + "\n"
+ config += ` neighbor_keepalive_interval = 60` + "\n"
+ config += ` neighbor_hold_time = 180` + "\n"
+ config += ` neighbor_min_hold_time = 3` + "\n"
+ config += ` neighbor_send_community_attribute = false` + "\n"
+ config += ` neighbor_nexthop_self = false` + "\n"
+ config += ` neighbor_disable_connection_verification = false` + "\n"
+ config += ` neighbor_tcp_mtu_path_discovery = false` + "\n"
+ config += ` neighbor_max_hop_count = 1` + "\n"
+ config += ` neighbor_tcp_transport_mode = false` + "\n"
+ config += ` neighbor_weight = 0` + "\n"
+ config += ` neighbor_version = "0"` + "\n"
+ config += ` }]` + "\n"
+ config += `}` + "\n"
+ return config
+}
+
+// End of section. //template:end testAccConfigAll
diff --git a/internal/provider/resource_fmc_device_ha_pair_monitoring.go b/internal/provider/resource_fmc_device_ha_pair_monitoring.go
new file mode 100644
index 00000000..bcc22d99
--- /dev/null
+++ b/internal/provider/resource_fmc_device_ha_pair_monitoring.go
@@ -0,0 +1,373 @@
+// Copyright © 2023 Cisco Systems, Inc. and its affiliates.
+// All rights reserved.
+//
+// Licensed under the Mozilla Public License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://mozilla.org/MPL/2.0/
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// SPDX-License-Identifier: MPL-2.0
+
+package provider
+
+// Section below is generated&owned by "gen/generator.go". //template:begin imports
+import (
+ "context"
+ "fmt"
+ "net/url"
+ "strings"
+
+ "github.com/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/types"
+ "github.com/hashicorp/terraform-plugin-log/tflog"
+ "github.com/netascode/go-fmc"
+ "github.com/netascode/terraform-provider-fmc/internal/provider/helpers"
+ "github.com/tidwall/gjson"
+)
+
+// End of section. //template:end imports
+
+// Section below is generated&owned by "gen/generator.go". //template:begin model
+
+// Ensure provider defined types fully satisfy framework interfaces
+var (
+ _ resource.Resource = &DeviceHAPairMonitoringResource{}
+ _ resource.ResourceWithImportState = &DeviceHAPairMonitoringResource{}
+)
+
+func NewDeviceHAPairMonitoringResource() resource.Resource {
+ return &DeviceHAPairMonitoringResource{}
+}
+
+type DeviceHAPairMonitoringResource struct {
+ client *fmc.Client
+}
+
+func (r *DeviceHAPairMonitoringResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
+ resp.TypeName = req.ProviderTypeName + "_device_ha_pair_monitoring"
+}
+
+func (r *DeviceHAPairMonitoringResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
+ resp.Schema = schema.Schema{
+ // This description is used by the documentation generator and the language server.
+ MarkdownDescription: helpers.NewAttributeDescription("This resource can manage a Device HA Pair Monitoring.").String,
+
+ Attributes: map[string]schema.Attribute{
+ "id": schema.StringAttribute{
+ MarkdownDescription: "The id of the object",
+ Computed: true,
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.UseStateForUnknown(),
+ },
+ },
+ "domain": schema.StringAttribute{
+ MarkdownDescription: "The name of the FMC domain",
+ Optional: true,
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.RequiresReplace(),
+ },
+ },
+ "device_id": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("UUID of the parent HA device (fmc_device.example.id).").String,
+ Required: true,
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.RequiresReplace(),
+ },
+ },
+ "type": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Type of the resource.").String,
+ Computed: true,
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.UseStateForUnknown(),
+ },
+ },
+ "logical_name": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Logical Name of the monitored interface.").String,
+ Required: true,
+ },
+ "monitor_interface": schema.BoolAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Monitor this interface for failures.").String,
+ Required: true,
+ },
+ "ipv4_active_address": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Active IPv4 address from the interface.").String,
+ Computed: true,
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.UseStateForUnknown(),
+ },
+ },
+ "ipv4_standby_address": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Standby IPv4 address. It has to be in the same subnet as primaty IP configured on this interface.").String,
+ Optional: true,
+ },
+ "ipv4_netmask": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("IPv4 Network Mask assigned on the interface.").String,
+ Computed: true,
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.UseStateForUnknown(),
+ },
+ },
+ "ipv6_addresses": schema.ListNestedAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("").String,
+ Optional: true,
+ NestedObject: schema.NestedAttributeObject{
+ Attributes: map[string]schema.Attribute{
+ "active_address": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Active IPv6 address with prefix. Address has to be configured on the interface.").String,
+ Optional: true,
+ },
+ "standby_address": schema.StringAttribute{
+ MarkdownDescription: helpers.NewAttributeDescription("Standby IPv6 address. Address has to be from the same subnet as active IPv6 address.").String,
+ Optional: true,
+ },
+ },
+ },
+ },
+ },
+ }
+}
+
+func (r *DeviceHAPairMonitoringResource) Configure(_ context.Context, req resource.ConfigureRequest, _ *resource.ConfigureResponse) {
+ if req.ProviderData == nil {
+ return
+ }
+
+ r.client = req.ProviderData.(*FmcProviderData).Client
+}
+
+// End of section. //template:end model
+
+// Section below is generated&owned by "gen/generator.go". //template:begin create
+
+func (r *DeviceHAPairMonitoringResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
+ var plan DeviceHAPairMonitoring
+
+ // Read plan
+ diags := req.Plan.Get(ctx, &plan)
+ if resp.Diagnostics.Append(diags...); resp.Diagnostics.HasError() {
+ return
+ }
+
+ // Set request domain if provided
+ reqMods := [](func(*fmc.Req)){}
+ if !plan.Domain.IsNull() && plan.Domain.ValueString() != "" {
+ reqMods = append(reqMods, fmc.DomainName(plan.Domain.ValueString()))
+ }
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: considering object logical_name %s", plan.Id, plan.LogicalName))
+ if plan.Id.ValueString() == "" && plan.LogicalName.ValueString() != "" {
+ offset := 0
+ limit := 1000
+ for page := 1; ; page++ {
+ queryString := fmt.Sprintf("?limit=%d&offset=%d&expanded=true", limit, offset)
+ res, err := r.client.Get(plan.getPath()+queryString, reqMods...)
+ if err != nil {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to retrieve objects, got error: %s", err))
+ return
+ }
+ if value := res.Get("items"); len(value.Array()) > 0 {
+ value.ForEach(func(k, v gjson.Result) bool {
+ if plan.LogicalName.ValueString() == v.Get("name").String() {
+ plan.Id = types.StringValue(v.Get("id").String())
+ tflog.Debug(ctx, fmt.Sprintf("%s: Found object with logical_name '%s', id: %s", plan.Id, plan.LogicalName.ValueString(), plan.Id))
+ return false
+ }
+ return true
+ })
+ }
+ if plan.Id.ValueString() != "" || !res.Get("paging.next.0").Exists() {
+ break
+ }
+ offset += limit
+ }
+
+ if plan.Id.ValueString() == "" {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to find object with logical_name: %s", plan.LogicalName.ValueString()))
+ return
+ }
+ }
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Beginning Create", plan.Id.ValueString()))
+
+ // Create object
+ body := plan.toBody(ctx, DeviceHAPairMonitoring{})
+ res, err := r.client.Put(plan.getPath()+"/"+url.PathEscape(plan.Id.ValueString()), body, reqMods...)
+ if err != nil {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to configure object (POST/PUT), got error: %s, %s", err, res.String()))
+ return
+ }
+ plan.Id = types.StringValue(res.Get("id").String())
+ plan.fromBodyUnknowns(ctx, res)
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Create finished successfully", plan.Id.ValueString()))
+
+ diags = resp.State.Set(ctx, &plan)
+ resp.Diagnostics.Append(diags...)
+
+ helpers.SetFlagImporting(ctx, false, resp.Private, &resp.Diagnostics)
+}
+
+// End of section. //template:end create
+
+// Section below is generated&owned by "gen/generator.go". //template:begin read
+
+func (r *DeviceHAPairMonitoringResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
+ var state DeviceHAPairMonitoring
+
+ // Read state
+ diags := req.State.Get(ctx, &state)
+ if resp.Diagnostics.Append(diags...); resp.Diagnostics.HasError() {
+ return
+ }
+
+ // Set request domain if provided
+ reqMods := [](func(*fmc.Req)){}
+ if !state.Domain.IsNull() && state.Domain.ValueString() != "" {
+ reqMods = append(reqMods, fmc.DomainName(state.Domain.ValueString()))
+ }
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Beginning Read", state.Id.String()))
+
+ urlPath := state.getPath() + "/" + url.QueryEscape(state.Id.ValueString())
+ res, err := r.client.Get(urlPath, reqMods...)
+
+ if err != nil && strings.Contains(err.Error(), "StatusCode 404") {
+ resp.State.RemoveResource(ctx)
+ return
+ } else if err != nil {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to retrieve object (GET), got error: %s, %s", err, res.String()))
+ return
+ }
+
+ imp, diags := helpers.IsFlagImporting(ctx, req)
+ if resp.Diagnostics.Append(diags...); resp.Diagnostics.HasError() {
+ return
+ }
+
+ // After `terraform import` we switch to a full read.
+ if imp {
+ state.fromBody(ctx, res)
+ } else {
+ state.fromBodyPartial(ctx, res)
+ }
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Read finished successfully", state.Id.ValueString()))
+
+ diags = resp.State.Set(ctx, &state)
+ resp.Diagnostics.Append(diags...)
+
+ helpers.SetFlagImporting(ctx, false, resp.Private, &resp.Diagnostics)
+}
+
+// End of section. //template:end read
+
+// Section below is generated&owned by "gen/generator.go". //template:begin update
+
+func (r *DeviceHAPairMonitoringResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
+ var plan, state DeviceHAPairMonitoring
+
+ // Read plan
+ diags := req.Plan.Get(ctx, &plan)
+ if resp.Diagnostics.Append(diags...); resp.Diagnostics.HasError() {
+ return
+ }
+
+ // Read state
+ diags = req.State.Get(ctx, &state)
+ if resp.Diagnostics.Append(diags...); resp.Diagnostics.HasError() {
+ return
+ }
+
+ // Set request domain if provided
+ reqMods := [](func(*fmc.Req)){}
+ if !plan.Domain.IsNull() && plan.Domain.ValueString() != "" {
+ reqMods = append(reqMods, fmc.DomainName(plan.Domain.ValueString()))
+ }
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Beginning Update", plan.Id.ValueString()))
+
+ body := plan.toBody(ctx, state)
+ res, err := r.client.Put(plan.getPath()+"/"+url.QueryEscape(plan.Id.ValueString()), body, reqMods...)
+ if err != nil {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to configure object (PUT), got error: %s, %s", err, res.String()))
+ return
+ }
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Update finished successfully", plan.Id.ValueString()))
+
+ diags = resp.State.Set(ctx, &plan)
+ resp.Diagnostics.Append(diags...)
+}
+
+// End of section. //template:end update
+
+func (r *DeviceHAPairMonitoringResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
+ var state DeviceHAPairMonitoring
+
+ // Read state
+ diags := req.State.Get(ctx, &state)
+ if resp.Diagnostics.Append(diags...); resp.Diagnostics.HasError() {
+ return
+ }
+
+ // Set request domain if provided
+ reqMods := [](func(*fmc.Req)){}
+ if !state.Domain.IsNull() && state.Domain.ValueString() != "" {
+ reqMods = append(reqMods, fmc.DomainName(state.Domain.ValueString()))
+ }
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Beginning Delete", state.Id.ValueString()))
+ body := state.toBodyPutDelete(ctx, DeviceHAPairMonitoring{})
+ res, err := r.client.Put(state.getPath()+"/"+url.QueryEscape(state.Id.ValueString()), body, reqMods...)
+ if err != nil {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to remove object configuration (PUT), got error: %s, %s", err, res.String()))
+ return
+ }
+
+ tflog.Debug(ctx, fmt.Sprintf("%s: Delete finished successfully", state.Id.ValueString()))
+
+ resp.State.RemoveResource(ctx)
+}
+
+// Section below is generated&owned by "gen/generator.go". //template:begin import
+
+func (r *DeviceHAPairMonitoringResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
+ idParts := strings.Split(req.ID, ",")
+
+ if len(idParts) != 2 || idParts[0] == "" || idParts[1] == "" {
+ resp.Diagnostics.AddError(
+ "Unexpected Import Identifier",
+ fmt.Sprintf("Expected import identifier with format: ,. Got: %q", req.ID),
+ )
+ return
+ }
+ resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("device_id"), idParts[0])...)
+ resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("id"), idParts[1])...)
+
+ helpers.SetFlagImporting(ctx, true, resp.Private, &resp.Diagnostics)
+}
+
+// End of section. //template:end import
+
+// Section below is generated&owned by "gen/generator.go". //template:begin createSubresources
+
+// End of section. //template:end createSubresources
+
+// Section below is generated&owned by "gen/generator.go". //template:begin deleteSubresources
+
+// End of section. //template:end deleteSubresources
+
+// Section below is generated&owned by "gen/generator.go". //template:begin updateSubresources
+
+// End of section. //template:end updateSubresources
diff --git a/internal/provider/resource_fmc_device_ha_pair_monitoring_test.go b/internal/provider/resource_fmc_device_ha_pair_monitoring_test.go
new file mode 100644
index 00000000..4f4f230f
--- /dev/null
+++ b/internal/provider/resource_fmc_device_ha_pair_monitoring_test.go
@@ -0,0 +1,104 @@
+// Copyright © 2023 Cisco Systems, Inc. and its affiliates.
+// All rights reserved.
+//
+// Licensed under the Mozilla Public License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://mozilla.org/MPL/2.0/
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// SPDX-License-Identifier: MPL-2.0
+
+package provider
+
+// Section below is generated&owned by "gen/generator.go". //template:begin imports
+import (
+ "os"
+ "testing"
+
+ "github.com/hashicorp/terraform-plugin-testing/helper/resource"
+)
+
+// End of section. //template:end imports
+
+// Section below is generated&owned by "gen/generator.go". //template:begin testAcc
+
+func TestAccFmcDeviceHAPairMonitoring(t *testing.T) {
+ if os.Getenv("TF_VAR_device_ha_id") == "" {
+ t.Skip("skipping test, set environment variable TF_VAR_device_ha_id")
+ }
+ var checks []resource.TestCheckFunc
+ checks = append(checks, resource.TestCheckResourceAttrSet("fmc_device_ha_pair_monitoring.test", "type"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_ha_pair_monitoring.test", "logical_name", "outside"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_ha_pair_monitoring.test", "monitor_interface", "true"))
+ checks = append(checks, resource.TestCheckResourceAttrSet("fmc_device_ha_pair_monitoring.test", "ipv4_active_address"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_ha_pair_monitoring.test", "ipv4_standby_address", "10.1.1.2"))
+ checks = append(checks, resource.TestCheckResourceAttrSet("fmc_device_ha_pair_monitoring.test", "ipv4_netmask"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_ha_pair_monitoring.test", "ipv6_addresses.0.active_address", "2006::1/30"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_device_ha_pair_monitoring.test", "ipv6_addresses.0.standby_address", "2006::2"))
+
+ var steps []resource.TestStep
+ if os.Getenv("SKIP_MINIMUM_TEST") == "" {
+ steps = append(steps, resource.TestStep{
+ Config: testAccFmcDeviceHAPairMonitoringPrerequisitesConfig + testAccFmcDeviceHAPairMonitoringConfig_minimum(),
+ })
+ }
+ steps = append(steps, resource.TestStep{
+ Config: testAccFmcDeviceHAPairMonitoringPrerequisitesConfig + testAccFmcDeviceHAPairMonitoringConfig_all(),
+ Check: resource.ComposeTestCheckFunc(checks...),
+ })
+
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { testAccPreCheck(t) },
+ ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
+ ErrorCheck: func(err error) error { return testAccErrorCheck(t, err) },
+ Steps: steps,
+ })
+}
+
+// End of section. //template:end testAcc
+
+// Section below is generated&owned by "gen/generator.go". //template:begin testPrerequisites
+
+const testAccFmcDeviceHAPairMonitoringPrerequisitesConfig = `
+variable "device_ha_id" { default = null } // tests will set $TF_VAR_device_ha_id
+`
+
+// End of section. //template:end testPrerequisites
+
+// Section below is generated&owned by "gen/generator.go". //template:begin testAccConfigMinimal
+
+func testAccFmcDeviceHAPairMonitoringConfig_minimum() string {
+ config := `resource "fmc_device_ha_pair_monitoring" "test" {` + "\n"
+ config += ` device_id = var.device_ha_id` + "\n"
+ config += ` logical_name = "outside"` + "\n"
+ config += ` monitor_interface = true` + "\n"
+ config += `}` + "\n"
+ return config
+}
+
+// End of section. //template:end testAccConfigMinimal
+
+// Section below is generated&owned by "gen/generator.go". //template:begin testAccConfigAll
+
+func testAccFmcDeviceHAPairMonitoringConfig_all() string {
+ config := `resource "fmc_device_ha_pair_monitoring" "test" {` + "\n"
+ config += ` device_id = var.device_ha_id` + "\n"
+ config += ` logical_name = "outside"` + "\n"
+ config += ` monitor_interface = true` + "\n"
+ config += ` ipv4_standby_address = "10.1.1.2"` + "\n"
+ config += ` ipv6_addresses = [{` + "\n"
+ config += ` active_address = "2006::1/30"` + "\n"
+ config += ` standby_address = "2006::2"` + "\n"
+ config += ` }]` + "\n"
+ config += `}` + "\n"
+ return config
+}
+
+// End of section. //template:end testAccConfigAll
diff --git a/internal/provider/resource_fmc_device_physical_interface.go b/internal/provider/resource_fmc_device_physical_interface.go
index 0aa6e5e1..84da5122 100644
--- a/internal/provider/resource_fmc_device_physical_interface.go
+++ b/internal/provider/resource_fmc_device_physical_interface.go
@@ -498,13 +498,13 @@ func (r *DevicePhysicalInterfaceResource) Create(ctx context.Context, req resour
if !plan.Domain.IsNull() && plan.Domain.ValueString() != "" {
reqMods = append(reqMods, fmc.DomainName(plan.Domain.ValueString()))
}
- tflog.Debug(ctx, fmt.Sprintf("%s: considering object name %s", plan.Id, plan.Name))
+ tflog.Debug(ctx, fmt.Sprintf("%s: considering object name %s", plan.Id, plan.Name))
if plan.Id.ValueString() == "" && plan.Name.ValueString() != "" {
offset := 0
limit := 1000
for page := 1; ; page++ {
- queryString := fmt.Sprintf("?limit=%d&offset=%d", limit, offset)
+ queryString := fmt.Sprintf("?limit=%d&offset=%d&expanded=true", limit, offset)
res, err := r.client.Get(plan.getPath()+queryString, reqMods...)
if err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to retrieve objects, got error: %s", err))
diff --git a/internal/provider/resource_fmc_device_vtep_policy.go b/internal/provider/resource_fmc_device_vtep_policy.go
index 1a91249e..32ee0fe0 100644
--- a/internal/provider/resource_fmc_device_vtep_policy.go
+++ b/internal/provider/resource_fmc_device_vtep_policy.go
@@ -129,9 +129,6 @@ func (r *DeviceVTEPPolicyResource) Schema(ctx context.Context, req resource.Sche
stringvalidator.OneOf("VXLAN", "GENEVE"),
},
Default: stringdefault.StaticString("VXLAN"),
- PlanModifiers: []planmodifier.String{
- stringplanmodifier.RequiresReplace(),
- },
},
"neighbor_discovery": schema.StringAttribute{
MarkdownDescription: helpers.NewAttributeDescription("How to discover addresses of the neighbor VTEPs for the VTEP-to-VTEP communication. For STATIC_PEER_IP and DEFAULT_MULTICAST_GROUP you must set `neighbor_address_literal` to a single IP address. For STATIC_PEER_GROUP you must however set `neighbor_address_id` to a UUID of a network group and such network group can contain only IPv4 Hosts and IPv4 Ranges (but not Networks, etc.).").AddStringEnumDescription("NONE", "STATIC_PEER_IP", "STATIC_PEER_GROUP", "DEFAULT_MULTICAST_GROUP").String,
diff --git a/internal/provider/resource_fmc_network.go b/internal/provider/resource_fmc_network.go
index c96138f1..eac41b2d 100644
--- a/internal/provider/resource_fmc_network.go
+++ b/internal/provider/resource_fmc_network.go
@@ -28,7 +28,6 @@ import (
"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/stringdefault"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-log/tflog"
@@ -83,12 +82,10 @@ func (r *NetworkResource) Schema(ctx context.Context, req resource.SchemaRequest
Required: true,
},
"type": schema.StringAttribute{
- MarkdownDescription: helpers.NewAttributeDescription("Type of the object; this value is always 'Network'.").AddDefaultValueDescription("Network").String,
- Optional: true,
+ MarkdownDescription: helpers.NewAttributeDescription("Type of the object; this value is always 'Network'.").String,
Computed: true,
- Default: stringdefault.StaticString("Network"),
PlanModifiers: []planmodifier.String{
- stringplanmodifier.RequiresReplace(),
+ stringplanmodifier.UseStateForUnknown(),
},
},
"description": schema.StringAttribute{
diff --git a/internal/provider/resource_fmc_networks.go b/internal/provider/resource_fmc_networks.go
index 1597369d..7e9325d9 100644
--- a/internal/provider/resource_fmc_networks.go
+++ b/internal/provider/resource_fmc_networks.go
@@ -32,7 +32,6 @@ import (
"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/stringdefault"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-log/tflog"
@@ -108,10 +107,11 @@ func (r *NetworksResource) Schema(ctx context.Context, req resource.SchemaReques
Required: true,
},
"type": schema.StringAttribute{
- MarkdownDescription: helpers.NewAttributeDescription("Type of the object; this value is always 'Network'.").AddDefaultValueDescription("Network").String,
- Optional: true,
+ MarkdownDescription: helpers.NewAttributeDescription("Type of the object; this value is always 'Network'.").String,
Computed: true,
- Default: stringdefault.StaticString("Network"),
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.UseStateForUnknown(),
+ },
},
},
},
diff --git a/internal/provider/resource_fmc_port_group.go b/internal/provider/resource_fmc_port_group.go
index e3f77c72..c908f395 100644
--- a/internal/provider/resource_fmc_port_group.go
+++ b/internal/provider/resource_fmc_port_group.go
@@ -29,7 +29,6 @@ import (
"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/stringdefault"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
"github.com/hashicorp/terraform-plugin-framework/types"
@@ -85,12 +84,10 @@ func (r *PortGroupResource) Schema(ctx context.Context, req resource.SchemaReque
Required: true,
},
"type": schema.StringAttribute{
- MarkdownDescription: helpers.NewAttributeDescription("Type of the object; this value is always 'PortObjectGroup'.").AddDefaultValueDescription("PortObjectGroup").String,
- Optional: true,
+ MarkdownDescription: helpers.NewAttributeDescription("Type of the object; this value is always 'PortObjectGroup'.").String,
Computed: true,
- Default: stringdefault.StaticString("PortObjectGroup"),
PlanModifiers: []planmodifier.String{
- stringplanmodifier.RequiresReplace(),
+ stringplanmodifier.UseStateForUnknown(),
},
},
"description": schema.StringAttribute{
diff --git a/internal/provider/resource_fmc_port_groups.go b/internal/provider/resource_fmc_port_groups.go
index f0d5e832..ba2dc48c 100644
--- a/internal/provider/resource_fmc_port_groups.go
+++ b/internal/provider/resource_fmc_port_groups.go
@@ -33,7 +33,6 @@ import (
"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/stringdefault"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
"github.com/hashicorp/terraform-plugin-framework/types"
@@ -98,12 +97,10 @@ func (r *PortGroupsResource) Schema(ctx context.Context, req resource.SchemaRequ
},
},
"type": schema.StringAttribute{
- MarkdownDescription: helpers.NewAttributeDescription("Type of the object; this value is always 'PortObjectGroup'.").AddDefaultValueDescription("PortObjectGroup").String,
- Optional: true,
+ MarkdownDescription: helpers.NewAttributeDescription("Type of the object; this value is always 'PortObjectGroup'.").String,
Computed: true,
- Default: stringdefault.StaticString("PortObjectGroup"),
PlanModifiers: []planmodifier.String{
- stringplanmodifier.RequiresReplace(),
+ stringplanmodifier.UseStateForUnknown(),
},
},
"description": schema.StringAttribute{
diff --git a/internal/provider/resource_fmc_security_zone.go b/internal/provider/resource_fmc_security_zone.go
index 494b20c7..8a4f1b4a 100644
--- a/internal/provider/resource_fmc_security_zone.go
+++ b/internal/provider/resource_fmc_security_zone.go
@@ -29,7 +29,6 @@ import (
"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/stringdefault"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
"github.com/hashicorp/terraform-plugin-framework/types"
@@ -84,21 +83,19 @@ func (r *SecurityZoneResource) Schema(ctx context.Context, req resource.SchemaRe
MarkdownDescription: helpers.NewAttributeDescription("User-provided resource name.").String,
Required: true,
},
- "interface_mode": schema.StringAttribute{
+ "interface_type": schema.StringAttribute{
MarkdownDescription: helpers.NewAttributeDescription("The mode of the associated interfaces, with the exception of mode ROUTED that corresponds to mode NONE of associated interfaces.").AddStringEnumDescription("PASSIVE", "INLINE", "SWITCHED", "ROUTED", "ASA").String,
Required: true,
Validators: []validator.String{
stringvalidator.OneOf("PASSIVE", "INLINE", "SWITCHED", "ROUTED", "ASA"),
},
- PlanModifiers: []planmodifier.String{
- stringplanmodifier.RequiresReplace(),
- },
},
"type": schema.StringAttribute{
- MarkdownDescription: helpers.NewAttributeDescription("Type of the object; this value is always 'SecurityZone'.").AddDefaultValueDescription("SecurityZone").String,
- Optional: true,
+ MarkdownDescription: helpers.NewAttributeDescription("Type of the object; this value is always 'SecurityZone'.").String,
Computed: true,
- Default: stringdefault.StaticString("SecurityZone"),
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.UseStateForUnknown(),
+ },
},
},
}
diff --git a/internal/provider/resource_fmc_security_zone_test.go b/internal/provider/resource_fmc_security_zone_test.go
index b178caeb..c535d642 100644
--- a/internal/provider/resource_fmc_security_zone_test.go
+++ b/internal/provider/resource_fmc_security_zone_test.go
@@ -32,7 +32,7 @@ import (
func TestAccFmcSecurityZone(t *testing.T) {
var checks []resource.TestCheckFunc
checks = append(checks, resource.TestCheckResourceAttr("fmc_security_zone.test", "name", "security_zone_1"))
- checks = append(checks, resource.TestCheckResourceAttr("fmc_security_zone.test", "interface_mode", "ROUTED"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_security_zone.test", "interface_type", "ROUTED"))
var steps []resource.TestStep
if os.Getenv("SKIP_MINIMUM_TEST") == "" {
@@ -67,7 +67,7 @@ func TestAccFmcSecurityZone(t *testing.T) {
func testAccFmcSecurityZoneConfig_minimum() string {
config := `resource "fmc_security_zone" "test" {` + "\n"
config += ` name = "security_zone_1"` + "\n"
- config += ` interface_mode = "ROUTED"` + "\n"
+ config += ` interface_type = "ROUTED"` + "\n"
config += `}` + "\n"
return config
}
@@ -79,7 +79,7 @@ func testAccFmcSecurityZoneConfig_minimum() string {
func testAccFmcSecurityZoneConfig_all() string {
config := `resource "fmc_security_zone" "test" {` + "\n"
config += ` name = "security_zone_1"` + "\n"
- config += ` interface_mode = "ROUTED"` + "\n"
+ config += ` interface_type = "ROUTED"` + "\n"
config += `}` + "\n"
return config
}
diff --git a/internal/provider/resource_fmc_security_zones.go b/internal/provider/resource_fmc_security_zones.go
index 162ef4fe..7e0730e4 100644
--- a/internal/provider/resource_fmc_security_zones.go
+++ b/internal/provider/resource_fmc_security_zones.go
@@ -33,7 +33,6 @@ import (
"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/stringdefault"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
"github.com/hashicorp/terraform-plugin-framework/types"
@@ -97,21 +96,19 @@ func (r *SecurityZonesResource) Schema(ctx context.Context, req resource.SchemaR
stringplanmodifier.UseStateForUnknown(),
},
},
- "interface_mode": schema.StringAttribute{
+ "interface_type": schema.StringAttribute{
MarkdownDescription: helpers.NewAttributeDescription("The mode of the associated interfaces, with the exception of mode ROUTED that corresponds to mode NONE of associated interfaces.").AddStringEnumDescription("PASSIVE", "INLINE", "SWITCHED", "ROUTED", "ASA").String,
Required: true,
Validators: []validator.String{
stringvalidator.OneOf("PASSIVE", "INLINE", "SWITCHED", "ROUTED", "ASA"),
},
- PlanModifiers: []planmodifier.String{
- stringplanmodifier.RequiresReplace(),
- },
},
"type": schema.StringAttribute{
- MarkdownDescription: helpers.NewAttributeDescription("Type of the object; this value is always 'SecurityZone'.").AddDefaultValueDescription("SecurityZone").String,
- Optional: true,
+ MarkdownDescription: helpers.NewAttributeDescription("Type of the object; this value is always 'SecurityZone'.").String,
Computed: true,
- Default: stringdefault.StaticString("SecurityZone"),
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.UseStateForUnknown(),
+ },
},
},
},
diff --git a/internal/provider/resource_fmc_security_zones_test.go b/internal/provider/resource_fmc_security_zones_test.go
index 5cd02e4d..7ae4611d 100644
--- a/internal/provider/resource_fmc_security_zones_test.go
+++ b/internal/provider/resource_fmc_security_zones_test.go
@@ -32,7 +32,7 @@ import (
func TestAccFmcSecurityZones(t *testing.T) {
var checks []resource.TestCheckFunc
checks = append(checks, resource.TestCheckResourceAttrSet("fmc_security_zones.test", "items.security_zone_1.id"))
- checks = append(checks, resource.TestCheckResourceAttr("fmc_security_zones.test", "items.security_zone_1.interface_mode", "ROUTED"))
+ checks = append(checks, resource.TestCheckResourceAttr("fmc_security_zones.test", "items.security_zone_1.interface_type", "ROUTED"))
var steps []resource.TestStep
if os.Getenv("SKIP_MINIMUM_TEST") == "" {
@@ -63,7 +63,7 @@ func TestAccFmcSecurityZones(t *testing.T) {
func testAccFmcSecurityZonesConfig_minimum() string {
config := `resource "fmc_security_zones" "test" {` + "\n"
config += ` items = { "security_zone_1" = {` + "\n"
- config += ` interface_mode = "ROUTED"` + "\n"
+ config += ` interface_type = "ROUTED"` + "\n"
config += ` }}` + "\n"
config += `}` + "\n"
return config
@@ -76,7 +76,7 @@ func testAccFmcSecurityZonesConfig_minimum() string {
func testAccFmcSecurityZonesConfig_all() string {
config := `resource "fmc_security_zones" "test" {` + "\n"
config += ` items = { "security_zone_1" = {` + "\n"
- config += ` interface_mode = "ROUTED"` + "\n"
+ config += ` interface_type = "ROUTED"` + "\n"
config += ` }}` + "\n"
config += `}` + "\n"
return config