From 11842519c9771a3eab156504853694624f58a1bf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 22 Mar 2024 00:14:47 +0000 Subject: [PATCH 01/25] deps: bump github.com/hashicorp/terraform-plugin-framework Bumps [github.com/hashicorp/terraform-plugin-framework](https://github.com/hashicorp/terraform-plugin-framework) from 1.6.1 to 1.7.0. - [Release notes](https://github.com/hashicorp/terraform-plugin-framework/releases) - [Changelog](https://github.com/hashicorp/terraform-plugin-framework/blob/main/CHANGELOG.md) - [Commits](https://github.com/hashicorp/terraform-plugin-framework/compare/v1.6.1...v1.7.0) --- updated-dependencies: - dependency-name: github.com/hashicorp/terraform-plugin-framework dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 9ec8bbf4..e9fdaa06 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.21 require ( github.com/google/go-cmp v0.6.0 github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 - github.com/hashicorp/terraform-plugin-framework v1.6.1 + github.com/hashicorp/terraform-plugin-framework v1.7.0 github.com/hashicorp/terraform-plugin-framework-validators v0.12.0 github.com/hashicorp/terraform-plugin-go v0.22.1 github.com/hashicorp/terraform-plugin-mux v0.15.0 diff --git a/go.sum b/go.sum index 9b6a23b0..b3059272 100644 --- a/go.sum +++ b/go.sum @@ -72,8 +72,8 @@ github.com/hashicorp/terraform-exec v0.20.0 h1:DIZnPsqzPGuUnq6cH8jWcPunBfY+C+M8J github.com/hashicorp/terraform-exec v0.20.0/go.mod h1:ckKGkJWbsNqFKV1itgMnE0hY9IYf1HoiekpuN0eWoDw= github.com/hashicorp/terraform-json v0.21.0 h1:9NQxbLNqPbEMze+S6+YluEdXgJmhQykRyRNd+zTI05U= github.com/hashicorp/terraform-json v0.21.0/go.mod h1:qdeBs11ovMzo5puhrRibdD6d2Dq6TyE/28JiU4tIQxk= -github.com/hashicorp/terraform-plugin-framework v1.6.1 h1:hw2XrmUu8d8jVL52ekxim2IqDc+2Kpekn21xZANARLU= -github.com/hashicorp/terraform-plugin-framework v1.6.1/go.mod h1:aJI+n/hBPhz1J+77GdgNfk5svW12y7fmtxe/5L5IuwI= +github.com/hashicorp/terraform-plugin-framework v1.7.0 h1:wOULbVmfONnJo9iq7/q+iBOBJul5vRovaYJIu2cY/Pw= +github.com/hashicorp/terraform-plugin-framework v1.7.0/go.mod h1:jY9Id+3KbZ17OMpulgnWLSfwxNVYSoYBQFTgsx044CI= github.com/hashicorp/terraform-plugin-framework-validators v0.12.0 h1:HOjBuMbOEzl7snOdOoUfE2Jgeto6JOjLVQ39Ls2nksc= github.com/hashicorp/terraform-plugin-framework-validators v0.12.0/go.mod h1:jfHGE/gzjxYz6XoUwi/aYiiKrJDeutQNUtGQXkaHklg= github.com/hashicorp/terraform-plugin-go v0.22.1 h1:iTS7WHNVrn7uhe3cojtvWWn83cm2Z6ryIUDTRO0EV7w= From a405a308753e9d7e0151a8552d6465fbb06633e0 Mon Sep 17 00:00:00 2001 From: Jeremy Muriel Date: Fri, 22 Mar 2024 16:24:00 +0100 Subject: [PATCH 02/25] tests: bump golangci-lint to v1.57 disable deactivated deprecated linters reorder field of struct to align on schema order (after disable maligned linter) --- .github/workflows/linters.yml | 2 +- .golangci.yml | 4 +- docs/resources/eventoptions_generate_event.md | 4 +- docs/resources/forwardingoptions_sampling.md | 8 +- docs/resources/security.md | 4 +- internal/junos/client.go | 24 ++-- .../providerfwk/data_source_applications.go | 36 ++--- .../data_source_interface_logical.go | 2 +- .../data_source_interface_physical.go | 16 +-- .../providerfwk/data_source_security_zone.go | 8 +- .../providerfwk/resource_aggregate_route.go | 24 ++-- internal/providerfwk/resource_application.go | 6 +- internal/providerfwk/resource_bgp_group.go | 80 +++++------ internal/providerfwk/resource_bgp_neighbor.go | 80 +++++------ .../providerfwk/resource_bridge_domain.go | 10 +- .../resource_eventoptions_generate_event.go | 26 ++-- .../resource_eventoptions_policy.go | 12 +- internal/providerfwk/resource_evpn.go | 8 +- .../providerfwk/resource_firewall_filter.go | 28 ++-- .../providerfwk/resource_firewall_policer.go | 6 +- .../resource_forwardingoptions_sampling.go | 62 ++++----- ...rce_forwardingoptions_sampling_instance.go | 20 +-- ...forwardingoptions_storm_control_profile.go | 8 +- .../providerfwk/resource_generate_route.go | 24 ++-- internal/providerfwk/resource_iccp_peer.go | 2 +- .../providerfwk/resource_interface_logical.go | 100 +++++++------- .../resource_interface_physical.go | 50 +++---- internal/providerfwk/resource_multichassis.go | 2 +- .../resource_policyoptions_as_path.go | 2 +- .../resource_policyoptions_as_path_group.go | 4 +- .../resource_policyoptions_community.go | 8 +- ...resource_policyoptions_policy_statement.go | 12 +- .../resource_policyoptions_prefix_list.go | 2 +- .../providerfwk/resource_routing_instance.go | 12 +- internal/providerfwk/resource_security.go | 34 ++--- .../resource_security_global_policy.go | 28 ++-- .../resource_security_ike_gateway.go | 8 +- .../resource_security_ipsec_vpn.go | 8 +- .../resource_security_nat_static.go | 4 +- .../providerfwk/resource_security_policy.go | 36 ++--- .../providerfwk/resource_security_zone.go | 24 ++-- ...rce_services_flowmonitoring_v9_template.go | 28 ++-- ...services_flowmonitoring_vipfix_template.go | 28 ++-- internal/providerfwk/resource_snmp.go | 22 +-- .../providerfwk/resource_snmp_community.go | 8 +- internal/providerfwk/resource_static_route.go | 48 +++---- .../providerfwk/resource_switch_options.go | 2 +- internal/providerfwk/resource_system.go | 126 +++++++++--------- .../resource_system_syslog_file.go | 16 +-- .../resource_system_syslog_host.go | 4 +- .../resource_system_syslog_user.go | 2 +- .../resource_system_tacplus_server.go | 2 +- .../providerfwk/resource_virtual_chassis.go | 24 ++-- internal/providerfwk/resourcedata_bgp.go | 6 +- .../providerfwk/upgradestate_bgp_group.go | 38 +++--- .../providerfwk/upgradestate_bgp_neighbor.go | 38 +++--- .../providerfwk/upgradestate_bridge_domain.go | 6 +- .../upgradestate_eventoptions_policy.go | 6 +- internal/providerfwk/upgradestate_evpn.go | 4 +- .../upgradestate_firewall_filter.go | 16 +-- .../upgradestate_firewall_policer.go | 4 +- ...ate_forwardingoptions_sampling_instance.go | 26 ++-- .../upgradestate_interface_logical.go | 60 ++++----- .../upgradestate_interface_physical.go | 20 +-- ...adestate_policyoptions_policy_statement.go | 2 +- internal/providerfwk/upgradestate_security.go | 22 +-- .../upgradestate_security_global_policy.go | 22 +-- .../upgradestate_security_ike_gateway.go | 26 ++-- .../upgradestate_security_ipsec_vpn.go | 4 +- .../upgradestate_security_nat_static.go | 2 +- .../upgradestate_security_policy.go | 18 +-- ...services_flowmonitoring_vipfix_template.go | 12 +- internal/providerfwk/upgradestate_snmp.go | 12 +- internal/providerfwk/upgradestate_system.go | 64 ++++----- .../upgradestate_system_syslog_file.go | 8 +- .../upgradestate_system_syslog_host.go | 4 +- 76 files changed, 784 insertions(+), 784 deletions(-) diff --git a/.github/workflows/linters.yml b/.github/workflows/linters.yml index 847faf8e..d66917b7 100644 --- a/.github/workflows/linters.yml +++ b/.github/workflows/linters.yml @@ -19,7 +19,7 @@ jobs: - name: golangci-lint uses: golangci/golangci-lint-action@v4 with: - version: 'v1.56.1' + version: 'v1.57.1' args: -c .golangci.yml -v markdown-lint: diff --git a/.golangci.yml b/.golangci.yml index 26aef4bc..2d942ac0 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -3,12 +3,12 @@ run: linters: enable-all: true disable: - # maligned # deprecated 1.38 but govet-fieldalignment not usuable + - maligned # deprecated 1.38 - interfacer # deprecated 1.38 - scopelint # deprecated 1.39 - golint # deprecated 1.41 - exhaustivestruct # deprecated 1.46 - # ifshort deprecated 1.48 but no replacement + - ifshort # deprecated 1.48 - deadcode # deprecated 1.49 - structcheck # deprecated 1.49 - varcheck # deprecated 1.49 diff --git a/docs/resources/eventoptions_generate_event.md b/docs/resources/eventoptions_generate_event.md index 81474d90..bbb61189 100644 --- a/docs/resources/eventoptions_generate_event.md +++ b/docs/resources/eventoptions_generate_event.md @@ -24,6 +24,8 @@ The following arguments are supported: - **name** (Required, String, Forces new resource) Name of the event to be generated. +- **no_drift** (Optional, Boolean) + Avoid event generation delay propagating to next event. - **start_time** (Optional, String) Start-time to generate event (YYYY-MM-DD.HH:MM:SS). `time_interval` need to be set. @@ -31,8 +33,6 @@ The following arguments are supported: Frequency for generating the event (60..2592000 seconds). - **time_of_day** (Optional, String) Time of day at which to generate event (HH:MM:SS). -- **no_drift** (Optional, Boolean) - Avoid event generation delay propagating to next event. ## Attribute Reference diff --git a/docs/resources/forwardingoptions_sampling.md b/docs/resources/forwardingoptions_sampling.md index 47144cfc..59450375 100644 --- a/docs/resources/forwardingoptions_sampling.md +++ b/docs/resources/forwardingoptions_sampling.md @@ -99,16 +99,16 @@ The following arguments are supported: Disable sampled packet dumps. - **files** (Optional, Number) Maximum number of sampled packet dump files (2..10000). - - **no_stamp** (Optional, Boolean) - Don't timestamp every packet in the dump. - - **no_world_readable** (Optional, Boolean) - Don't allow any user to read the sampled dump. - **size** (Optional, Number) Maximum sample dump file size (1024..104857600). - **stamp** (Optional, Boolean) Timestamp every packet in the dump. + - **no_stamp** (Optional, Boolean) + Don't timestamp every packet in the dump. - **world_readable** (Optional, Boolean) Allow any user to read the sampled dump. + - **no_world_readable** (Optional, Boolean) + Don't allow any user to read the sampled dump. - **flow_active_timeout** (Optional, Number) Interval after which an active flow is exported (60..1800 seconds). - **flow_inactive_timeout** (Optional, Number) diff --git a/docs/resources/security.md b/docs/resources/security.md index 4436d346..a4d1b30a 100644 --- a/docs/resources/security.md +++ b/docs/resources/security.md @@ -175,12 +175,12 @@ The following arguments are supported: Maximum number of trace files (2..1000). - **match** (Optional, String) Regular expression for lines to be logged. -- **no_world_readable** (Optional, Boolean) - Don't allow any user to read the log file. - **size** (Optional, Number) Maximum trace file size (10240..1073741824). - **world_readable** (Optional, Boolean) Allow any user to read the log file. +- **no_world_readable** (Optional, Boolean) + Don't allow any user to read the log file. --- diff --git a/internal/junos/client.go b/internal/junos/client.go index 33137c80..79e2f683 100644 --- a/internal/junos/client.go +++ b/internal/junos/client.go @@ -8,27 +8,27 @@ const directoryPermission = 0o755 // Client information to connect on Junos Device and more. type Client struct { - fakeUpdateAlso bool - fakeDeleteAlso bool - junosCommitConfirmed int - junosCommitConfirmedWaitPercent int - junosPort int - junosSSHTimeoutToEstab int - junosSSHRetryToEstab int - sleepLock int - sleepShort int - sleepSSHClosed int - filePermission int64 junosIP string + junosPort int junosUserName string junosPassword string junosSSHKeyPEM string junosSSHKeyFile string junosSSHKeyPass string groupIntDel string + sleepShort int + sleepLock int + junosCommitConfirmed int + junosCommitConfirmedWaitPercent int + sleepSSHClosed int + junosSSHCiphers []string + junosSSHTimeoutToEstab int + junosSSHRetryToEstab int + filePermission int64 logFileDst string fakeCreateSetFile string - junosSSHCiphers []string + fakeUpdateAlso bool + fakeDeleteAlso bool } func NewClient(ip string) *Client { diff --git a/internal/providerfwk/data_source_applications.go b/internal/providerfwk/data_source_applications.go index 6dc0391e..eb74af02 100644 --- a/internal/providerfwk/data_source_applications.go +++ b/internal/providerfwk/data_source_applications.go @@ -186,25 +186,8 @@ func (dsc *applicationsDataSource) Schema( type applicationsDataSourceData struct { ID types.String `tfsdk:"id"` MatchName types.String `tfsdk:"match_name"` - MatchOptions []applicationsDataSourceBlockMatchOptions `tfsdk:"match_options"` Applications []applicationsDataSourceBlockApplications `tfsdk:"applications"` -} - -type applicationsDataSourceBlockMatchOptions struct { - Alg types.String `tfsdk:"alg"` - ApplicationProtocol types.String `tfsdk:"application_protocol"` - DestinationPort types.String `tfsdk:"destination_port"` - EtherType types.String `tfsdk:"ether_type"` - IcmpCode types.String `tfsdk:"icmp_code"` - IcmpType types.String `tfsdk:"icmp_type"` - Icmp6Code types.String `tfsdk:"icmp6_code"` - Icmp6Type types.String `tfsdk:"icmp6_type"` - InactivityTimeout types.Int64 `tfsdk:"inactivity_timeout"` - InactivityTimeoutNever types.Bool `tfsdk:"inactivity_timeout_never"` - Protocol types.String `tfsdk:"protocol"` - RPCRrogramNumber types.String `tfsdk:"rpc_program_number"` - SourcePort types.String `tfsdk:"source_port"` - UUID types.String `tfsdk:"uuid"` + MatchOptions []applicationsDataSourceBlockMatchOptions `tfsdk:"match_options"` } type applicationsDataSourceBlockApplications struct { @@ -238,6 +221,23 @@ type applicationsDataSourceBlockApplicationsBlockTerm struct { UUID types.String `tfsdk:"uuid"` } +type applicationsDataSourceBlockMatchOptions struct { + Alg types.String `tfsdk:"alg"` + ApplicationProtocol types.String `tfsdk:"application_protocol"` + DestinationPort types.String `tfsdk:"destination_port"` + EtherType types.String `tfsdk:"ether_type"` + IcmpCode types.String `tfsdk:"icmp_code"` + IcmpType types.String `tfsdk:"icmp_type"` + Icmp6Code types.String `tfsdk:"icmp6_code"` + Icmp6Type types.String `tfsdk:"icmp6_type"` + InactivityTimeout types.Int64 `tfsdk:"inactivity_timeout"` + InactivityTimeoutNever types.Bool `tfsdk:"inactivity_timeout_never"` + Protocol types.String `tfsdk:"protocol"` + RPCRrogramNumber types.String `tfsdk:"rpc_program_number"` + SourcePort types.String `tfsdk:"source_port"` + UUID types.String `tfsdk:"uuid"` +} + func (dsc *applicationsDataSource) Read( ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse, ) { diff --git a/internal/providerfwk/data_source_interface_logical.go b/internal/providerfwk/data_source_interface_logical.go index 13579c7a..3e2ed9da 100644 --- a/internal/providerfwk/data_source_interface_logical.go +++ b/internal/providerfwk/data_source_interface_logical.go @@ -265,12 +265,12 @@ func (dsc *interfaceLogicalDataSource) Schema( } type interfaceLogicalDataSourceData struct { - Disable types.Bool `tfsdk:"disable"` ID types.String `tfsdk:"id"` ConfigInterface types.String `tfsdk:"config_interface"` Match types.String `tfsdk:"match"` Name types.String `tfsdk:"name"` Description types.String `tfsdk:"description"` + Disable types.Bool `tfsdk:"disable"` RoutingInstance types.String `tfsdk:"routing_instance"` SecurityInboundProtocols []types.String `tfsdk:"security_inbound_protocols"` SecurityInboundServices []types.String `tfsdk:"security_inbound_services"` diff --git a/internal/providerfwk/data_source_interface_physical.go b/internal/providerfwk/data_source_interface_physical.go index d7be1582..fbc73ab0 100644 --- a/internal/providerfwk/data_source_interface_physical.go +++ b/internal/providerfwk/data_source_interface_physical.go @@ -270,29 +270,29 @@ func (dsc *interfacePhysicalDataSource) Schema( } type interfacePhysicalDataSourceData struct { - Disable types.Bool `tfsdk:"disable"` - FlexibleVlanTagging types.Bool `tfsdk:"flexible_vlan_tagging"` - GratuitousArpReply types.Bool `tfsdk:"gratuitous_arp_reply"` - NoGratuitousArpReply types.Bool `tfsdk:"no_gratuitous_arp_reply"` - NoGratuitousArpRequest types.Bool `tfsdk:"no_gratuitous_arp_request"` - Trunk types.Bool `tfsdk:"trunk"` - TrunkNonELS types.Bool `tfsdk:"trunk_non_els"` - VlanTagging types.Bool `tfsdk:"vlan_tagging"` ID types.String `tfsdk:"id"` ConfigInterface types.String `tfsdk:"config_interface"` Match types.String `tfsdk:"match"` Name types.String `tfsdk:"name"` Description types.String `tfsdk:"description"` + Disable types.Bool `tfsdk:"disable"` Encapsulation types.String `tfsdk:"encapsulation"` + FlexibleVlanTagging types.Bool `tfsdk:"flexible_vlan_tagging"` + GratuitousArpReply types.Bool `tfsdk:"gratuitous_arp_reply"` + NoGratuitousArpReply types.Bool `tfsdk:"no_gratuitous_arp_reply"` HoldTimeDown types.Int64 `tfsdk:"hold_time_down"` HoldTimeUp types.Int64 `tfsdk:"hold_time_up"` LinkMode types.String `tfsdk:"link_mode"` Mtu types.Int64 `tfsdk:"mtu"` + NoGratuitousArpRequest types.Bool `tfsdk:"no_gratuitous_arp_request"` Speed types.String `tfsdk:"speed"` StormControl types.String `tfsdk:"storm_control"` + Trunk types.Bool `tfsdk:"trunk"` + TrunkNonELS types.Bool `tfsdk:"trunk_non_els"` VlanMembers []types.String `tfsdk:"vlan_members"` VlanNative types.Int64 `tfsdk:"vlan_native"` VlanNativeNonELS types.String `tfsdk:"vlan_native_non_els"` + VlanTagging types.Bool `tfsdk:"vlan_tagging"` ESI *interfacePhysicalBlockESI `tfsdk:"esi"` EtherOpts *interfacePhysicalBlockEtherOpts `tfsdk:"ether_opts"` GigetherOpts *interfacePhysicalBlockEtherOpts `tfsdk:"gigether_opts"` diff --git a/internal/providerfwk/data_source_security_zone.go b/internal/providerfwk/data_source_security_zone.go index a6cea275..a9ade348 100644 --- a/internal/providerfwk/data_source_security_zone.go +++ b/internal/providerfwk/data_source_security_zone.go @@ -195,17 +195,17 @@ func (dsc *securityZoneDataSource) Schema( } type securityZoneDataSourceData struct { - ApplicationTracking types.Bool `tfsdk:"application_tracking"` - ReverseReroute types.Bool `tfsdk:"reverse_reroute"` - SourceIdentityLog types.Bool `tfsdk:"source_identity_log"` - TCPRst types.Bool `tfsdk:"tcp_rst"` ID types.String `tfsdk:"id"` Name types.String `tfsdk:"name"` AdvancePolicyBasedRoutingProfile types.String `tfsdk:"advance_policy_based_routing_profile"` + ApplicationTracking types.Bool `tfsdk:"application_tracking"` Description types.String `tfsdk:"description"` Screen types.String `tfsdk:"screen"` InboundProtocols []types.String `tfsdk:"inbound_protocols"` InboundServices []types.String `tfsdk:"inbound_services"` + ReverseReroute types.Bool `tfsdk:"reverse_reroute"` + SourceIdentityLog types.Bool `tfsdk:"source_identity_log"` + TCPRst types.Bool `tfsdk:"tcp_rst"` AddressBook []securityZoneBlockAddressBook `tfsdk:"address_book"` AddressBookDNS []securityZoneBlockAddressBookDNS `tfsdk:"address_book_dns"` AddressBookRange []securityZoneBlockAddressBookRange `tfsdk:"address_book_range"` diff --git a/internal/providerfwk/resource_aggregate_route.go b/internal/providerfwk/resource_aggregate_route.go index b1b32c93..15f26955 100644 --- a/internal/providerfwk/resource_aggregate_route.go +++ b/internal/providerfwk/resource_aggregate_route.go @@ -229,41 +229,41 @@ func (rsc *aggregateRoute) Schema( } type aggregateRouteData struct { - Active types.Bool `tfsdk:"active"` - ASPathAtomicAggregate types.Bool `tfsdk:"as_path_atomic_aggregate"` - Brief types.Bool `tfsdk:"brief"` - Discard types.Bool `tfsdk:"discard"` - Full types.Bool `tfsdk:"full"` - Passive types.Bool `tfsdk:"passive"` ID types.String `tfsdk:"id"` Destination types.String `tfsdk:"destination"` RoutingInstance types.String `tfsdk:"routing_instance"` + Active types.Bool `tfsdk:"active"` ASPathAggregatorAddress types.String `tfsdk:"as_path_aggregator_address"` ASPathAggregatorASNumber types.String `tfsdk:"as_path_aggregator_as_number"` + ASPathAtomicAggregate types.Bool `tfsdk:"as_path_atomic_aggregate"` ASPathOrigin types.String `tfsdk:"as_path_origin"` ASPathPath types.String `tfsdk:"as_path_path"` + Brief types.Bool `tfsdk:"brief"` Community []types.String `tfsdk:"community"` + Discard types.Bool `tfsdk:"discard"` + Full types.Bool `tfsdk:"full"` Metric types.Int64 `tfsdk:"metric"` + Passive types.Bool `tfsdk:"passive"` Policy []types.String `tfsdk:"policy"` Preference types.Int64 `tfsdk:"preference"` } type aggregateRouteConfig struct { - Active types.Bool `tfsdk:"active"` - ASPathAtomicAggregate types.Bool `tfsdk:"as_path_atomic_aggregate"` - Brief types.Bool `tfsdk:"brief"` - Discard types.Bool `tfsdk:"discard"` - Full types.Bool `tfsdk:"full"` - Passive types.Bool `tfsdk:"passive"` ID types.String `tfsdk:"id"` Destination types.String `tfsdk:"destination"` RoutingInstance types.String `tfsdk:"routing_instance"` + Active types.Bool `tfsdk:"active"` ASPathAggregatorAddress types.String `tfsdk:"as_path_aggregator_address"` ASPathAggregatorASNumber types.String `tfsdk:"as_path_aggregator_as_number"` + ASPathAtomicAggregate types.Bool `tfsdk:"as_path_atomic_aggregate"` ASPathOrigin types.String `tfsdk:"as_path_origin"` ASPathPath types.String `tfsdk:"as_path_path"` + Brief types.Bool `tfsdk:"brief"` Community types.List `tfsdk:"community"` + Discard types.Bool `tfsdk:"discard"` + Full types.Bool `tfsdk:"full"` Metric types.Int64 `tfsdk:"metric"` + Passive types.Bool `tfsdk:"passive"` Policy types.List `tfsdk:"policy"` Preference types.Int64 `tfsdk:"preference"` } diff --git a/internal/providerfwk/resource_application.go b/internal/providerfwk/resource_application.go index 7033ac05..c2fdbb56 100644 --- a/internal/providerfwk/resource_application.go +++ b/internal/providerfwk/resource_application.go @@ -300,7 +300,6 @@ func (rsc *application) Schema( } type applicationData struct { - InactivityTimeoutNever types.Bool `tfsdk:"inactivity_timeout_never"` ID types.String `tfsdk:"id"` Name types.String `tfsdk:"name"` ApplicationProtocol types.String `tfsdk:"application_protocol"` @@ -308,6 +307,7 @@ type applicationData struct { DestinationPort types.String `tfsdk:"destination_port"` EtherType types.String `tfsdk:"ether_type"` InactivityTimeout types.Int64 `tfsdk:"inactivity_timeout"` + InactivityTimeoutNever types.Bool `tfsdk:"inactivity_timeout_never"` Protocol types.String `tfsdk:"protocol"` RPCProgramNumber types.String `tfsdk:"rpc_program_number"` SourcePort types.String `tfsdk:"source_port"` @@ -316,7 +316,6 @@ type applicationData struct { } type applicationConfig struct { - InactivityTimeoutNever types.Bool `tfsdk:"inactivity_timeout_never"` ID types.String `tfsdk:"id"` Name types.String `tfsdk:"name"` ApplicationProtocol types.String `tfsdk:"application_protocol"` @@ -324,6 +323,7 @@ type applicationConfig struct { DestinationPort types.String `tfsdk:"destination_port"` EtherType types.String `tfsdk:"ether_type"` InactivityTimeout types.Int64 `tfsdk:"inactivity_timeout"` + InactivityTimeoutNever types.Bool `tfsdk:"inactivity_timeout_never"` Protocol types.String `tfsdk:"protocol"` RPCProgramNumber types.String `tfsdk:"rpc_program_number"` SourcePort types.String `tfsdk:"source_port"` @@ -332,7 +332,6 @@ type applicationConfig struct { } type applicationBlockTerm struct { - InactivityTimeoutNever types.Bool `tfsdk:"inactivity_timeout_never"` Name types.String `tfsdk:"name"` Protocol types.String `tfsdk:"protocol"` Alg types.String `tfsdk:"alg"` @@ -342,6 +341,7 @@ type applicationBlockTerm struct { Icmp6Code types.String `tfsdk:"icmp6_code"` Icmp6Type types.String `tfsdk:"icmp6_type"` InactivityTimeout types.Int64 `tfsdk:"inactivity_timeout"` + InactivityTimeoutNever types.Bool `tfsdk:"inactivity_timeout_never"` RPCRrogramNumber types.String `tfsdk:"rpc_program_number"` SourcePort types.String `tfsdk:"source_port"` UUID types.String `tfsdk:"uuid"` diff --git a/internal/providerfwk/resource_bgp_group.go b/internal/providerfwk/resource_bgp_group.go index a824694d..f4bdc7ce 100644 --- a/internal/providerfwk/resource_bgp_group.go +++ b/internal/providerfwk/resource_bgp_group.go @@ -762,6 +762,10 @@ func (rsc *bgpGroup) schemaFamilyPrefixLimitAttributes() map[string]schema.Attri } type bgpGroupData struct { + ID types.String `tfsdk:"id"` + Name types.String `tfsdk:"name"` + RoutingInstance types.String `tfsdk:"routing_instance"` + Type types.String `tfsdk:"type"` AcceptRemoteNexthop types.Bool `tfsdk:"accept_remote_nexthop"` AdvertiseExternal types.Bool `tfsdk:"advertise_external"` AdvertiseExternalConditional types.Bool `tfsdk:"advertise_external_conditional"` @@ -769,45 +773,41 @@ type bgpGroupData struct { AdvertisePeerAS types.Bool `tfsdk:"advertise_peer_as"` NoAdvertisePeerAS types.Bool `tfsdk:"no_advertise_peer_as"` ASOverride types.Bool `tfsdk:"as_override"` - Damping types.Bool `tfsdk:"damping"` - KeepAll types.Bool `tfsdk:"keep_all"` - KeepNone types.Bool `tfsdk:"keep_none"` - LocalASAlias types.Bool `tfsdk:"local_as_alias"` - LocalASNoPrependGlobalAS types.Bool `tfsdk:"local_as_no_prepend_global_as"` - LocalASPrivate types.Bool `tfsdk:"local_as_private"` - LogUpdown types.Bool `tfsdk:"log_updown"` - MetricOutIgp types.Bool `tfsdk:"metric_out_igp"` - MetricOutIgpDelayMedUpdate types.Bool `tfsdk:"metric_out_igp_delay_med_update"` - MetricOutMinimumIgp types.Bool `tfsdk:"metric_out_minimum_igp"` - MtuDiscovery types.Bool `tfsdk:"mtu_discovery"` - Multihop types.Bool `tfsdk:"multihop"` - NoClientReflect types.Bool `tfsdk:"no_client_reflect"` - Passive types.Bool `tfsdk:"passive"` - RemovePrivate types.Bool `tfsdk:"remove_private"` - TCPAggressiveTransmission types.Bool `tfsdk:"tcp_aggressive_transmission"` AuthenticationAlgorithm types.String `tfsdk:"authentication_algorithm"` AuthenticationKey types.String `tfsdk:"authentication_key"` AuthenticationKeyChain types.String `tfsdk:"authentication_key_chain"` Cluster types.String `tfsdk:"cluster"` + Damping types.Bool `tfsdk:"damping"` Description types.String `tfsdk:"description"` Export []types.String `tfsdk:"export"` HoldTime types.Int64 `tfsdk:"hold_time"` - ID types.String `tfsdk:"id"` Import []types.String `tfsdk:"import"` + KeepAll types.Bool `tfsdk:"keep_all"` + KeepNone types.Bool `tfsdk:"keep_none"` LocalAddress types.String `tfsdk:"local_address"` LocalAS types.String `tfsdk:"local_as"` + LocalASAlias types.Bool `tfsdk:"local_as_alias"` LocalASLoops types.Int64 `tfsdk:"local_as_loops"` + LocalASNoPrependGlobalAS types.Bool `tfsdk:"local_as_no_prepend_global_as"` + LocalASPrivate types.Bool `tfsdk:"local_as_private"` LocalInterface types.String `tfsdk:"local_interface"` LocalPreference types.Int64 `tfsdk:"local_preference"` + LogUpdown types.Bool `tfsdk:"log_updown"` MetricOut types.Int64 `tfsdk:"metric_out"` + MetricOutIgp types.Bool `tfsdk:"metric_out_igp"` + MetricOutIgpDelayMedUpdate types.Bool `tfsdk:"metric_out_igp_delay_med_update"` MetricOutIgpOffset types.Int64 `tfsdk:"metric_out_igp_offset"` + MetricOutMinimumIgp types.Bool `tfsdk:"metric_out_minimum_igp"` MetricOutMinimumIgpOffset types.Int64 `tfsdk:"metric_out_minimum_igp_offset"` - Name types.String `tfsdk:"name"` + MtuDiscovery types.Bool `tfsdk:"mtu_discovery"` + Multihop types.Bool `tfsdk:"multihop"` + NoClientReflect types.Bool `tfsdk:"no_client_reflect"` OutDelay types.Int64 `tfsdk:"out_delay"` + Passive types.Bool `tfsdk:"passive"` PeerAS types.String `tfsdk:"peer_as"` Preference types.Int64 `tfsdk:"preference"` - RoutingInstance types.String `tfsdk:"routing_instance"` - Type types.String `tfsdk:"type"` + RemovePrivate types.Bool `tfsdk:"remove_private"` + TCPAggressiveTransmission types.Bool `tfsdk:"tcp_aggressive_transmission"` BfdLivenessDetection *bgpBlockBfdLivenessDetection `tfsdk:"bfd_liveness_detection"` BgpErrorTolerance *bgpBlockBgpErrorTolerance `tfsdk:"bgp_error_tolerance"` BgpMultipath *bgpBlockBgpMultipath `tfsdk:"bgp_multipath"` @@ -818,6 +818,10 @@ type bgpGroupData struct { } type bgpGroupConfig struct { + ID types.String `tfsdk:"id"` + Name types.String `tfsdk:"name"` + RoutingInstance types.String `tfsdk:"routing_instance"` + Type types.String `tfsdk:"type"` AcceptRemoteDesktop types.Bool `tfsdk:"accept_remote_nexthop"` AdvertiseExternal types.Bool `tfsdk:"advertise_external"` AdvertiseExternalConditional types.Bool `tfsdk:"advertise_external_conditional"` @@ -825,45 +829,41 @@ type bgpGroupConfig struct { AdvertisePeerAS types.Bool `tfsdk:"advertise_peer_as"` NoAdvertisePeerAS types.Bool `tfsdk:"no_advertise_peer_as"` ASOverride types.Bool `tfsdk:"as_override"` - Damping types.Bool `tfsdk:"damping"` - KeepAll types.Bool `tfsdk:"keep_all"` - KeepNone types.Bool `tfsdk:"keep_none"` - LocalASAlias types.Bool `tfsdk:"local_as_alias"` - LocalASNoPrependGlobalAS types.Bool `tfsdk:"local_as_no_prepend_global_as"` - LocalASPrivate types.Bool `tfsdk:"local_as_private"` - LogUpdown types.Bool `tfsdk:"log_updown"` - MetricOutIgp types.Bool `tfsdk:"metric_out_igp"` - MetricOutIgpDelayMedUpdate types.Bool `tfsdk:"metric_out_igp_delay_med_update"` - MetricOutMinimumIgp types.Bool `tfsdk:"metric_out_minimum_igp"` - MtuDiscovery types.Bool `tfsdk:"mtu_discovery"` - Multihop types.Bool `tfsdk:"multihop"` - NoClientReflect types.Bool `tfsdk:"no_client_reflect"` - Passive types.Bool `tfsdk:"passive"` - RemotePrivate types.Bool `tfsdk:"remove_private"` - TCPAggressiveTransmission types.Bool `tfsdk:"tcp_aggressive_transmission"` AuthenticationAlgorithm types.String `tfsdk:"authentication_algorithm"` AuthenticationKey types.String `tfsdk:"authentication_key"` AuthenticationKeyChain types.String `tfsdk:"authentication_key_chain"` Cluster types.String `tfsdk:"cluster"` + Damping types.Bool `tfsdk:"damping"` Description types.String `tfsdk:"description"` Export types.List `tfsdk:"export"` HoldTime types.Int64 `tfsdk:"hold_time"` - ID types.String `tfsdk:"id"` Import types.List `tfsdk:"import"` + KeepAll types.Bool `tfsdk:"keep_all"` + KeepNone types.Bool `tfsdk:"keep_none"` LocalAddress types.String `tfsdk:"local_address"` LocalAS types.String `tfsdk:"local_as"` + LocalASAlias types.Bool `tfsdk:"local_as_alias"` LocalASLoops types.Int64 `tfsdk:"local_as_loops"` + LocalASNoPrependGlobalAS types.Bool `tfsdk:"local_as_no_prepend_global_as"` + LocalASPrivate types.Bool `tfsdk:"local_as_private"` LocalInterface types.String `tfsdk:"local_interface"` LocalPreference types.Int64 `tfsdk:"local_preference"` + LogUpdown types.Bool `tfsdk:"log_updown"` MetricOut types.Int64 `tfsdk:"metric_out"` + MetricOutIgp types.Bool `tfsdk:"metric_out_igp"` + MetricOutIgpDelayMedUpdate types.Bool `tfsdk:"metric_out_igp_delay_med_update"` MetricOutIgpOffset types.Int64 `tfsdk:"metric_out_igp_offset"` + MetricOutMinimumIgp types.Bool `tfsdk:"metric_out_minimum_igp"` MetricOutMinimumIgpOffset types.Int64 `tfsdk:"metric_out_minimum_igp_offset"` - Name types.String `tfsdk:"name"` + MtuDiscovery types.Bool `tfsdk:"mtu_discovery"` + Multihop types.Bool `tfsdk:"multihop"` + NoClientReflect types.Bool `tfsdk:"no_client_reflect"` OutDelay types.Int64 `tfsdk:"out_delay"` + Passive types.Bool `tfsdk:"passive"` PeerAS types.String `tfsdk:"peer_as"` Preference types.Int64 `tfsdk:"preference"` - RoutingInstance types.String `tfsdk:"routing_instance"` - Type types.String `tfsdk:"type"` + RemotePrivate types.Bool `tfsdk:"remove_private"` + TCPAggressiveTransmission types.Bool `tfsdk:"tcp_aggressive_transmission"` BfdLivenessDetection *bgpBlockBfdLivenessDetection `tfsdk:"bfd_liveness_detection"` BgpErrorTolerance *bgpBlockBgpErrorTolerance `tfsdk:"bgp_error_tolerance"` BgpMultipah *bgpBlockBgpMultipath `tfsdk:"bgp_multipath"` diff --git a/internal/providerfwk/resource_bgp_neighbor.go b/internal/providerfwk/resource_bgp_neighbor.go index eec808e3..3307dfa3 100644 --- a/internal/providerfwk/resource_bgp_neighbor.go +++ b/internal/providerfwk/resource_bgp_neighbor.go @@ -761,6 +761,10 @@ func (rsc *bgpNeighbor) schemaFamilyPrefixLimitAttributes() map[string]schema.At } type bgpNeighborData struct { + ID types.String `tfsdk:"id"` + IP types.String `tfsdk:"ip"` + RoutingInstance types.String `tfsdk:"routing_instance"` + Group types.String `tfsdk:"group"` AcceptRemoteNexthop types.Bool `tfsdk:"accept_remote_nexthop"` AdvertiseExternal types.Bool `tfsdk:"advertise_external"` AdvertiseExternalConditional types.Bool `tfsdk:"advertise_external_conditional"` @@ -768,45 +772,41 @@ type bgpNeighborData struct { AdvertisePeerAS types.Bool `tfsdk:"advertise_peer_as"` NoAdvertisePeerAS types.Bool `tfsdk:"no_advertise_peer_as"` ASOverride types.Bool `tfsdk:"as_override"` - Damping types.Bool `tfsdk:"damping"` - KeepAll types.Bool `tfsdk:"keep_all"` - KeepNone types.Bool `tfsdk:"keep_none"` - LocalASAlias types.Bool `tfsdk:"local_as_alias"` - LocalASNoPrependGlobalAS types.Bool `tfsdk:"local_as_no_prepend_global_as"` - LocalASPrivate types.Bool `tfsdk:"local_as_private"` - LogUpdown types.Bool `tfsdk:"log_updown"` - MetricOutIgp types.Bool `tfsdk:"metric_out_igp"` - MetricOutIgpDelayMedUpdate types.Bool `tfsdk:"metric_out_igp_delay_med_update"` - MetricOutMinimumIgp types.Bool `tfsdk:"metric_out_minimum_igp"` - MtuDiscovery types.Bool `tfsdk:"mtu_discovery"` - Multihop types.Bool `tfsdk:"multihop"` - NoClientReflect types.Bool `tfsdk:"no_client_reflect"` - Passive types.Bool `tfsdk:"passive"` - RemovePrivate types.Bool `tfsdk:"remove_private"` - TCPAggressiveTransmission types.Bool `tfsdk:"tcp_aggressive_transmission"` AuthenticationAlgorithm types.String `tfsdk:"authentication_algorithm"` AuthenticationKey types.String `tfsdk:"authentication_key"` AuthenticationKeyChain types.String `tfsdk:"authentication_key_chain"` Cluster types.String `tfsdk:"cluster"` + Damping types.Bool `tfsdk:"damping"` Description types.String `tfsdk:"description"` Export []types.String `tfsdk:"export"` - Group types.String `tfsdk:"group"` HoldTime types.Int64 `tfsdk:"hold_time"` - ID types.String `tfsdk:"id"` Import []types.String `tfsdk:"import"` - IP types.String `tfsdk:"ip"` + KeepAll types.Bool `tfsdk:"keep_all"` + KeepNone types.Bool `tfsdk:"keep_none"` LocalAddress types.String `tfsdk:"local_address"` LocalAS types.String `tfsdk:"local_as"` + LocalASAlias types.Bool `tfsdk:"local_as_alias"` LocalASLoops types.Int64 `tfsdk:"local_as_loops"` + LocalASNoPrependGlobalAS types.Bool `tfsdk:"local_as_no_prepend_global_as"` + LocalASPrivate types.Bool `tfsdk:"local_as_private"` LocalInterface types.String `tfsdk:"local_interface"` LocalPreference types.Int64 `tfsdk:"local_preference"` + LogUpdown types.Bool `tfsdk:"log_updown"` MetricOut types.Int64 `tfsdk:"metric_out"` + MetricOutIgp types.Bool `tfsdk:"metric_out_igp"` + MetricOutIgpDelayMedUpdate types.Bool `tfsdk:"metric_out_igp_delay_med_update"` MetricOutIgpOffset types.Int64 `tfsdk:"metric_out_igp_offset"` + MetricOutMinimumIgp types.Bool `tfsdk:"metric_out_minimum_igp"` MetricOutMinimumIgpOffset types.Int64 `tfsdk:"metric_out_minimum_igp_offset"` + MtuDiscovery types.Bool `tfsdk:"mtu_discovery"` + Multihop types.Bool `tfsdk:"multihop"` + NoClientReflect types.Bool `tfsdk:"no_client_reflect"` OutDelay types.Int64 `tfsdk:"out_delay"` + Passive types.Bool `tfsdk:"passive"` PeerAS types.String `tfsdk:"peer_as"` Preference types.Int64 `tfsdk:"preference"` - RoutingInstance types.String `tfsdk:"routing_instance"` + RemovePrivate types.Bool `tfsdk:"remove_private"` + TCPAggressiveTransmission types.Bool `tfsdk:"tcp_aggressive_transmission"` BfdLivenessDetection *bgpBlockBfdLivenessDetection `tfsdk:"bfd_liveness_detection"` BgpErrorTolerance *bgpBlockBgpErrorTolerance `tfsdk:"bgp_error_tolerance"` BgpMultipath *bgpBlockBgpMultipath `tfsdk:"bgp_multipath"` @@ -817,6 +817,10 @@ type bgpNeighborData struct { } type bgpNeighborConfig struct { + ID types.String `tfsdk:"id"` + IP types.String `tfsdk:"ip"` + RoutingInstance types.String `tfsdk:"routing_instance"` + Group types.String `tfsdk:"group"` AcceptRemoteDesktop types.Bool `tfsdk:"accept_remote_nexthop"` AdvertiseExternal types.Bool `tfsdk:"advertise_external"` AdvertiseExternalConditional types.Bool `tfsdk:"advertise_external_conditional"` @@ -824,45 +828,41 @@ type bgpNeighborConfig struct { AdvertisePeerAS types.Bool `tfsdk:"advertise_peer_as"` NoAdvertisePeerAS types.Bool `tfsdk:"no_advertise_peer_as"` ASOverride types.Bool `tfsdk:"as_override"` - Damping types.Bool `tfsdk:"damping"` - KeepAll types.Bool `tfsdk:"keep_all"` - KeepNone types.Bool `tfsdk:"keep_none"` - LocalASAlias types.Bool `tfsdk:"local_as_alias"` - LocalASNoPrependGlobalAS types.Bool `tfsdk:"local_as_no_prepend_global_as"` - LocalASPrivate types.Bool `tfsdk:"local_as_private"` - LogUpdown types.Bool `tfsdk:"log_updown"` - MetricOutIgp types.Bool `tfsdk:"metric_out_igp"` - MetricOutIgpDelayMedUpdate types.Bool `tfsdk:"metric_out_igp_delay_med_update"` - MetricOutMinimumIgp types.Bool `tfsdk:"metric_out_minimum_igp"` - MtuDiscovery types.Bool `tfsdk:"mtu_discovery"` - Multihop types.Bool `tfsdk:"multihop"` - NoClientReflect types.Bool `tfsdk:"no_client_reflect"` - Passive types.Bool `tfsdk:"passive"` - RemotePrivate types.Bool `tfsdk:"remove_private"` - TCPAggressiveTransmission types.Bool `tfsdk:"tcp_aggressive_transmission"` AuthenticationAlgorithm types.String `tfsdk:"authentication_algorithm"` AuthenticationKey types.String `tfsdk:"authentication_key"` AuthenticationKeyChain types.String `tfsdk:"authentication_key_chain"` Cluster types.String `tfsdk:"cluster"` + Damping types.Bool `tfsdk:"damping"` Description types.String `tfsdk:"description"` Export types.List `tfsdk:"export"` - Group types.String `tfsdk:"group"` HoldTime types.Int64 `tfsdk:"hold_time"` - ID types.String `tfsdk:"id"` Import types.List `tfsdk:"import"` - IP types.String `tfsdk:"ip"` + KeepAll types.Bool `tfsdk:"keep_all"` + KeepNone types.Bool `tfsdk:"keep_none"` LocalAddress types.String `tfsdk:"local_address"` LocalAS types.String `tfsdk:"local_as"` + LocalASAlias types.Bool `tfsdk:"local_as_alias"` LocalASLoops types.Int64 `tfsdk:"local_as_loops"` + LocalASNoPrependGlobalAS types.Bool `tfsdk:"local_as_no_prepend_global_as"` + LocalASPrivate types.Bool `tfsdk:"local_as_private"` LocalInterface types.String `tfsdk:"local_interface"` LocalPreference types.Int64 `tfsdk:"local_preference"` + LogUpdown types.Bool `tfsdk:"log_updown"` MetricOut types.Int64 `tfsdk:"metric_out"` + MetricOutIgp types.Bool `tfsdk:"metric_out_igp"` + MetricOutIgpDelayMedUpdate types.Bool `tfsdk:"metric_out_igp_delay_med_update"` MetricOutIgpOffset types.Int64 `tfsdk:"metric_out_igp_offset"` + MetricOutMinimumIgp types.Bool `tfsdk:"metric_out_minimum_igp"` MetricOutMinimumIgpOffset types.Int64 `tfsdk:"metric_out_minimum_igp_offset"` + MtuDiscovery types.Bool `tfsdk:"mtu_discovery"` + Multihop types.Bool `tfsdk:"multihop"` + NoClientReflect types.Bool `tfsdk:"no_client_reflect"` OutDelay types.Int64 `tfsdk:"out_delay"` + Passive types.Bool `tfsdk:"passive"` PeerAS types.String `tfsdk:"peer_as"` Preference types.Int64 `tfsdk:"preference"` - RoutingInstance types.String `tfsdk:"routing_instance"` + RemotePrivate types.Bool `tfsdk:"remove_private"` + TCPAggressiveTransmission types.Bool `tfsdk:"tcp_aggressive_transmission"` BfdLivenessDetection *bgpBlockBfdLivenessDetection `tfsdk:"bfd_liveness_detection"` BgpErrorTolerance *bgpBlockBgpErrorTolerance `tfsdk:"bgp_error_tolerance"` BgpMultipah *bgpBlockBgpMultipath `tfsdk:"bgp_multipath"` diff --git a/internal/providerfwk/resource_bridge_domain.go b/internal/providerfwk/resource_bridge_domain.go index b664bad9..8580cc63 100644 --- a/internal/providerfwk/resource_bridge_domain.go +++ b/internal/providerfwk/resource_bridge_domain.go @@ -278,13 +278,13 @@ func (rsc *bridgeDomain) Schema( } type bridgeDomainData struct { - DomainTypeBridge types.Bool `tfsdk:"domain_type_bridge"` ID types.String `tfsdk:"id"` Name types.String `tfsdk:"name"` RoutingInstance types.String `tfsdk:"routing_instance"` CommunityVlans []types.String `tfsdk:"community_vlans"` Description types.String `tfsdk:"description"` DomainID types.Int64 `tfsdk:"domain_id"` + DomainTypeBridge types.Bool `tfsdk:"domain_type_bridge"` Interface []types.String `tfsdk:"interface"` IsolatedVLAN types.Int64 `tfsdk:"isolated_vlan"` RoutingInterface types.String `tfsdk:"routing_interface"` @@ -295,13 +295,13 @@ type bridgeDomainData struct { } type bridgeDomainConfig struct { - DomainTypeBridge types.Bool `tfsdk:"domain_type_bridge"` ID types.String `tfsdk:"id"` Name types.String `tfsdk:"name"` RoutingInstance types.String `tfsdk:"routing_instance"` CommunityVlans types.Set `tfsdk:"community_vlans"` Description types.String `tfsdk:"description"` DomainID types.Int64 `tfsdk:"domain_id"` + DomainTypeBridge types.Bool `tfsdk:"domain_type_bridge"` Interface types.Set `tfsdk:"interface"` IsolatedVLAN types.Int64 `tfsdk:"isolated_vlan"` RoutingInterface types.String `tfsdk:"routing_interface"` @@ -316,14 +316,14 @@ func (rscConfig *bridgeDomainConfig) isEmpty() bool { } type bridgeDomainBlockVXLAN struct { - VNIExtendEvpn types.Bool `tfsdk:"vni_extend_evpn"` + VNI types.Int64 `tfsdk:"vni"` DecapsulateAcceptInnerVlan types.Bool `tfsdk:"decapsulate_accept_inner_vlan"` EncapsulateInnerVlan types.Bool `tfsdk:"encapsulate_inner_vlan"` IngressNodeReplication types.Bool `tfsdk:"ingress_node_replication"` - OvsdbManaged types.Bool `tfsdk:"ovsdb_managed"` - VNI types.Int64 `tfsdk:"vni"` MulticastGroup types.String `tfsdk:"multicast_group"` + OvsdbManaged types.Bool `tfsdk:"ovsdb_managed"` UnreachableVtepAgingTimer types.Int64 `tfsdk:"unreachable_vtep_aging_timer"` + VNIExtendEvpn types.Bool `tfsdk:"vni_extend_evpn"` } func (rsc *bridgeDomain) ValidateConfig( diff --git a/internal/providerfwk/resource_eventoptions_generate_event.go b/internal/providerfwk/resource_eventoptions_generate_event.go index 9f77d63b..98056b00 100644 --- a/internal/providerfwk/resource_eventoptions_generate_event.go +++ b/internal/providerfwk/resource_eventoptions_generate_event.go @@ -97,6 +97,13 @@ func (rsc *eventoptionsGenerateEvent) Schema( tfvalidator.StringDoubleQuoteExclusion(), }, }, + "no_drift": schema.BoolAttribute{ + Optional: true, + Description: "Avoid event generation delay propagating to next event.", + Validators: []validator.Bool{ + tfvalidator.BoolTrue(), + }, + }, "start_time": schema.StringAttribute{ Optional: true, Description: "Start-time to generate event.", @@ -124,21 +131,14 @@ func (rsc *eventoptionsGenerateEvent) Schema( ), }, }, - "no_drift": schema.BoolAttribute{ - Optional: true, - Description: "Avoid event generation delay propagating to next event.", - Validators: []validator.Bool{ - tfvalidator.BoolTrue(), - }, - }, }, } } type eventoptionsGenerateEventData struct { - NoDrift types.Bool `tfsdk:"no_drift"` ID types.String `tfsdk:"id"` Name types.String `tfsdk:"name"` + NoDrift types.Bool `tfsdk:"no_drift"` StartTime types.String `tfsdk:"start_time"` TimeInterval types.Int64 `tfsdk:"time_interval"` TimeOfDay types.String `tfsdk:"time_of_day"` @@ -349,6 +349,9 @@ func (rscData *eventoptionsGenerateEventData) set( configSet := make([]string, 0) setPrefix := "set event-options generate-event \"" + rscData.Name.ValueString() + "\" " + if rscData.NoDrift.ValueBool() { + configSet = append(configSet, setPrefix+"no-drift") + } if v := rscData.StartTime.ValueString(); v != "" { configSet = append(configSet, setPrefix+"start-time "+v) } @@ -359,9 +362,6 @@ func (rscData *eventoptionsGenerateEventData) set( if v := rscData.TimeOfDay.ValueString(); v != "" { configSet = append(configSet, setPrefix+"time-of-day "+v) } - if rscData.NoDrift.ValueBool() { - configSet = append(configSet, setPrefix+"no-drift") - } return path.Empty(), junSess.ConfigSet(configSet) } @@ -388,6 +388,8 @@ func (rscData *eventoptionsGenerateEventData) read( } itemTrim := strings.TrimPrefix(item, junos.SetLS) switch { + case itemTrim == "no-drift": + rscData.NoDrift = types.BoolValue(true) case balt.CutPrefixInString(&itemTrim, "start-time "): rscData.StartTime = types.StringValue(strings.Split(strings.Trim(itemTrim, "\""), " ")[0]) case balt.CutPrefixInString(&itemTrim, "time-interval "): @@ -397,8 +399,6 @@ func (rscData *eventoptionsGenerateEventData) read( } case balt.CutPrefixInString(&itemTrim, "time-of-day "): rscData.TimeOfDay = types.StringValue(strings.Split(strings.Trim(itemTrim, "\""), " ")[0]) - case itemTrim == "no-drift": - rscData.NoDrift = types.BoolValue(true) } } } diff --git a/internal/providerfwk/resource_eventoptions_policy.go b/internal/providerfwk/resource_eventoptions_policy.go index 1368f940..e5065336 100644 --- a/internal/providerfwk/resource_eventoptions_policy.go +++ b/internal/providerfwk/resource_eventoptions_policy.go @@ -609,9 +609,9 @@ type eventoptionsPolicyConfig struct { type eventoptionsPolicyBlockThen struct { Ignore types.Bool `tfsdk:"ignore"` - RaiseTrap types.Bool `tfsdk:"raise_trap"` PriorityOverrideFacility types.String `tfsdk:"priority_override_facility"` PriorityOverrideSeverity types.String `tfsdk:"priority_override_severity"` + RaiseTrap types.Bool `tfsdk:"raise_trap"` ChangeConfiguration *eventoptionsPolicyBlockThenBlockChangeConfigurtion `tfsdk:"change_configuration"` EventScript []eventoptionsPolicyBlockThenBlockEventScript `tfsdk:"event_script"` ExecuteCommands *eventoptionsPolicyBlockThenBlockExecuteCommands `tfsdk:"execute_commands"` @@ -624,9 +624,9 @@ func (block *eventoptionsPolicyBlockThen) isEmpty() bool { type eventoptionsPolicyBlockThenConfig struct { Ignore types.Bool `tfsdk:"ignore"` - RaiseTrap types.Bool `tfsdk:"raise_trap"` PriorityOverrideFacility types.String `tfsdk:"priority_override_facility"` PriorityOverrideSeverity types.String `tfsdk:"priority_override_severity"` + RaiseTrap types.Bool `tfsdk:"raise_trap"` ChangeConfiguration *eventoptionsPolicyBlockThenBlockChangeConfigurtionConfig `tfsdk:"change_configuration"` EventScript types.List `tfsdk:"event_script"` ExecuteCommands *eventoptionsPolicyBlockThenBlockExecuteCommandsConfig `tfsdk:"execute_commands"` @@ -638,24 +638,24 @@ func (block *eventoptionsPolicyBlockThenConfig) isEmpty() bool { } type eventoptionsPolicyBlockThenBlockChangeConfigurtion struct { + Commands []types.String `tfsdk:"commands"` CommitOptionsCheck types.Bool `tfsdk:"commit_options_check"` CommitOptionsCheckSynchronize types.Bool `tfsdk:"commit_options_check_synchronize"` CommitOptionsForce types.Bool `tfsdk:"commit_options_force"` - CommitOptionsSynchronize types.Bool `tfsdk:"commit_options_synchronize"` - Commands []types.String `tfsdk:"commands"` CommitOptionsLog types.String `tfsdk:"commit_options_log"` + CommitOptionsSynchronize types.Bool `tfsdk:"commit_options_synchronize"` RetryCount types.Int64 `tfsdk:"retry_count"` RetryInterval types.Int64 `tfsdk:"retry_interval"` Username types.String `tfsdk:"user_name"` } type eventoptionsPolicyBlockThenBlockChangeConfigurtionConfig struct { + Commands types.List `tfsdk:"commands"` CommitOptionsCheck types.Bool `tfsdk:"commit_options_check"` CommitOptionsCheckSynchronize types.Bool `tfsdk:"commit_options_check_synchronize"` CommitOptionsForce types.Bool `tfsdk:"commit_options_force"` - CommitOptionsSynchronize types.Bool `tfsdk:"commit_options_synchronize"` - Commands types.List `tfsdk:"commands"` CommitOptionsLog types.String `tfsdk:"commit_options_log"` + CommitOptionsSynchronize types.Bool `tfsdk:"commit_options_synchronize"` RetryCount types.Int64 `tfsdk:"retry_count"` RetryInterval types.Int64 `tfsdk:"retry_interval"` Username types.String `tfsdk:"user_name"` diff --git a/internal/providerfwk/resource_evpn.go b/internal/providerfwk/resource_evpn.go index 96e1d366..397f4ac2 100644 --- a/internal/providerfwk/resource_evpn.go +++ b/internal/providerfwk/resource_evpn.go @@ -252,23 +252,23 @@ func (rsc *evpn) Schema( } type evpnData struct { - RoutingInstanceEvpn types.Bool `tfsdk:"routing_instance_evpn"` ID types.String `tfsdk:"id"` RoutingInstance types.String `tfsdk:"routing_instance"` Encapsulation types.String `tfsdk:"encapsulation"` DefaultGateway types.String `tfsdk:"default_gateway"` MulticastMode types.String `tfsdk:"multicast_mode"` + RoutingInstanceEvpn types.Bool `tfsdk:"routing_instance_evpn"` DuplicateMacDetection *evpnBlockDuplicateMACDetection `tfsdk:"duplicate_mac_detection"` SwitchOrRIOptions *evpnBlockSwitchOrRIOptions `tfsdk:"switch_or_ri_options"` } type evpnConfig struct { - RoutingInstanceEvpn types.Bool `tfsdk:"routing_instance_evpn"` ID types.String `tfsdk:"id"` RoutingInstance types.String `tfsdk:"routing_instance"` Encapsulation types.String `tfsdk:"encapsulation"` DefaultGateway types.String `tfsdk:"default_gateway"` MulticastMode types.String `tfsdk:"multicast_mode"` + RoutingInstanceEvpn types.Bool `tfsdk:"routing_instance_evpn"` DuplicateMacDetection *evpnBlockDuplicateMACDetection `tfsdk:"duplicate_mac_detection"` SwitchOrRIOptions *evpnBlockSwitchOrRIOptionsConfig `tfsdk:"switch_or_ri_options"` } @@ -284,21 +284,21 @@ func (block *evpnBlockDuplicateMACDetection) isEmpty() bool { } type evpnBlockSwitchOrRIOptions struct { - VRFTargetAuto types.Bool `tfsdk:"vrf_target_auto"` RouteDistinguisher types.String `tfsdk:"route_distinguisher"` VRFExport []types.String `tfsdk:"vrf_export"` VRFImport []types.String `tfsdk:"vrf_import"` VRFTarget types.String `tfsdk:"vrf_target"` + VRFTargetAuto types.Bool `tfsdk:"vrf_target_auto"` VRFTargetExport types.String `tfsdk:"vrf_target_export"` VRFTargetImport types.String `tfsdk:"vrf_target_import"` } type evpnBlockSwitchOrRIOptionsConfig struct { - VRFTargetAuto types.Bool `tfsdk:"vrf_target_auto"` RouteDistinguisher types.String `tfsdk:"route_distinguisher"` VRFExport types.List `tfsdk:"vrf_export"` VRFImport types.List `tfsdk:"vrf_import"` VRFTarget types.String `tfsdk:"vrf_target"` + VRFTargetAuto types.Bool `tfsdk:"vrf_target_auto"` VRFTargetExport types.String `tfsdk:"vrf_target_export"` VRFTargetImport types.String `tfsdk:"vrf_target_import"` } diff --git a/internal/providerfwk/resource_firewall_filter.go b/internal/providerfwk/resource_firewall_filter.go index 9ce28d25..efae953b 100644 --- a/internal/providerfwk/resource_firewall_filter.go +++ b/internal/providerfwk/resource_firewall_filter.go @@ -761,18 +761,18 @@ func (rsc *firewallFilter) Schema( } type firewallFilterData struct { - InterfaceSpecific types.Bool `tfsdk:"interface_specific"` ID types.String `tfsdk:"id"` Name types.String `tfsdk:"name"` Family types.String `tfsdk:"family"` + InterfaceSpecific types.Bool `tfsdk:"interface_specific"` Term []firewallFilterBlockTerm `tfsdk:"term"` } type firewallFilterConfig struct { - InterfaceSpecific types.Bool `tfsdk:"interface_specific"` ID types.String `tfsdk:"id"` Name types.String `tfsdk:"name"` Family types.String `tfsdk:"family"` + InterfaceSpecific types.Bool `tfsdk:"interface_specific"` Term types.List `tfsdk:"term"` } @@ -795,9 +795,6 @@ func (block *firewallFilterBlockTermConfig) isEmpty() bool { } type firewallFilterBlockTermBlockFrom struct { - IsFragment types.Bool `tfsdk:"is_fragment"` - TCPEstablished types.Bool `tfsdk:"tcp_established"` - TCPInitial types.Bool `tfsdk:"tcp_initial"` Address []types.String `tfsdk:"address"` AddressExcept []types.String `tfsdk:"address_except"` DestinationAddress []types.String `tfsdk:"destination_address"` @@ -815,6 +812,7 @@ type firewallFilterBlockTermBlockFrom struct { IcmpType []types.String `tfsdk:"icmp_type"` IcmpTypeExcept []types.String `tfsdk:"icmp_type_except"` Interface []types.String `tfsdk:"interface"` + IsFragment types.Bool `tfsdk:"is_fragment"` LossPriority []types.String `tfsdk:"loss_priority"` LossPriorityExcept []types.String `tfsdk:"loss_priority_except"` NextHeader []types.String `tfsdk:"next_header"` @@ -837,13 +835,12 @@ type firewallFilterBlockTermBlockFrom struct { SourcePortExcept []types.String `tfsdk:"source_port_except"` SourcePrefixList []types.String `tfsdk:"source_prefix_list"` SourcePrefixListExcept []types.String `tfsdk:"source_prefix_list_except"` + TCPEstablished types.Bool `tfsdk:"tcp_established"` TCPFlags types.String `tfsdk:"tcp_flags"` + TCPInitial types.Bool `tfsdk:"tcp_initial"` } type firewallFilterBlockTermBlockFromConfig struct { - IsFragment types.Bool `tfsdk:"is_fragment"` - TCPEstablished types.Bool `tfsdk:"tcp_established"` - TCPInitial types.Bool `tfsdk:"tcp_initial"` Address types.Set `tfsdk:"address"` AddressExcept types.Set `tfsdk:"address_except"` DestinationAddress types.Set `tfsdk:"destination_address"` @@ -861,6 +858,7 @@ type firewallFilterBlockTermBlockFromConfig struct { IcmpType types.Set `tfsdk:"icmp_type"` IcmpTypeExcept types.Set `tfsdk:"icmp_type_except"` Interface types.Set `tfsdk:"interface"` + IsFragment types.Bool `tfsdk:"is_fragment"` LossPriority types.Set `tfsdk:"loss_priority"` LossPriorityExcept types.Set `tfsdk:"loss_priority_except"` NextHeader types.Set `tfsdk:"next_header"` @@ -883,7 +881,9 @@ type firewallFilterBlockTermBlockFromConfig struct { SourcePortExcept types.Set `tfsdk:"source_port_except"` SourcePrefixList types.Set `tfsdk:"source_prefix_list"` SourcePrefixListExcept types.Set `tfsdk:"source_prefix_list_except"` + TCPEstablished types.Bool `tfsdk:"tcp_established"` TCPFlags types.String `tfsdk:"tcp_flags"` + TCPInitial types.Bool `tfsdk:"tcp_initial"` } func (block *firewallFilterBlockTermBlockFromConfig) isEmpty() bool { @@ -891,18 +891,18 @@ func (block *firewallFilterBlockTermBlockFromConfig) isEmpty() bool { } type firewallFilterBlockTermBlockThen struct { - Log types.Bool `tfsdk:"log"` - PacketMode types.Bool `tfsdk:"packet_mode"` - PortMirror types.Bool `tfsdk:"port_mirror"` - Sample types.Bool `tfsdk:"sample"` - ServiceAccounting types.Bool `tfsdk:"service_accounting"` - Syslog types.Bool `tfsdk:"syslog"` Action types.String `tfsdk:"action"` Count types.String `tfsdk:"count"` ForwardingClass types.String `tfsdk:"forwarding_class"` + Log types.Bool `tfsdk:"log"` LossPriority types.String `tfsdk:"loss_priority"` + PacketMode types.Bool `tfsdk:"packet_mode"` Policer types.String `tfsdk:"policer"` + PortMirror types.Bool `tfsdk:"port_mirror"` RoutingInstance types.String `tfsdk:"routing_instance"` + Sample types.Bool `tfsdk:"sample"` + ServiceAccounting types.Bool `tfsdk:"service_accounting"` + Syslog types.Bool `tfsdk:"syslog"` } func (block *firewallFilterBlockTermBlockThen) isEmpty() bool { diff --git a/internal/providerfwk/resource_firewall_policer.go b/internal/providerfwk/resource_firewall_policer.go index 0579d48c..79d637b9 100644 --- a/internal/providerfwk/resource_firewall_policer.go +++ b/internal/providerfwk/resource_firewall_policer.go @@ -240,13 +240,13 @@ func (rsc *firewallPolicer) Schema( } type firewallPolicerData struct { + ID types.String `tfsdk:"id"` + Name types.String `tfsdk:"name"` FilterSpecific types.Bool `tfsdk:"filter_specific"` LogicalBandwidthPolicer types.Bool `tfsdk:"logical_bandwidth_policer"` LogicalInterfacePolicer types.Bool `tfsdk:"logical_interface_policer"` PhysicalInterfacePolicer types.Bool `tfsdk:"physical_interface_policer"` SharedBandwidthPolicer types.Bool `tfsdk:"shared_bandwidth_policer"` - ID types.String `tfsdk:"id"` - Name types.String `tfsdk:"name"` IfExceeding *firewallPolicerBlockIfExceeding `tfsdk:"if_exceeding"` IfExceedingPPS *firewallPolicerBlockIfExceedingPPS `tfsdk:"if_exceeding_pps"` Then *firewallPolicerBlockThen `tfsdk:"then"` @@ -273,9 +273,9 @@ func (block *firewallPolicerBlockIfExceedingPPS) hasKnownValue() bool { type firewallPolicerBlockThen struct { Discard types.Bool `tfsdk:"discard"` - OutOfProfile types.Bool `tfsdk:"out_of_profile"` ForwardingClass types.String `tfsdk:"forwarding_class"` LossPriority types.String `tfsdk:"loss_priority"` + OutOfProfile types.Bool `tfsdk:"out_of_profile"` } func (block *firewallPolicerBlockThen) isEmpty() bool { diff --git a/internal/providerfwk/resource_forwardingoptions_sampling.go b/internal/providerfwk/resource_forwardingoptions_sampling.go index 0f139da5..a50c43f6 100644 --- a/internal/providerfwk/resource_forwardingoptions_sampling.go +++ b/internal/providerfwk/resource_forwardingoptions_sampling.go @@ -165,20 +165,6 @@ func (rsc *forwardingoptionsSampling) Schema( int64validator.Between(2, 10000), }, }, - "no_stamp": schema.BoolAttribute{ - Optional: true, - Description: "Don't timestamp every packet in the dump.", - Validators: []validator.Bool{ - tfvalidator.BoolTrue(), - }, - }, - "no_world_readable": schema.BoolAttribute{ - Optional: true, - Description: "Don't allow any user to read the sampled dump.", - Validators: []validator.Bool{ - tfvalidator.BoolTrue(), - }, - }, "size": schema.Int64Attribute{ Optional: true, Description: "Maximum sample dump file size (1024..104857600).", @@ -193,6 +179,13 @@ func (rsc *forwardingoptionsSampling) Schema( tfvalidator.BoolTrue(), }, }, + "no_stamp": schema.BoolAttribute{ + Optional: true, + Description: "Don't timestamp every packet in the dump.", + Validators: []validator.Bool{ + tfvalidator.BoolTrue(), + }, + }, "world_readable": schema.BoolAttribute{ Optional: true, Description: "Allow any user to read the sampled dump.", @@ -200,6 +193,13 @@ func (rsc *forwardingoptionsSampling) Schema( tfvalidator.BoolTrue(), }, }, + "no_world_readable": schema.BoolAttribute{ + Optional: true, + Description: "Don't allow any user to read the sampled dump.", + Validators: []validator.Bool{ + tfvalidator.BoolTrue(), + }, + }, }, PlanModifiers: []planmodifier.Object{ tfplanmodifier.BlockRemoveNull(), @@ -663,11 +663,11 @@ func (rsc *forwardingoptionsSampling) schemaOutputInterfaceAttributes() map[stri } type forwardingoptionsSamplingData struct { + ID types.String `tfsdk:"id"` + RoutingInstance types.String `tfsdk:"routing_instance"` Disable types.Bool `tfsdk:"disable"` PreRewriteTos types.Bool `tfsdk:"pre_rewrite_tos"` SampleOnce types.Bool `tfsdk:"sample_once"` - ID types.String `tfsdk:"id"` - RoutingInstance types.String `tfsdk:"routing_instance"` FamilyInetInput *forwardingoptionsSamplingBlockInput `tfsdk:"family_inet_input"` FamilyInetOutput *forwardingoptionsSamplingBlockFamilyInetOutput `tfsdk:"family_inet_output"` FamilyInet6Input *forwardingoptionsSamplingBlockInput `tfsdk:"family_inet6_input"` @@ -678,11 +678,11 @@ type forwardingoptionsSamplingData struct { } type forwardingoptionsSamplingConfig struct { + ID types.String `tfsdk:"id"` + RoutingInstance types.String `tfsdk:"routing_instance"` Disable types.Bool `tfsdk:"disable"` PreRewriteTos types.Bool `tfsdk:"pre_rewrite_tos"` SampleOnce types.Bool `tfsdk:"sample_once"` - ID types.String `tfsdk:"id"` - RoutingInstance types.String `tfsdk:"routing_instance"` FamilyInetInput *forwardingoptionsSamplingBlockInput `tfsdk:"family_inet_input"` FamilyInetOutput *forwardingoptionsSamplingBlockFamilyInetOutputConfig `tfsdk:"family_inet_output"` FamilyInet6Input *forwardingoptionsSamplingBlockInput `tfsdk:"family_inet6_input"` @@ -737,31 +737,31 @@ func (block *forwardingoptionsSamplingBlockFamilyInetOutputConfig) isEmpty() boo } type forwardingoptionsSamplingBlockFamilyInetOutputBlockFile struct { - Disable types.Bool `tfsdk:"disable"` - NoStamp types.Bool `tfsdk:"no_stamp"` - NoWorldReadable types.Bool `tfsdk:"no_world_readable"` - Stamp types.Bool `tfsdk:"stamp"` - WorldReadable types.Bool `tfsdk:"world_readable"` Filename types.String `tfsdk:"filename"` + Disable types.Bool `tfsdk:"disable"` Files types.Int64 `tfsdk:"files"` Size types.Int64 `tfsdk:"size"` + Stamp types.Bool `tfsdk:"stamp"` + NoStamp types.Bool `tfsdk:"no_stamp"` + WorldReadable types.Bool `tfsdk:"world_readable"` + NoWorldReadable types.Bool `tfsdk:"no_world_readable"` } //nolint:lll type forwardingoptionsSamplingBlockFamilyInetOutputBlockFlowServer struct { + Hostname types.String `tfsdk:"hostname"` + Port types.Int64 `tfsdk:"port"` AggregationAutonomousSystem types.Bool `tfsdk:"aggregation_autonomous_system"` AggregationDestinationPrefix types.Bool `tfsdk:"aggregation_destination_prefix"` AggregationProtocolPort types.Bool `tfsdk:"aggregation_protocol_port"` AggregationSourceDestinationPrefix types.Bool `tfsdk:"aggregation_source_destination_prefix"` AggregationSourceDestinationPrefixCaidaCompliant types.Bool `tfsdk:"aggregation_source_destination_prefix_caida_compliant"` AggregationSourcePrefix types.Bool `tfsdk:"aggregation_source_prefix"` - LocalDump types.Bool `tfsdk:"local_dump"` - NoLocalDump types.Bool `tfsdk:"no_local_dump"` - Hostname types.String `tfsdk:"hostname"` - Port types.Int64 `tfsdk:"port"` AutonomousSystemType types.String `tfsdk:"autonomous_system_type"` Dscp types.Int64 `tfsdk:"dscp"` ForwardingClass types.String `tfsdk:"forwarding_class"` + LocalDump types.Bool `tfsdk:"local_dump"` + NoLocalDump types.Bool `tfsdk:"no_local_dump"` RoutingInstance types.String `tfsdk:"routing_instance"` SourceAddress types.String `tfsdk:"source_address"` Version types.Int64 `tfsdk:"version"` @@ -816,19 +816,19 @@ func (block *forwardingoptionsSamplingBlockFamilyMplsOutputConfig) isEmpty() boo //nolint:lll type forwardingoptionsSamplingBlockOutputBlockFlowServer struct { + Hostname types.String `tfsdk:"hostname"` + Port types.Int64 `tfsdk:"port"` AggregationAutonomousSystem types.Bool `tfsdk:"aggregation_autonomous_system"` AggregationDestinationPrefix types.Bool `tfsdk:"aggregation_destination_prefix"` AggregationProtocolPort types.Bool `tfsdk:"aggregation_protocol_port"` AggregationSourceDestinationPrefix types.Bool `tfsdk:"aggregation_source_destination_prefix"` AggregationSourceDestinationPrefixCaidaCompliant types.Bool `tfsdk:"aggregation_source_destination_prefix_caida_compliant"` AggregationSourcePrefix types.Bool `tfsdk:"aggregation_source_prefix"` - LocalDump types.Bool `tfsdk:"local_dump"` - NoLocalDump types.Bool `tfsdk:"no_local_dump"` - Hostname types.String `tfsdk:"hostname"` - Port types.Int64 `tfsdk:"port"` AutonomousSystemType types.String `tfsdk:"autonomous_system_type"` Dscp types.Int64 `tfsdk:"dscp"` ForwardingClass types.String `tfsdk:"forwarding_class"` + LocalDump types.Bool `tfsdk:"local_dump"` + NoLocalDump types.Bool `tfsdk:"no_local_dump"` RoutingInstance types.String `tfsdk:"routing_instance"` SourceAddress types.String `tfsdk:"source_address"` Version9Template types.String `tfsdk:"version9_template"` diff --git a/internal/providerfwk/resource_forwardingoptions_sampling_instance.go b/internal/providerfwk/resource_forwardingoptions_sampling_instance.go index cc58a1e4..442b6a94 100644 --- a/internal/providerfwk/resource_forwardingoptions_sampling_instance.go +++ b/internal/providerfwk/resource_forwardingoptions_sampling_instance.go @@ -624,10 +624,10 @@ func (rsc *forwardingoptionsSamplingInstance) schemaOutputInterfaceAttributes() } type forwardingoptionsSamplingInstanceData struct { - Disable types.Bool `tfsdk:"disable"` ID types.String `tfsdk:"id"` Name types.String `tfsdk:"name"` RoutingInstance types.String `tfsdk:"routing_instance"` + Disable types.Bool `tfsdk:"disable"` FamilyInetInput *forwardingoptionsSamplingInstanceBlockInput `tfsdk:"family_inet_input"` FamilyInetOutput *forwardingoptionsSamplingInstanceBlockFamilyInetOutput `tfsdk:"family_inet_output"` FamilyInet6Input *forwardingoptionsSamplingInstanceBlockInput `tfsdk:"family_inet6_input"` @@ -638,10 +638,10 @@ type forwardingoptionsSamplingInstanceData struct { } type forwardingoptionsSamplingInstanceConfig struct { - Disable types.Bool `tfsdk:"disable"` ID types.String `tfsdk:"id"` Name types.String `tfsdk:"name"` RoutingInstance types.String `tfsdk:"routing_instance"` + Disable types.Bool `tfsdk:"disable"` FamilyInetInput *forwardingoptionsSamplingInstanceBlockInput `tfsdk:"family_inet_input"` FamilyInetOutput *forwardingoptionsSamplingInstanceBlockFamilyInetOutputConfig `tfsdk:"family_inet_output"` FamilyInet6Input *forwardingoptionsSamplingInstanceBlockInput `tfsdk:"family_inet6_input"` @@ -695,19 +695,19 @@ func (block *forwardingoptionsSamplingInstanceBlockFamilyInetOutputConfig) isEmp //nolint:lll type forwardingoptionsSamplingInstanceBlockFamilyInetOutputBlockFlowServer struct { + Hostname types.String `tfsdk:"hostname"` + Port types.Int64 `tfsdk:"port"` AggregationAutonomousSystem types.Bool `tfsdk:"aggregation_autonomous_system"` AggregationDestinationPrefix types.Bool `tfsdk:"aggregation_destination_prefix"` AggregationProtocolPort types.Bool `tfsdk:"aggregation_protocol_port"` AggregationSourceDestinationPrefix types.Bool `tfsdk:"aggregation_source_destination_prefix"` AggregationSourceDestinationPrefixCaidaCompliant types.Bool `tfsdk:"aggregation_source_destination_prefix_caida_compliant"` AggregationSourcePrefix types.Bool `tfsdk:"aggregation_source_prefix"` - LocalDump types.Bool `tfsdk:"local_dump"` - NoLocalDump types.Bool `tfsdk:"no_local_dump"` - Hostname types.String `tfsdk:"hostname"` - Port types.Int64 `tfsdk:"port"` AutonomousSystemType types.String `tfsdk:"autonomous_system_type"` Dscp types.Int64 `tfsdk:"dscp"` ForwardingClass types.String `tfsdk:"forwarding_class"` + LocalDump types.Bool `tfsdk:"local_dump"` + NoLocalDump types.Bool `tfsdk:"no_local_dump"` RoutingInstance types.String `tfsdk:"routing_instance"` SourceAddress types.String `tfsdk:"source_address"` Version types.Int64 `tfsdk:"version"` @@ -754,19 +754,19 @@ func (block *forwardingoptionsSamplingInstanceBlockFamilyMplsOutputConfig) isEmp //nolint:lll type forwardingoptionsSamplingInstanceBlockOutputBlockFlowServer struct { + Hostname types.String `tfsdk:"hostname"` + Port types.Int64 `tfsdk:"port"` AggregationAutonomousSystem types.Bool `tfsdk:"aggregation_autonomous_system"` AggregationDestinationPrefix types.Bool `tfsdk:"aggregation_destination_prefix"` AggregationProtocolPort types.Bool `tfsdk:"aggregation_protocol_port"` AggregationSourceDestinationPrefix types.Bool `tfsdk:"aggregation_source_destination_prefix"` AggregationSourceDestinationPrefixCaidaCompliant types.Bool `tfsdk:"aggregation_source_destination_prefix_caida_compliant"` AggregationSourcePrefix types.Bool `tfsdk:"aggregation_source_prefix"` - LocalDump types.Bool `tfsdk:"local_dump"` - NoLocalDump types.Bool `tfsdk:"no_local_dump"` - Hostname types.String `tfsdk:"hostname"` - Port types.Int64 `tfsdk:"port"` AutonomousSystemType types.String `tfsdk:"autonomous_system_type"` Dscp types.Int64 `tfsdk:"dscp"` ForwardingClass types.String `tfsdk:"forwarding_class"` + LocalDump types.Bool `tfsdk:"local_dump"` + NoLocalDump types.Bool `tfsdk:"no_local_dump"` RoutingInstance types.String `tfsdk:"routing_instance"` SourceAddress types.String `tfsdk:"source_address"` Version9Template types.String `tfsdk:"version9_template"` diff --git a/internal/providerfwk/resource_forwardingoptions_storm_control_profile.go b/internal/providerfwk/resource_forwardingoptions_storm_control_profile.go index 9181fa84..01b677ec 100644 --- a/internal/providerfwk/resource_forwardingoptions_storm_control_profile.go +++ b/internal/providerfwk/resource_forwardingoptions_storm_control_profile.go @@ -175,21 +175,21 @@ func (rsc *forwardingoptionsStormControlProfile) Schema( } type forwardingoptionsStormControlProfileData struct { - ActionShutdown types.Bool `tfsdk:"action_shutdown"` ID types.String `tfsdk:"id"` Name types.String `tfsdk:"name"` + ActionShutdown types.Bool `tfsdk:"action_shutdown"` All *forwardingoptionsStormControlProfileBlockAll `tfsdk:"all"` } type forwardingoptionsStormControlProfileBlockAll struct { + BandwidthLevel types.Int64 `tfsdk:"bandwidth_level"` + BandwidthPercentage types.Int64 `tfsdk:"bandwidth_percentage"` + BurstSize types.Int64 `tfsdk:"burst_size"` NoBroadcast types.Bool `tfsdk:"no_broadcast"` NoMulticast types.Bool `tfsdk:"no_multicast"` NoRegisteredMulticast types.Bool `tfsdk:"no_registered_multicast"` NoUnknownUnicast types.Bool `tfsdk:"no_unknown_unicast"` NoUnregisteredMulticast types.Bool `tfsdk:"no_unregistered_multicast"` - BandwidthLevel types.Int64 `tfsdk:"bandwidth_level"` - BandwidthPercentage types.Int64 `tfsdk:"bandwidth_percentage"` - BurstSize types.Int64 `tfsdk:"burst_size"` } func (rsc *forwardingoptionsStormControlProfile) ValidateConfig( diff --git a/internal/providerfwk/resource_generate_route.go b/internal/providerfwk/resource_generate_route.go index ebbf9640..0eaa1e00 100644 --- a/internal/providerfwk/resource_generate_route.go +++ b/internal/providerfwk/resource_generate_route.go @@ -237,43 +237,43 @@ func (rsc *generateRoute) Schema( } type generateRouteData struct { - Active types.Bool `tfsdk:"active"` - ASPathAtomicAggregate types.Bool `tfsdk:"as_path_atomic_aggregate"` - Brief types.Bool `tfsdk:"brief"` - Discard types.Bool `tfsdk:"discard"` - Full types.Bool `tfsdk:"full"` - Passive types.Bool `tfsdk:"passive"` ID types.String `tfsdk:"id"` Destination types.String `tfsdk:"destination"` RoutingInstance types.String `tfsdk:"routing_instance"` + Active types.Bool `tfsdk:"active"` ASPathAggregatorAddress types.String `tfsdk:"as_path_aggregator_address"` ASPathAggregatorASNumber types.String `tfsdk:"as_path_aggregator_as_number"` + ASPathAtomicAggregate types.Bool `tfsdk:"as_path_atomic_aggregate"` ASPathOrigin types.String `tfsdk:"as_path_origin"` ASPathPath types.String `tfsdk:"as_path_path"` + Brief types.Bool `tfsdk:"brief"` Community []types.String `tfsdk:"community"` + Discard types.Bool `tfsdk:"discard"` + Full types.Bool `tfsdk:"full"` Metric types.Int64 `tfsdk:"metric"` NextTable types.String `tfsdk:"next_table"` + Passive types.Bool `tfsdk:"passive"` Policy []types.String `tfsdk:"policy"` Preference types.Int64 `tfsdk:"preference"` } type generateRouteConfig struct { - Active types.Bool `tfsdk:"active"` - ASPathAtomicAggregate types.Bool `tfsdk:"as_path_atomic_aggregate"` - Brief types.Bool `tfsdk:"brief"` - Discard types.Bool `tfsdk:"discard"` - Full types.Bool `tfsdk:"full"` - Passive types.Bool `tfsdk:"passive"` ID types.String `tfsdk:"id"` Destination types.String `tfsdk:"destination"` RoutingInstance types.String `tfsdk:"routing_instance"` + Active types.Bool `tfsdk:"active"` ASPathAggregatorAddress types.String `tfsdk:"as_path_aggregator_address"` ASPathAggregatorASNumber types.String `tfsdk:"as_path_aggregator_as_number"` + ASPathAtomicAggregate types.Bool `tfsdk:"as_path_atomic_aggregate"` ASPathOrigin types.String `tfsdk:"as_path_origin"` ASPathPath types.String `tfsdk:"as_path_path"` + Brief types.Bool `tfsdk:"brief"` Community types.List `tfsdk:"community"` + Discard types.Bool `tfsdk:"discard"` + Full types.Bool `tfsdk:"full"` Metric types.Int64 `tfsdk:"metric"` NextTable types.String `tfsdk:"next_table"` + Passive types.Bool `tfsdk:"passive"` Policy types.List `tfsdk:"policy"` Preference types.Int64 `tfsdk:"preference"` } diff --git a/internal/providerfwk/resource_iccp_peer.go b/internal/providerfwk/resource_iccp_peer.go index 1431c9c9..cdcb3606 100644 --- a/internal/providerfwk/resource_iccp_peer.go +++ b/internal/providerfwk/resource_iccp_peer.go @@ -243,11 +243,11 @@ type iccpPeerBlockBackupLivenessDetection struct { } type iccpPeerBlockLivenessDetection struct { - NoAdaptation types.Bool `tfsdk:"no_adaptation"` DetectionTimeThreshold types.Int64 `tfsdk:"detection_time_threshold"` MinimumInterval types.Int64 `tfsdk:"minimum_interval"` MinimumReceiveInterval types.Int64 `tfsdk:"minimum_receive_interval"` Multiplier types.Int64 `tfsdk:"multiplier"` + NoAdaptation types.Bool `tfsdk:"no_adaptation"` TransmitIntervalMinimumInterval types.Int64 `tfsdk:"transmit_interval_minimum_interval"` TransmitIntervalThreshold types.Int64 `tfsdk:"transmit_interval_threshold"` Version types.String `tfsdk:"version"` diff --git a/internal/providerfwk/resource_interface_logical.go b/internal/providerfwk/resource_interface_logical.go index 09fc9321..aebcf7e6 100644 --- a/internal/providerfwk/resource_interface_logical.go +++ b/internal/providerfwk/resource_interface_logical.go @@ -1012,56 +1012,56 @@ func (rsc *interfaceLogical) Schema( } type interfaceLogicalData struct { - St0AlsoOnDestroy types.Bool `tfsdk:"st0_also_on_destroy"` - VlanNoCompute types.Bool `tfsdk:"vlan_no_compute"` - Disable types.Bool `tfsdk:"disable"` ID types.String `tfsdk:"id"` Name types.String `tfsdk:"name"` + St0AlsoOnDestroy types.Bool `tfsdk:"st0_also_on_destroy"` Description types.String `tfsdk:"description"` + Disable types.Bool `tfsdk:"disable"` RoutingInstance types.String `tfsdk:"routing_instance"` SecurityInboundProtocols []types.String `tfsdk:"security_inbound_protocols"` SecurityInboundServices []types.String `tfsdk:"security_inbound_services"` SecurityZone types.String `tfsdk:"security_zone"` VlanID types.Int64 `tfsdk:"vlan_id"` + VlanNoCompute types.Bool `tfsdk:"vlan_no_compute"` FamilyInet *interfaceLogicalBlockFamilyInet `tfsdk:"family_inet"` FamilyInet6 *interfaceLogicalBlockFamilyInet6 `tfsdk:"family_inet6"` Tunnel *interfaceLogicalBlockTunnel `tfsdk:"tunnel"` } type interfaceLogicalConfig struct { - St0AlsoOnDestroy types.Bool `tfsdk:"st0_also_on_destroy"` - VlanNoCompute types.Bool `tfsdk:"vlan_no_compute"` - Disable types.Bool `tfsdk:"disable"` ID types.String `tfsdk:"id"` Name types.String `tfsdk:"name"` + St0AlsoOnDestroy types.Bool `tfsdk:"st0_also_on_destroy"` Description types.String `tfsdk:"description"` + Disable types.Bool `tfsdk:"disable"` RoutingInstance types.String `tfsdk:"routing_instance"` SecurityInboundProtocols types.Set `tfsdk:"security_inbound_protocols"` SecurityInboundServices types.Set `tfsdk:"security_inbound_services"` SecurityZone types.String `tfsdk:"security_zone"` VlanID types.Int64 `tfsdk:"vlan_id"` + VlanNoCompute types.Bool `tfsdk:"vlan_no_compute"` FamilyInet *interfaceLogicalBlockFamilyInetConfig `tfsdk:"family_inet"` FamilyInet6 *interfaceLogicalBlockFamilyInet6Config `tfsdk:"family_inet6"` Tunnel *interfaceLogicalBlockTunnel `tfsdk:"tunnel"` } type interfaceLogicalBlockFamilyInet struct { - SamplingInput types.Bool `tfsdk:"sampling_input"` - SamplingOutput types.Bool `tfsdk:"sampling_output"` FilterInput types.String `tfsdk:"filter_input"` FilterOutput types.String `tfsdk:"filter_output"` Mtu types.Int64 `tfsdk:"mtu"` + SamplingInput types.Bool `tfsdk:"sampling_input"` + SamplingOutput types.Bool `tfsdk:"sampling_output"` Address []interfaceLogicalBlockFamilyInetBlockAddress `tfsdk:"address"` DHCP *interfaceLogicalBlockFamilyInetBlockDhcp `tfsdk:"dhcp"` RPFCheck *interfaceLogicalBlockFamilyBlockRPFCheck `tfsdk:"rpf_check"` } type interfaceLogicalBlockFamilyInetConfig struct { - SamplingInput types.Bool `tfsdk:"sampling_input"` - SamplingOutput types.Bool `tfsdk:"sampling_output"` FilterInput types.String `tfsdk:"filter_input"` FilterOutput types.String `tfsdk:"filter_output"` Mtu types.Int64 `tfsdk:"mtu"` + SamplingInput types.Bool `tfsdk:"sampling_input"` + SamplingOutput types.Bool `tfsdk:"sampling_output"` Address types.List `tfsdk:"address"` DHCP *interfaceLogicalBlockFamilyInetBlockDhcp `tfsdk:"dhcp"` RPFCheck *interfaceLogicalBlockFamilyBlockRPFCheck `tfsdk:"rpf_check"` @@ -1073,47 +1073,47 @@ type interfaceLogicalBlockFamilyBlockRPFCheck struct { } type interfaceLogicalBlockFamilyInetBlockAddress struct { + CidrIP types.String `tfsdk:"cidr_ip"` Preferred types.Bool `tfsdk:"preferred"` Primary types.Bool `tfsdk:"primary"` - CidrIP types.String `tfsdk:"cidr_ip"` VRRPGroup []interfaceLogicalBlockFamilyInetBlockAddressBlockVRRPGroup `tfsdk:"vrrp_group"` } type interfaceLogicalBlockFamilyInetBlockAddressConfig struct { + CidrIP types.String `tfsdk:"cidr_ip"` Preferred types.Bool `tfsdk:"preferred"` Primary types.Bool `tfsdk:"primary"` - CidrIP types.String `tfsdk:"cidr_ip"` VRRPGroup types.List `tfsdk:"vrrp_group"` } //nolint:lll type interfaceLogicalBlockFamilyInetBlockAddressBlockVRRPGroup struct { - AcceptData types.Bool `tfsdk:"accept_data"` - NoAcceptData types.Bool `tfsdk:"no_accept_data"` - Preempt types.Bool `tfsdk:"preempt"` - NoPreempt types.Bool `tfsdk:"no_preempt"` Identifier types.Int64 `tfsdk:"identifier"` VirtualAddress []types.String `tfsdk:"virtual_address"` + AcceptData types.Bool `tfsdk:"accept_data"` + NoAcceptData types.Bool `tfsdk:"no_accept_data"` AdvertiseInterval types.Int64 `tfsdk:"advertise_interval"` AdvertisementsThreshold types.Int64 `tfsdk:"advertisements_threshold"` AuthenticationKey types.String `tfsdk:"authentication_key"` AuthenticationType types.String `tfsdk:"authentication_type"` + Preempt types.Bool `tfsdk:"preempt"` + NoPreempt types.Bool `tfsdk:"no_preempt"` Priority types.Int64 `tfsdk:"priority"` TrackInterface []interfaceLogicalBlockFamilyBlockAddressBlockVRRPGroupBlockTrackInterface `tfsdk:"track_interface"` TrackRoute []interfaceLogicalBlockFamilyBlockAddressBlockVRRPGroupBlockTrackRoute `tfsdk:"track_route"` } type interfaceLogicalBlockFamilyInetBlockAddressBlockVRRPGroupConfig struct { - AcceptData types.Bool `tfsdk:"accept_data"` - NoAcceptData types.Bool `tfsdk:"no_accept_data"` - Preempt types.Bool `tfsdk:"preempt"` - NoPreempt types.Bool `tfsdk:"no_preempt"` Identifier types.Int64 `tfsdk:"identifier"` VirtualAddress types.List `tfsdk:"virtual_address"` + AcceptData types.Bool `tfsdk:"accept_data"` + NoAcceptData types.Bool `tfsdk:"no_accept_data"` AdvertiseInterval types.Int64 `tfsdk:"advertise_interval"` AdvertisementsThreshold types.Int64 `tfsdk:"advertisements_threshold"` AuthenticationKey types.String `tfsdk:"authentication_key"` AuthenticationType types.String `tfsdk:"authentication_type"` + Preempt types.Bool `tfsdk:"preempt"` + NoPreempt types.Bool `tfsdk:"no_preempt"` Priority types.Int64 `tfsdk:"priority"` TrackInterface types.List `tfsdk:"track_interface"` TrackRoute types.List `tfsdk:"track_route"` @@ -1132,23 +1132,23 @@ type interfaceLogicalBlockFamilyBlockAddressBlockVRRPGroupBlockTrackRoute struct type interfaceLogicalBlockFamilyInetBlockDhcp struct { SrxOldOptionName types.Bool `tfsdk:"srx_old_option_name"` - ClientIdentifierPrefixHostname types.Bool `tfsdk:"client_identifier_prefix_hostname"` - ClientIdentifierPrefixRoutingInstanceName types.Bool `tfsdk:"client_identifier_prefix_routing_instance_name"` - ForceDiscover types.Bool `tfsdk:"force_discover"` - LeaseTimeInfinite types.Bool `tfsdk:"lease_time_infinite"` - NoDNSInstall types.Bool `tfsdk:"no_dns_install"` - OptionsNoHostname types.Bool `tfsdk:"options_no_hostname"` - UpdateServer types.Bool `tfsdk:"update_server"` ClientIdentifierASCII types.String `tfsdk:"client_identifier_ascii"` ClientIdentifierHexadecimal types.String `tfsdk:"client_identifier_hexadecimal"` + ClientIdentifierPrefixHostname types.Bool `tfsdk:"client_identifier_prefix_hostname"` + ClientIdentifierPrefixRoutingInstanceName types.Bool `tfsdk:"client_identifier_prefix_routing_instance_name"` ClientIdentifierUseInterfaceDescription types.String `tfsdk:"client_identifier_use_interface_description"` ClientIdentifierUseridASCII types.String `tfsdk:"client_identifier_userid_ascii"` ClientIdentifierUseridHexadecimal types.String `tfsdk:"client_identifier_userid_hexadecimal"` + ForceDiscover types.Bool `tfsdk:"force_discover"` LeaseTime types.Int64 `tfsdk:"lease_time"` + LeaseTimeInfinite types.Bool `tfsdk:"lease_time_infinite"` Metric types.Int64 `tfsdk:"metric"` + NoDNSInstall types.Bool `tfsdk:"no_dns_install"` + OptionsNoHostname types.Bool `tfsdk:"options_no_hostname"` RetransmissionAttempt types.Int64 `tfsdk:"retransmission_attempt"` RetransmissionInterval types.Int64 `tfsdk:"retransmission_interval"` ServerAddress types.String `tfsdk:"server_address"` + UpdateServer types.Bool `tfsdk:"update_server"` VendorID types.String `tfsdk:"vendor_id"` } @@ -1158,11 +1158,11 @@ func (block *interfaceLogicalBlockFamilyInetBlockDhcp) hasKnownValue() bool { type interfaceLogicalBlockFamilyInet6 struct { DadDisable types.Bool `tfsdk:"dad_disable"` - SamplingInput types.Bool `tfsdk:"sampling_input"` - SamplingOutput types.Bool `tfsdk:"sampling_output"` FilterInput types.String `tfsdk:"filter_input"` FilterOutput types.String `tfsdk:"filter_output"` Mtu types.Int64 `tfsdk:"mtu"` + SamplingInput types.Bool `tfsdk:"sampling_input"` + SamplingOutput types.Bool `tfsdk:"sampling_output"` Address []interfaceLogicalBlockFamilyInet6BlockAddress `tfsdk:"address"` DHCPv6Client *interfaceLogicalBlockFamilyInet6BlockDhcpV6Client `tfsdk:"dhcpv6_client"` RPFCheck *interfaceLogicalBlockFamilyBlockRPFCheck `tfsdk:"rpf_check"` @@ -1170,70 +1170,70 @@ type interfaceLogicalBlockFamilyInet6 struct { type interfaceLogicalBlockFamilyInet6Config struct { DadDisable types.Bool `tfsdk:"dad_disable"` - SamplingInput types.Bool `tfsdk:"sampling_input"` - SamplingOutput types.Bool `tfsdk:"sampling_output"` FilterInput types.String `tfsdk:"filter_input"` FilterOutput types.String `tfsdk:"filter_output"` Mtu types.Int64 `tfsdk:"mtu"` + SamplingInput types.Bool `tfsdk:"sampling_input"` + SamplingOutput types.Bool `tfsdk:"sampling_output"` Address types.List `tfsdk:"address"` DHCPv6Client *interfaceLogicalBlockFamilyInet6BlockDhcpV6ClientConfig `tfsdk:"dhcpv6_client"` RPFCheck *interfaceLogicalBlockFamilyBlockRPFCheck `tfsdk:"rpf_check"` } type interfaceLogicalBlockFamilyInet6BlockAddress struct { + CidrIP types.String `tfsdk:"cidr_ip"` Preferred types.Bool `tfsdk:"preferred"` Primary types.Bool `tfsdk:"primary"` - CidrIP types.String `tfsdk:"cidr_ip"` VRRPGroup []interfaceLogicalBlockFamilyInet6BlockAddressBlockVRRPGroup `tfsdk:"vrrp_group"` } type interfaceLogicalBlockFamilyInet6BlockAddressConfig struct { + CidrIP types.String `tfsdk:"cidr_ip"` Preferred types.Bool `tfsdk:"preferred"` Primary types.Bool `tfsdk:"primary"` - CidrIP types.String `tfsdk:"cidr_ip"` VRRPGroup types.List `tfsdk:"vrrp_group"` } //nolint:lll type interfaceLogicalBlockFamilyInet6BlockAddressBlockVRRPGroup struct { - AcceptData types.Bool `tfsdk:"accept_data"` - NoAcceptData types.Bool `tfsdk:"no_accept_data"` - Preempt types.Bool `tfsdk:"preempt"` - NoPreempt types.Bool `tfsdk:"no_preempt"` Identifier types.Int64 `tfsdk:"identifier"` VirtualAddress []types.String `tfsdk:"virtual_address"` VirutalLinkLocalAddress types.String `tfsdk:"virtual_link_local_address"` + AcceptData types.Bool `tfsdk:"accept_data"` + NoAcceptData types.Bool `tfsdk:"no_accept_data"` AdvertiseInterval types.Int64 `tfsdk:"advertise_interval"` AdvertisementsThreshold types.Int64 `tfsdk:"advertisements_threshold"` + Preempt types.Bool `tfsdk:"preempt"` + NoPreempt types.Bool `tfsdk:"no_preempt"` Priority types.Int64 `tfsdk:"priority"` TrackInterface []interfaceLogicalBlockFamilyBlockAddressBlockVRRPGroupBlockTrackInterface `tfsdk:"track_interface"` TrackRoute []interfaceLogicalBlockFamilyBlockAddressBlockVRRPGroupBlockTrackRoute `tfsdk:"track_route"` } type interfaceLogicalBlockFamilyInet6BlockAddressBlockVRRPGroupConfig struct { - AcceptData types.Bool `tfsdk:"accept_data"` - NoAcceptData types.Bool `tfsdk:"no_accept_data"` - Preempt types.Bool `tfsdk:"preempt"` - NoPreempt types.Bool `tfsdk:"no_preempt"` Identifier types.Int64 `tfsdk:"identifier"` VirtualAddress types.List `tfsdk:"virtual_address"` VirutalLinkLocalAddress types.String `tfsdk:"virtual_link_local_address"` + AcceptData types.Bool `tfsdk:"accept_data"` + NoAcceptData types.Bool `tfsdk:"no_accept_data"` AdvertiseInterval types.Int64 `tfsdk:"advertise_interval"` AdvertisementsThreshold types.Int64 `tfsdk:"advertisements_threshold"` + Preempt types.Bool `tfsdk:"preempt"` + NoPreempt types.Bool `tfsdk:"no_preempt"` Priority types.Int64 `tfsdk:"priority"` TrackInterface types.List `tfsdk:"track_interface"` TrackRoute types.List `tfsdk:"track_route"` } type interfaceLogicalBlockFamilyInet6BlockDhcpV6Client struct { + ClientIdentifierDuidType types.String `tfsdk:"client_identifier_duid_type"` + ClientType types.String `tfsdk:"client_type"` ClientIATypeNA types.Bool `tfsdk:"client_ia_type_na"` ClientIATypePD types.Bool `tfsdk:"client_ia_type_pd"` NoDNSInstall types.Bool `tfsdk:"no_dns_install"` - RapidCommit types.Bool `tfsdk:"rapid_commit"` - ClientIdentifierDuidType types.String `tfsdk:"client_identifier_duid_type"` - ClientType types.String `tfsdk:"client_type"` PrefixDelegatingPreferredPrefixLength types.Int64 `tfsdk:"prefix_delegating_preferred_prefix_length"` PrefixDelegatingSubPrefixLength types.Int64 `tfsdk:"prefix_delegating_sub_prefix_length"` + RapidCommit types.Bool `tfsdk:"rapid_commit"` ReqOption []types.String `tfsdk:"req_option"` RetransmissionAttempt types.Int64 `tfsdk:"retransmission_attempt"` UpdateRouterAdvertisementInterface []types.String `tfsdk:"update_router_advertisement_interface"` @@ -1241,14 +1241,14 @@ type interfaceLogicalBlockFamilyInet6BlockDhcpV6Client struct { } type interfaceLogicalBlockFamilyInet6BlockDhcpV6ClientConfig struct { + ClientIdentifierDuidType types.String `tfsdk:"client_identifier_duid_type"` + ClientType types.String `tfsdk:"client_type"` ClientIATypeNA types.Bool `tfsdk:"client_ia_type_na"` ClientIATypePD types.Bool `tfsdk:"client_ia_type_pd"` NoDNSInstall types.Bool `tfsdk:"no_dns_install"` - RapidCommit types.Bool `tfsdk:"rapid_commit"` - ClientIdentifierDuidType types.String `tfsdk:"client_identifier_duid_type"` - ClientType types.String `tfsdk:"client_type"` PrefixDelegatingPreferredPrefixLength types.Int64 `tfsdk:"prefix_delegating_preferred_prefix_length"` PrefixDelegatingSubPrefixLength types.Int64 `tfsdk:"prefix_delegating_sub_prefix_length"` + RapidCommit types.Bool `tfsdk:"rapid_commit"` ReqOption types.Set `tfsdk:"req_option"` RetransmissionAttempt types.Int64 `tfsdk:"retransmission_attempt"` UpdateRouterAdvertisementInterface types.Set `tfsdk:"update_router_advertisement_interface"` @@ -1260,13 +1260,13 @@ func (block *interfaceLogicalBlockFamilyInet6BlockDhcpV6ClientConfig) hasKnownVa } type interfaceLogicalBlockTunnel struct { + Destination types.String `tfsdk:"destination"` + Source types.String `tfsdk:"source"` AllowFragmentation types.Bool `tfsdk:"allow_fragmentation"` DoNotFragment types.Bool `tfsdk:"do_not_fragment"` + FlowLabel types.Int64 `tfsdk:"flow_label"` PathMtuDiscovery types.Bool `tfsdk:"path_mtu_discovery"` NoPathMtuDiscovery types.Bool `tfsdk:"no_path_mtu_discovery"` - Destination types.String `tfsdk:"destination"` - Source types.String `tfsdk:"source"` - FlowLabel types.Int64 `tfsdk:"flow_label"` RoutingInstanceDestination types.String `tfsdk:"routing_instance_destination"` TrafficClass types.Int64 `tfsdk:"traffic_class"` TTL types.Int64 `tfsdk:"ttl"` diff --git a/internal/providerfwk/resource_interface_physical.go b/internal/providerfwk/resource_interface_physical.go index 66638694..d8d68203 100644 --- a/internal/providerfwk/resource_interface_physical.go +++ b/internal/providerfwk/resource_interface_physical.go @@ -736,28 +736,28 @@ func (rsc *interfacePhysical) schemaEtherOptsAttributes() map[string]schema.Attr } type interfacePhysicalData struct { - NoDisableOnDestroy types.Bool `tfsdk:"no_disable_on_destroy"` - Disable types.Bool `tfsdk:"disable"` - FlexibleVlanTagging types.Bool `tfsdk:"flexible_vlan_tagging"` - GratuitousArpReply types.Bool `tfsdk:"gratuitous_arp_reply"` - NoGratuitousArpReply types.Bool `tfsdk:"no_gratuitous_arp_reply"` - NoGratuitousArpRequest types.Bool `tfsdk:"no_gratuitous_arp_request"` - Trunk types.Bool `tfsdk:"trunk"` - TrunkNonELS types.Bool `tfsdk:"trunk_non_els"` - VlanTagging types.Bool `tfsdk:"vlan_tagging"` ID types.String `tfsdk:"id"` Name types.String `tfsdk:"name"` + NoDisableOnDestroy types.Bool `tfsdk:"no_disable_on_destroy"` Description types.String `tfsdk:"description"` + Disable types.Bool `tfsdk:"disable"` Encapsulation types.String `tfsdk:"encapsulation"` + FlexibleVlanTagging types.Bool `tfsdk:"flexible_vlan_tagging"` + GratuitousArpReply types.Bool `tfsdk:"gratuitous_arp_reply"` HoldTimeDown types.Int64 `tfsdk:"hold_time_down"` HoldTimeUp types.Int64 `tfsdk:"hold_time_up"` LinkMode types.String `tfsdk:"link_mode"` Mtu types.Int64 `tfsdk:"mtu"` + NoGratuitousArpReply types.Bool `tfsdk:"no_gratuitous_arp_reply"` + NoGratuitousArpRequest types.Bool `tfsdk:"no_gratuitous_arp_request"` Speed types.String `tfsdk:"speed"` StormControl types.String `tfsdk:"storm_control"` + Trunk types.Bool `tfsdk:"trunk"` + TrunkNonELS types.Bool `tfsdk:"trunk_non_els"` VlanMembers []types.String `tfsdk:"vlan_members"` VlanNative types.Int64 `tfsdk:"vlan_native"` VlanNativeNonELS types.String `tfsdk:"vlan_native_non_els"` + VlanTagging types.Bool `tfsdk:"vlan_tagging"` ESI *interfacePhysicalBlockESI `tfsdk:"esi"` EtherOpts *interfacePhysicalBlockEtherOpts `tfsdk:"ether_opts"` GigetherOpts *interfacePhysicalBlockEtherOpts `tfsdk:"gigether_opts"` @@ -765,28 +765,28 @@ type interfacePhysicalData struct { } type interfacePhysicalConfig struct { - NoDisableOnDestroy types.Bool `tfsdk:"no_disable_on_destroy"` - Disable types.Bool `tfsdk:"disable"` - FlexibleVlanTagging types.Bool `tfsdk:"flexible_vlan_tagging"` - GratuitousArpReply types.Bool `tfsdk:"gratuitous_arp_reply"` - NoGratuitousArpReply types.Bool `tfsdk:"no_gratuitous_arp_reply"` - NoGratuitousArpRequest types.Bool `tfsdk:"no_gratuitous_arp_request"` - Trunk types.Bool `tfsdk:"trunk"` - TrunkNonELS types.Bool `tfsdk:"trunk_non_els"` - VlanTagging types.Bool `tfsdk:"vlan_tagging"` ID types.String `tfsdk:"id"` Name types.String `tfsdk:"name"` + NoDisableOnDestroy types.Bool `tfsdk:"no_disable_on_destroy"` Description types.String `tfsdk:"description"` + Disable types.Bool `tfsdk:"disable"` Encapsulation types.String `tfsdk:"encapsulation"` + FlexibleVlanTagging types.Bool `tfsdk:"flexible_vlan_tagging"` + GratuitousArpReply types.Bool `tfsdk:"gratuitous_arp_reply"` HoldTimeDown types.Int64 `tfsdk:"hold_time_down"` HoldTimeUp types.Int64 `tfsdk:"hold_time_up"` LinkMode types.String `tfsdk:"link_mode"` Mtu types.Int64 `tfsdk:"mtu"` + NoGratuitousArpReply types.Bool `tfsdk:"no_gratuitous_arp_reply"` + NoGratuitousArpRequest types.Bool `tfsdk:"no_gratuitous_arp_request"` Speed types.String `tfsdk:"speed"` StormControl types.String `tfsdk:"storm_control"` + Trunk types.Bool `tfsdk:"trunk"` + TrunkNonELS types.Bool `tfsdk:"trunk_non_els"` VlanMembers types.List `tfsdk:"vlan_members"` VlanNative types.Int64 `tfsdk:"vlan_native"` VlanNativeNonELS types.String `tfsdk:"vlan_native_non_els"` + VlanTagging types.Bool `tfsdk:"vlan_tagging"` ESI *interfacePhysicalBlockESI `tfsdk:"esi"` EtherOpts *interfacePhysicalBlockEtherOpts `tfsdk:"ether_opts"` GigetherOpts *interfacePhysicalBlockEtherOpts `tfsdk:"gigether_opts"` @@ -794,21 +794,21 @@ type interfacePhysicalConfig struct { } type interfacePhysicalBlockESI struct { - AutoDeriveLACP types.Bool `tfsdk:"auto_derive_lacp"` Mode types.String `tfsdk:"mode"` + AutoDeriveLACP types.Bool `tfsdk:"auto_derive_lacp"` DFElectionType types.String `tfsdk:"df_election_type"` Identifier types.String `tfsdk:"identifier"` SourceBMAC types.String `tfsdk:"source_bmac"` } type interfacePhysicalBlockEtherOpts struct { + Ae8023ad types.String `tfsdk:"ae_8023ad"` AutoNegotiation types.Bool `tfsdk:"auto_negotiation"` NoAutoNegotiation types.Bool `tfsdk:"no_auto_negotiation"` FlowControl types.Bool `tfsdk:"flow_control"` NoFlowControl types.Bool `tfsdk:"no_flow_control"` Loopback types.Bool `tfsdk:"loopback"` NoLoopback types.Bool `tfsdk:"no_loopback"` - Ae8023ad types.String `tfsdk:"ae_8023ad"` RedundantParent types.String `tfsdk:"redundant_parent"` } @@ -825,12 +825,12 @@ type interfacePhysicalBlockParentEtherOpts struct { NoFlowControl types.Bool `tfsdk:"no_flow_control"` Loopback types.Bool `tfsdk:"loopback"` NoLoopback types.Bool `tfsdk:"no_loopback"` - SourceFiltering types.Bool `tfsdk:"source_filtering"` LinkSpeed types.String `tfsdk:"link_speed"` MinimumBandwidth types.String `tfsdk:"minimum_bandwidth"` MinimumLinks types.Int64 `tfsdk:"minimum_links"` RedundancyGroup types.Int64 `tfsdk:"redundancy_group"` SourceAddressFilter []types.String `tfsdk:"source_address_filter"` + SourceFiltering types.Bool `tfsdk:"source_filtering"` BFDLivenessDetection *interfacePhysicalBlockParentEtherOptsBlockBFDLivenessDetection `tfsdk:"bfd_liveness_detection"` LACP *interfacePhysicalBlockParentEtherOptsBlockLACP `tfsdk:"lacp"` MCAE *interfacePhysicalBlockParentEtherOptsBlockMCAE `tfsdk:"mc_ae"` @@ -841,12 +841,12 @@ type interfacePhysicalBlockParentEtherOptsConfig struct { NoFlowControl types.Bool `tfsdk:"no_flow_control"` Loopback types.Bool `tfsdk:"loopback"` NoLoopback types.Bool `tfsdk:"no_loopback"` - SourceFiltering types.Bool `tfsdk:"source_filtering"` LinkSpeed types.String `tfsdk:"link_speed"` MinimumBandwidth types.String `tfsdk:"minimum_bandwidth"` MinimumLinks types.Int64 `tfsdk:"minimum_links"` RedundancyGroup types.Int64 `tfsdk:"redundancy_group"` SourceAddressFilter types.List `tfsdk:"source_address_filter"` + SourceFiltering types.Bool `tfsdk:"source_filtering"` BFDLivenessDetection *interfacePhysicalBlockParentEtherOptsBlockBFDLivenessDetection `tfsdk:"bfd_liveness_detection"` LACP *interfacePhysicalBlockParentEtherOptsBlockLACP `tfsdk:"lacp"` MCAE *interfacePhysicalBlockParentEtherOptsBlockMCAE `tfsdk:"mc_ae"` @@ -861,17 +861,17 @@ func (block *interfacePhysicalBlockParentEtherOptsConfig) hasKnownValue() bool { } type interfacePhysicalBlockParentEtherOptsBlockBFDLivenessDetection struct { - AuthenticationLooseCheck types.Bool `tfsdk:"authentication_loose_check"` - NoAdaptation types.Bool `tfsdk:"no_adaptation"` LocalAddress types.String `tfsdk:"local_address"` AuthenticationAlgorithm types.String `tfsdk:"authentication_algorithm"` AuthenticationKeyChain types.String `tfsdk:"authentication_key_chain"` + AuthenticationLooseCheck types.Bool `tfsdk:"authentication_loose_check"` DetectionTimeThreshold types.Int64 `tfsdk:"detection_time_threshold"` HolddownInterval types.Int64 `tfsdk:"holddown_interval"` MinimumInterval types.Int64 `tfsdk:"minimum_interval"` MinimumReceiveInterval types.Int64 `tfsdk:"minimum_receive_interval"` Multiplier types.Int64 `tfsdk:"multiplier"` Neighbor types.String `tfsdk:"neighbor"` + NoAdaptation types.Bool `tfsdk:"no_adaptation"` TransmitIntervalMinimumInterval types.Int64 `tfsdk:"transmit_interval_minimum_interval"` TransmitIntervalThreshold types.Int64 `tfsdk:"transmit_interval_threshold"` Version types.String `tfsdk:"version"` @@ -888,11 +888,11 @@ type interfacePhysicalBlockParentEtherOptsBlockLACP struct { //nolint:lll type interfacePhysicalBlockParentEtherOptsBlockMCAE struct { - EnhancedConvergence types.Bool `tfsdk:"enhanced_convergence"` ChassisID types.Int64 `tfsdk:"chassis_id"` MCAEID types.Int64 `tfsdk:"mc_ae_id"` Mode types.String `tfsdk:"mode"` StatusControl types.String `tfsdk:"status_control"` + EnhancedConvergence types.Bool `tfsdk:"enhanced_convergence"` InitDelayTime types.Int64 `tfsdk:"init_delay_time"` RedundancyGroup types.Int64 `tfsdk:"redundancy_group"` RevertTime types.Int64 `tfsdk:"revert_time"` diff --git a/internal/providerfwk/resource_multichassis.go b/internal/providerfwk/resource_multichassis.go index e63a8fc3..816d101d 100644 --- a/internal/providerfwk/resource_multichassis.go +++ b/internal/providerfwk/resource_multichassis.go @@ -108,9 +108,9 @@ func (rsc *multichassis) Schema( } type multichassisData struct { + ID types.String `tfsdk:"id"` CleanOnDestroy types.Bool `tfsdk:"clean_on_destroy"` MCLagConsistencyCheck types.Bool `tfsdk:"mc_lag_consistency_check"` - ID types.String `tfsdk:"id"` MCLagConsistencyCheckComparaisonDelayTime types.Int64 `tfsdk:"mc_lag_consistency_check_comparison_delay_time"` } diff --git a/internal/providerfwk/resource_policyoptions_as_path.go b/internal/providerfwk/resource_policyoptions_as_path.go index 9341b8af..9a4b809f 100644 --- a/internal/providerfwk/resource_policyoptions_as_path.go +++ b/internal/providerfwk/resource_policyoptions_as_path.go @@ -112,9 +112,9 @@ func (rsc *policyoptionsASPath) Schema( } type policyoptionsASPathData struct { - DynamicDB types.Bool `tfsdk:"dynamic_db"` ID types.String `tfsdk:"id"` Name types.String `tfsdk:"name"` + DynamicDB types.Bool `tfsdk:"dynamic_db"` Path types.String `tfsdk:"path"` } diff --git a/internal/providerfwk/resource_policyoptions_as_path_group.go b/internal/providerfwk/resource_policyoptions_as_path_group.go index 92f9029a..01bcbe3e 100644 --- a/internal/providerfwk/resource_policyoptions_as_path_group.go +++ b/internal/providerfwk/resource_policyoptions_as_path_group.go @@ -132,16 +132,16 @@ func (rsc *policyoptionsASPathGroup) Schema( } type policyoptionsASPathGroupData struct { - DynamicDB types.Bool `tfsdk:"dynamic_db"` ID types.String `tfsdk:"id"` Name types.String `tfsdk:"name"` + DynamicDB types.Bool `tfsdk:"dynamic_db"` ASPath []policyoptionsASPathGroupBlockASPAth `tfsdk:"as_path"` } type policyoptionsASPathGroupConfig struct { - DynamicDB types.Bool `tfsdk:"dynamic_db"` ID types.String `tfsdk:"id"` Name types.String `tfsdk:"name"` + DynamicDB types.Bool `tfsdk:"dynamic_db"` ASPath types.List `tfsdk:"as_path"` } diff --git a/internal/providerfwk/resource_policyoptions_community.go b/internal/providerfwk/resource_policyoptions_community.go index d3f5f3b1..3e1c57be 100644 --- a/internal/providerfwk/resource_policyoptions_community.go +++ b/internal/providerfwk/resource_policyoptions_community.go @@ -125,18 +125,18 @@ func (rsc *policyoptionsCommunity) Schema( } type policyoptionsCommunityData struct { - DynamicDB types.Bool `tfsdk:"dynamic_db"` - InvertMatch types.Bool `tfsdk:"invert_match"` ID types.String `tfsdk:"id"` Name types.String `tfsdk:"name"` + DynamicDB types.Bool `tfsdk:"dynamic_db"` + InvertMatch types.Bool `tfsdk:"invert_match"` Members []types.String `tfsdk:"members"` } type policyoptionsCommunityConfig struct { - DynamicDB types.Bool `tfsdk:"dynamic_db"` - InvertMatch types.Bool `tfsdk:"invert_match"` ID types.String `tfsdk:"id"` Name types.String `tfsdk:"name"` + DynamicDB types.Bool `tfsdk:"dynamic_db"` + InvertMatch types.Bool `tfsdk:"invert_match"` Members types.List `tfsdk:"members"` } diff --git a/internal/providerfwk/resource_policyoptions_policy_statement.go b/internal/providerfwk/resource_policyoptions_policy_statement.go index 3fd732d6..73997c50 100644 --- a/internal/providerfwk/resource_policyoptions_policy_statement.go +++ b/internal/providerfwk/resource_policyoptions_policy_statement.go @@ -895,10 +895,10 @@ func (rsc *policyoptionsPolicyStatement) schemaThenBlocks() map[string]schema.Bl } type policyoptionsPolicyStatementData struct { - AddItToForwardingTableExport types.Bool `tfsdk:"add_it_to_forwarding_table_export"` - DynamicDB types.Bool `tfsdk:"dynamic_db"` ID types.String `tfsdk:"id"` Name types.String `tfsdk:"name"` + AddItToForwardingTableExport types.Bool `tfsdk:"add_it_to_forwarding_table_export"` + DynamicDB types.Bool `tfsdk:"dynamic_db"` From *policyoptionsPolicyStatementBlockFrom `tfsdk:"from"` To *policyoptionsPolicyStatementBlockTo `tfsdk:"to"` Then *policyoptionsPolicyStatementBlockThen `tfsdk:"then"` @@ -906,10 +906,10 @@ type policyoptionsPolicyStatementData struct { } type policyoptionsPolicyStatementConfig struct { - AddItToForwardingTableExport types.Bool `tfsdk:"add_it_to_forwarding_table_export"` - DynamicDB types.Bool `tfsdk:"dynamic_db"` ID types.String `tfsdk:"id"` Name types.String `tfsdk:"name"` + AddItToForwardingTableExport types.Bool `tfsdk:"add_it_to_forwarding_table_export"` + DynamicDB types.Bool `tfsdk:"dynamic_db"` From *policyoptionsPolicyStatementBlockFromConfig `tfsdk:"from"` To *policyoptionsPolicyStatementBlockToConfig `tfsdk:"to"` Then *policyoptionsPolicyStatementBlockThenConfig `tfsdk:"then"` @@ -940,7 +940,6 @@ func (block *policyoptionsPolicyStatementBlockTermConfig) isEmpty() bool { type policyoptionsPolicyStatementBlockFrom struct { AggregateContributor types.Bool `tfsdk:"aggregate_contributor"` - NextHopTypeMerged types.Bool `tfsdk:"next_hop_type_merged"` BgpASPath []types.String `tfsdk:"bgp_as_path"` BgpASPathGroup []types.String `tfsdk:"bgp_as_path_group"` BgpCommunity []types.String `tfsdk:"bgp_community"` @@ -956,6 +955,7 @@ type policyoptionsPolicyStatementBlockFrom struct { Metric types.Int64 `tfsdk:"metric"` Neighbor []types.String `tfsdk:"neighbor"` NextHop []types.String `tfsdk:"next_hop"` + NextHopTypeMerged types.Bool `tfsdk:"next_hop_type_merged"` OspfArea types.String `tfsdk:"ospf_area"` Policy []types.String `tfsdk:"policy"` Preference types.Int64 `tfsdk:"preference"` @@ -980,7 +980,6 @@ func (block *policyoptionsPolicyStatementBlockFrom) isEmpty() bool { type policyoptionsPolicyStatementBlockFromConfig struct { AggregateContributor types.Bool `tfsdk:"aggregate_contributor"` - NextHopTypeMerged types.Bool `tfsdk:"next_hop_type_merged"` BgpASPath types.Set `tfsdk:"bgp_as_path"` BgpASPathGroup types.Set `tfsdk:"bgp_as_path_group"` BgpCommunity types.Set `tfsdk:"bgp_community"` @@ -996,6 +995,7 @@ type policyoptionsPolicyStatementBlockFromConfig struct { Metric types.Int64 `tfsdk:"metric"` Neighbor types.Set `tfsdk:"neighbor"` NextHop types.Set `tfsdk:"next_hop"` + NextHopTypeMerged types.Bool `tfsdk:"next_hop_type_merged"` OspfArea types.String `tfsdk:"ospf_area"` Policy types.List `tfsdk:"policy"` Preference types.Int64 `tfsdk:"preference"` diff --git a/internal/providerfwk/resource_policyoptions_prefix_list.go b/internal/providerfwk/resource_policyoptions_prefix_list.go index 59a37a12..a564606c 100644 --- a/internal/providerfwk/resource_policyoptions_prefix_list.go +++ b/internal/providerfwk/resource_policyoptions_prefix_list.go @@ -125,10 +125,10 @@ func (rsc *policyoptionsPrefixList) Schema( } type policyoptionsPrefixListData struct { - DynamicDB types.Bool `tfsdk:"dynamic_db"` ID types.String `tfsdk:"id"` Name types.String `tfsdk:"name"` ApplyPath types.String `tfsdk:"apply_path"` + DynamicDB types.Bool `tfsdk:"dynamic_db"` Prefix []types.String `tfsdk:"prefix"` } diff --git a/internal/providerfwk/resource_routing_instance.go b/internal/providerfwk/resource_routing_instance.go index 35e61d03..c0da3dbc 100644 --- a/internal/providerfwk/resource_routing_instance.go +++ b/internal/providerfwk/resource_routing_instance.go @@ -261,11 +261,10 @@ func (rsc *routingInstance) Schema( } type routingInstanceData struct { - ConfigureRDVrfOptSingly types.Bool `tfsdk:"configure_rd_vrfopts_singly"` - ConfigureTypeSingly types.Bool `tfsdk:"configure_type_singly"` - VRFTargetAuto types.Bool `tfsdk:"vrf_target_auto"` ID types.String `tfsdk:"id"` Name types.String `tfsdk:"name"` + ConfigureRDVrfOptSingly types.Bool `tfsdk:"configure_rd_vrfopts_singly"` + ConfigureTypeSingly types.Bool `tfsdk:"configure_type_singly"` Type types.String `tfsdk:"type"` AS types.String `tfsdk:"as"` Description types.String `tfsdk:"description"` @@ -276,6 +275,7 @@ type routingInstanceData struct { VRFExport []types.String `tfsdk:"vrf_export"` VRFImport []types.String `tfsdk:"vrf_import"` VRFTarget types.String `tfsdk:"vrf_target"` + VRFTargetAuto types.Bool `tfsdk:"vrf_target_auto"` VRFTargetExport types.String `tfsdk:"vrf_target_export"` VRFTargetImport types.String `tfsdk:"vrf_target_import"` VTEPSourceInterface types.String `tfsdk:"vtep_source_interface"` @@ -283,11 +283,10 @@ type routingInstanceData struct { } type routingInstanceConfig struct { - ConfigureRDVrfOptSingly types.Bool `tfsdk:"configure_rd_vrfopts_singly"` - ConfigureTypeSingly types.Bool `tfsdk:"configure_type_singly"` - VRFTargetAuto types.Bool `tfsdk:"vrf_target_auto"` ID types.String `tfsdk:"id"` Name types.String `tfsdk:"name"` + ConfigureRDVrfOptSingly types.Bool `tfsdk:"configure_rd_vrfopts_singly"` + ConfigureTypeSingly types.Bool `tfsdk:"configure_type_singly"` Type types.String `tfsdk:"type"` AS types.String `tfsdk:"as"` Description types.String `tfsdk:"description"` @@ -298,6 +297,7 @@ type routingInstanceConfig struct { VRFExport types.List `tfsdk:"vrf_export"` VRFImport types.List `tfsdk:"vrf_import"` VRFTarget types.String `tfsdk:"vrf_target"` + VRFTargetAuto types.Bool `tfsdk:"vrf_target_auto"` VRFTargetExport types.String `tfsdk:"vrf_target_export"` VRFTargetImport types.String `tfsdk:"vrf_target_import"` VTEPSourceInterface types.String `tfsdk:"vtep_source_interface"` diff --git a/internal/providerfwk/resource_security.go b/internal/providerfwk/resource_security.go index 01446bfd..0b08a0c3 100644 --- a/internal/providerfwk/resource_security.go +++ b/internal/providerfwk/resource_security.go @@ -868,16 +868,16 @@ func (rsc *security) Schema( int64validator.Between(10240, 1073741824), }, }, - "no_world_readable": schema.BoolAttribute{ + "world_readable": schema.BoolAttribute{ Optional: true, - Description: "Don't allow any user to read the log file.", + Description: "Allow any user to read the log file.", Validators: []validator.Bool{ tfvalidator.BoolTrue(), }, }, - "world_readable": schema.BoolAttribute{ + "no_world_readable": schema.BoolAttribute{ Optional: true, - Description: "Allow any user to read the log file.", + Description: "Don't allow any user to read the log file.", Validators: []validator.Bool{ tfvalidator.BoolTrue(), }, @@ -1275,8 +1275,8 @@ func (rsc *security) Schema( } type securityData struct { - CleanOnDestroy types.Bool `tfsdk:"clean_on_destroy"` ID types.String `tfsdk:"id"` + CleanOnDestroy types.Bool `tfsdk:"clean_on_destroy"` Alg *securityBlockAlg `tfsdk:"alg"` Flow *securityBlockFlow `tfsdk:"flow"` ForwardingOptions *securityBlockForwardingOptions `tfsdk:"forwarding_options"` @@ -1292,8 +1292,8 @@ type securityData struct { } type securityConfig struct { - CleanOnDestroy types.Bool `tfsdk:"clean_on_destroy"` ID types.String `tfsdk:"id"` + CleanOnDestroy types.Bool `tfsdk:"clean_on_destroy"` Alg *securityBlockAlg `tfsdk:"alg"` Flow *securityBlockFlow `tfsdk:"flow"` ForwardingOptions *securityBlockForwardingOptions `tfsdk:"forwarding_options"` @@ -1338,11 +1338,11 @@ type securityBlockFlow struct { ForceIPReassembly types.Bool `tfsdk:"force_ip_reassembly"` IpsecPerformanceAcceleration types.Bool `tfsdk:"ipsec_performance_acceleration"` McastBufferEnhance types.Bool `tfsdk:"mcast_buffer_enhance"` - PreserveIncomingFragmentSize types.Bool `tfsdk:"preserve_incoming_fragment_size"` - SyncIcmpSession types.Bool `tfsdk:"sync_icmp_session"` PendingSessQueueLength types.String `tfsdk:"pending_sess_queue_length"` + PreserveIncomingFragmentSize types.Bool `tfsdk:"preserve_incoming_fragment_size"` RouteChangeTimeout types.Int64 `tfsdk:"route_change_timeout"` SynFloodProtectionMode types.String `tfsdk:"syn_flood_protection_mode"` + SyncIcmpSession types.Bool `tfsdk:"sync_icmp_session"` AdvancedOptions *securityBlockFlowBlockAdvancedOptions `tfsdk:"advanced_options"` Aging *securityBlockFlowBlockAging `tfsdk:"aging"` EthernetSwitching *securityBlockFlowBlockEthernetSwitching `tfsdk:"ethernet_switching"` @@ -1406,13 +1406,13 @@ func (block *securityBlockFlowBlockTCPMss) isEmpty() bool { type securityBlockFlowBlockTCPSession struct { FinInvalidateSession types.Bool `tfsdk:"fin_invalidate_session"` + MaximumWindow types.String `tfsdk:"maximum_window"` NoSequenceCheck types.Bool `tfsdk:"no_sequence_check"` NoSynCheck types.Bool `tfsdk:"no_syn_check"` NoSynCheckInTunnel types.Bool `tfsdk:"no_syn_check_in_tunnel"` RstInvalidateSession types.Bool `tfsdk:"rst_invalidate_session"` RstSequenceCheck types.Bool `tfsdk:"rst_sequence_check"` StrictSynCheck types.Bool `tfsdk:"strict_syn_check"` - MaximumWindow types.String `tfsdk:"maximum_window"` TCPInitialTimeout types.Int64 `tfsdk:"tcp_initial_timeout"` TimeWaitState *securityBlockFlowBlockTCPSessionBlockTimeWaitState `tfsdk:"time_wait_state"` } @@ -1447,9 +1447,9 @@ func (block *securityBlockForwardingProcess) isEmpty() bool { type securityBlockIdpSecurityPackage struct { AutomaticEnable types.Bool `tfsdk:"automatic_enable"` - InstallIgnoreVersionCheck types.Bool `tfsdk:"install_ignore_version_check"` AutomaticInterval types.Int64 `tfsdk:"automatic_interval"` AutomaticStartTime types.String `tfsdk:"automatic_start_time"` + InstallIgnoreVersionCheck types.Bool `tfsdk:"install_ignore_version_check"` ProxyProfile types.String `tfsdk:"proxy_profile"` SourceAddress types.String `tfsdk:"source_address"` URL types.String `tfsdk:"url"` @@ -1512,12 +1512,12 @@ func (block *securityBlockIkeTraceoptionsConfig) isEmpty() bool { } type securityBlockIkeTraceoptionsBlockFile struct { - NoWorldReadable types.Bool `tfsdk:"no_world_readable"` - WorldReadable types.Bool `tfsdk:"world_readable"` Name types.String `tfsdk:"name"` Files types.Int64 `tfsdk:"files"` Match types.String `tfsdk:"match"` Size types.Int64 `tfsdk:"size"` + WorldReadable types.Bool `tfsdk:"world_readable"` + NoWorldReadable types.Bool `tfsdk:"no_world_readable"` } func (block *securityBlockIkeTraceoptionsBlockFile) isEmpty() bool { @@ -1526,16 +1526,16 @@ func (block *securityBlockIkeTraceoptionsBlockFile) isEmpty() bool { type securityBlockLog struct { Disable types.Bool `tfsdk:"disable"` - Report types.Bool `tfsdk:"report"` - UtcTimestamp types.Bool `tfsdk:"utc_timestamp"` EventRate types.Int64 `tfsdk:"event_rate"` FacilityOverride types.String `tfsdk:"facility_override"` Format types.String `tfsdk:"format"` MaxDatabaseRecord types.Int64 `tfsdk:"max_database_record"` Mode types.String `tfsdk:"mode"` RateCap types.Int64 `tfsdk:"rate_cap"` + Report types.Bool `tfsdk:"report"` SourceAddress types.String `tfsdk:"source_address"` SourceInterface types.String `tfsdk:"source_interface"` + UtcTimestamp types.Bool `tfsdk:"utc_timestamp"` File *securityBlockLogBlockFile `tfsdk:"file"` Transport *securityBlockLogBlockTransport `tfsdk:"transport"` } @@ -1563,17 +1563,17 @@ type securityBlockLogBlockTransport struct { type securityBlockNatSource struct { AddressPersistent types.Bool `tfsdk:"address_persistent"` - InterfacePortOverloadingOff types.Bool `tfsdk:"interface_port_overloading_off"` - PortRandomizationDisable types.Bool `tfsdk:"port_randomization_disable"` - SessionPersistenceScan types.Bool `tfsdk:"session_persistence_scan"` InterfacePortOverloadingFactor types.Int64 `tfsdk:"interface_port_overloading_factor"` + InterfacePortOverloadingOff types.Bool `tfsdk:"interface_port_overloading_off"` PoolDefaultPortRange types.Int64 `tfsdk:"pool_default_port_range"` PoolDefaultPortRangeTo types.Int64 `tfsdk:"pool_default_port_range_to"` PoolDefaultTwinPortRange types.Int64 `tfsdk:"pool_default_twin_port_range"` PoolDefaultTwinPortRangeTo types.Int64 `tfsdk:"pool_default_twin_port_range_to"` PoolUtilizationAlarmClearThreshold types.Int64 `tfsdk:"pool_utilization_alarm_clear_threshold"` PoolUtilizationAlarmRaiseThreshold types.Int64 `tfsdk:"pool_utilization_alarm_raise_threshold"` + PortRandomizationDisable types.Bool `tfsdk:"port_randomization_disable"` SessionDropHoldDown types.Int64 `tfsdk:"session_drop_hold_down"` + SessionPersistenceScan types.Bool `tfsdk:"session_persistence_scan"` } func (block *securityBlockNatSource) isEmpty() bool { diff --git a/internal/providerfwk/resource_security_global_policy.go b/internal/providerfwk/resource_security_global_policy.go index 2a63ac98..89500735 100644 --- a/internal/providerfwk/resource_security_global_policy.go +++ b/internal/providerfwk/resource_security_global_policy.go @@ -375,39 +375,39 @@ type securityGlobalPolicyConfig struct { //nolint:lll type securityGlobalPolicyBlockPolicy struct { - Count types.Bool `tfsdk:"count"` - LogInit types.Bool `tfsdk:"log_init"` - LogClose types.Bool `tfsdk:"log_close"` - MatchDestinationAddressExcluded types.Bool `tfsdk:"match_destination_address_excluded"` - MatchSourceAddressExcluded types.Bool `tfsdk:"match_source_address_excluded"` Name types.String `tfsdk:"name"` - Then types.String `tfsdk:"then"` - MatchSourceEndUserProfile types.String `tfsdk:"match_source_end_user_profile"` MatchSourceAddress []types.String `tfsdk:"match_source_address"` MatchDestinationAddress []types.String `tfsdk:"match_destination_address"` MatchFromZone []types.String `tfsdk:"match_from_zone"` MatchToZone []types.String `tfsdk:"match_to_zone"` + Then types.String `tfsdk:"then"` + Count types.Bool `tfsdk:"count"` + LogInit types.Bool `tfsdk:"log_init"` + LogClose types.Bool `tfsdk:"log_close"` MatchApplication []types.String `tfsdk:"match_application"` + MatchDestinationAddressExcluded types.Bool `tfsdk:"match_destination_address_excluded"` MatchDynamicApplication []types.String `tfsdk:"match_dynamic_application"` + MatchSourceAddressExcluded types.Bool `tfsdk:"match_source_address_excluded"` + MatchSourceEndUserProfile types.String `tfsdk:"match_source_end_user_profile"` PermitApplicationServices *securityPolicyBlockPolicyBlockPermitApplicationServices `tfsdk:"permit_application_services"` } //nolint:lll type securityGlobalPolicyBlockPolicyConfig struct { - Count types.Bool `tfsdk:"count"` - LogInit types.Bool `tfsdk:"log_init"` - LogClose types.Bool `tfsdk:"log_close"` - MatchDestinationAddressExcluded types.Bool `tfsdk:"match_destination_address_excluded"` - MatchSourceAddressExcluded types.Bool `tfsdk:"match_source_address_excluded"` Name types.String `tfsdk:"name"` - Then types.String `tfsdk:"then"` - MatchSourceEndUserProfile types.String `tfsdk:"match_source_end_user_profile"` MatchSourceAddress types.Set `tfsdk:"match_source_address"` MatchDestinationAddress types.Set `tfsdk:"match_destination_address"` MatchFromZone types.Set `tfsdk:"match_from_zone"` MatchToZone types.Set `tfsdk:"match_to_zone"` + Then types.String `tfsdk:"then"` + Count types.Bool `tfsdk:"count"` + LogInit types.Bool `tfsdk:"log_init"` + LogClose types.Bool `tfsdk:"log_close"` MatchApplication types.Set `tfsdk:"match_application"` + MatchDestinationAddressExcluded types.Bool `tfsdk:"match_destination_address_excluded"` MatchDynamicApplication types.Set `tfsdk:"match_dynamic_application"` + MatchSourceAddressExcluded types.Bool `tfsdk:"match_source_address_excluded"` + MatchSourceEndUserProfile types.String `tfsdk:"match_source_end_user_profile"` PermitApplicationServices *securityPolicyBlockPolicyBlockPermitApplicationServices `tfsdk:"permit_application_services"` } diff --git a/internal/providerfwk/resource_security_ike_gateway.go b/internal/providerfwk/resource_security_ike_gateway.go index d79bcc6f..da9a42ab 100644 --- a/internal/providerfwk/resource_security_ike_gateway.go +++ b/internal/providerfwk/resource_security_ike_gateway.go @@ -374,14 +374,14 @@ func (rsc *securityIkeGateway) Schema( } type securityIkeGatewayData struct { - GeneralIkeID types.Bool `tfsdk:"general_ike_id"` - NoNatTraversal types.Bool `tfsdk:"no_nat_traversal"` ID types.String `tfsdk:"id"` Name types.String `tfsdk:"name"` ExternalInterface types.String `tfsdk:"external_interface"` Policy types.String `tfsdk:"policy"` Address []types.String `tfsdk:"address"` + GeneralIkeID types.Bool `tfsdk:"general_ike_id"` LocalAddress types.String `tfsdk:"local_address"` + NoNatTraversal types.Bool `tfsdk:"no_nat_traversal"` Version types.String `tfsdk:"version"` Aaa *securityIkeGatewayBlockAaa `tfsdk:"aaa"` DeadPeerDetection *securityIkeGatewayBlockDeadPeerDetection `tfsdk:"dead_peer_detection"` @@ -391,14 +391,14 @@ type securityIkeGatewayData struct { } type securityIkeGatewayConfig struct { - GeneralIkeID types.Bool `tfsdk:"general_ike_id"` - NoNatTraversal types.Bool `tfsdk:"no_nat_traversal"` ID types.String `tfsdk:"id"` Name types.String `tfsdk:"name"` ExternalInterface types.String `tfsdk:"external_interface"` Policy types.String `tfsdk:"policy"` Address types.List `tfsdk:"address"` + GeneralIkeID types.Bool `tfsdk:"general_ike_id"` LocalAddress types.String `tfsdk:"local_address"` + NoNatTraversal types.Bool `tfsdk:"no_nat_traversal"` Version types.String `tfsdk:"version"` Aaa *securityIkeGatewayBlockAaa `tfsdk:"aaa"` DeadPeerDetection *securityIkeGatewayBlockDeadPeerDetection `tfsdk:"dead_peer_detection"` diff --git a/internal/providerfwk/resource_security_ipsec_vpn.go b/internal/providerfwk/resource_security_ipsec_vpn.go index 43234513..c0223f45 100644 --- a/internal/providerfwk/resource_security_ipsec_vpn.go +++ b/internal/providerfwk/resource_security_ipsec_vpn.go @@ -377,10 +377,10 @@ func (rsc *securityIpsecVpn) Schema( } type securityIpsecVpnData struct { - CopyOuterDscp types.Bool `tfsdk:"copy_outer_dscp"` ID types.String `tfsdk:"id"` Name types.String `tfsdk:"name"` BindInterface types.String `tfsdk:"bind_interface"` + CopyOuterDscp types.Bool `tfsdk:"copy_outer_dscp"` DfBit types.String `tfsdk:"df_bit"` EstablishTunnels types.String `tfsdk:"establish_tunnels"` Ike *securityIpsecVpnBlockIke `tfsdk:"ike"` @@ -392,10 +392,10 @@ type securityIpsecVpnData struct { } type securityIpsecVpnConfig struct { - CopyOuterDscp types.Bool `tfsdk:"copy_outer_dscp"` ID types.String `tfsdk:"id"` Name types.String `tfsdk:"name"` BindInterface types.String `tfsdk:"bind_interface"` + CopyOuterDscp types.Bool `tfsdk:"copy_outer_dscp"` DfBit types.String `tfsdk:"df_bit"` EstablishTunnels types.String `tfsdk:"establish_tunnels"` Ike *securityIpsecVpnBlockIke `tfsdk:"ike"` @@ -446,10 +446,10 @@ type securityIpsecVpnBlockUDPEncapsulate struct { } type securityIpsecVpnBlockVpnMonitor struct { - Optimized types.Bool `tfsdk:"optimized"` - SourceInterfaceAuto types.Bool `tfsdk:"source_interface_auto"` DestinationIP types.String `tfsdk:"destination_ip"` + Optimized types.Bool `tfsdk:"optimized"` SourceInterface types.String `tfsdk:"source_interface"` + SourceInterfaceAuto types.Bool `tfsdk:"source_interface_auto"` } func (block *securityIpsecVpnBlockVpnMonitor) hasKnownValue() bool { diff --git a/internal/providerfwk/resource_security_nat_static.go b/internal/providerfwk/resource_security_nat_static.go index 7bc720e9..1b782ce1 100644 --- a/internal/providerfwk/resource_security_nat_static.go +++ b/internal/providerfwk/resource_security_nat_static.go @@ -287,18 +287,18 @@ func (rsc *securityNatStatic) Schema( } type securityNatStaticData struct { - ConfigureRulesSingly types.Bool `tfsdk:"configure_rules_singly"` ID types.String `tfsdk:"id"` Name types.String `tfsdk:"name"` + ConfigureRulesSingly types.Bool `tfsdk:"configure_rules_singly"` Description types.String `tfsdk:"description"` From *securityNatStaticBlockFrom `tfsdk:"from"` Rule []securityNatStaticBlockRule `tfsdk:"rule"` } type securityNatStaticConfig struct { - ConfigureRulesSingly types.Bool `tfsdk:"configure_rules_singly"` ID types.String `tfsdk:"id"` Name types.String `tfsdk:"name"` + ConfigureRulesSingly types.Bool `tfsdk:"configure_rules_singly"` Description types.String `tfsdk:"description"` From *securityNatStaticBlockFromConfig `tfsdk:"from"` Rule types.List `tfsdk:"rule"` diff --git a/internal/providerfwk/resource_security_policy.go b/internal/providerfwk/resource_security_policy.go index a633ea1e..6d9c24aa 100644 --- a/internal/providerfwk/resource_security_policy.go +++ b/internal/providerfwk/resource_security_policy.go @@ -386,58 +386,58 @@ type securityPolicyConfig struct { //nolint:lll type securityPolicyBlockPolicy struct { + Name types.String `tfsdk:"name"` + MatchSourceAddress []types.String `tfsdk:"match_source_address"` + MatchDestinationAddress []types.String `tfsdk:"match_destination_address"` + Then types.String `tfsdk:"then"` Count types.Bool `tfsdk:"count"` LogInit types.Bool `tfsdk:"log_init"` LogClose types.Bool `tfsdk:"log_close"` + MatchApplication []types.String `tfsdk:"match_application"` MatchDestinationAddressExcluded types.Bool `tfsdk:"match_destination_address_excluded"` + MatchDynamicApplication []types.String `tfsdk:"match_dynamic_application"` MatchSourceAddressExcluded types.Bool `tfsdk:"match_source_address_excluded"` - Name types.String `tfsdk:"name"` - Then types.String `tfsdk:"then"` MatchSourceEndUserProfile types.String `tfsdk:"match_source_end_user_profile"` PermitTunnelIpsecVpn types.String `tfsdk:"permit_tunnel_ipsec_vpn"` - MatchSourceAddress []types.String `tfsdk:"match_source_address"` - MatchDestinationAddress []types.String `tfsdk:"match_destination_address"` - MatchApplication []types.String `tfsdk:"match_application"` - MatchDynamicApplication []types.String `tfsdk:"match_dynamic_application"` PermitApplicationServices *securityPolicyBlockPolicyBlockPermitApplicationServices `tfsdk:"permit_application_services"` } //nolint:lll type securityPolicyBlockPolicyConfig struct { + Name types.String `tfsdk:"name"` + MatchSourceAddress types.Set `tfsdk:"match_source_address"` + MatchDestinationAddress types.Set `tfsdk:"match_destination_address"` + Then types.String `tfsdk:"then"` Count types.Bool `tfsdk:"count"` LogInit types.Bool `tfsdk:"log_init"` LogClose types.Bool `tfsdk:"log_close"` + MatchApplication types.Set `tfsdk:"match_application"` MatchDestinationAddressExcluded types.Bool `tfsdk:"match_destination_address_excluded"` + MatchDynamicApplication types.Set `tfsdk:"match_dynamic_application"` MatchSourceAddressExcluded types.Bool `tfsdk:"match_source_address_excluded"` - Name types.String `tfsdk:"name"` - Then types.String `tfsdk:"then"` MatchSourceEndUserProfile types.String `tfsdk:"match_source_end_user_profile"` PermitTunnelIpsecVpn types.String `tfsdk:"permit_tunnel_ipsec_vpn"` - MatchSourceAddress types.Set `tfsdk:"match_source_address"` - MatchDestinationAddress types.Set `tfsdk:"match_destination_address"` - MatchApplication types.Set `tfsdk:"match_application"` - MatchDynamicApplication types.Set `tfsdk:"match_dynamic_application"` PermitApplicationServices *securityPolicyBlockPolicyBlockPermitApplicationServices `tfsdk:"permit_application_services"` } type securityPolicyBlockPolicyBlockPermitApplicationServices struct { - Idp types.Bool `tfsdk:"idp"` - RedirectWx types.Bool `tfsdk:"redirect_wx"` - ReverseRedirectWx types.Bool `tfsdk:"reverse_redirect_wx"` AdvancedAntiMalwarePolicy types.String `tfsdk:"advanced_anti_malware_policy"` ApplicationFirewallRuleSet types.String `tfsdk:"application_firewall_rule_set"` ApplicationTrafficControlRuleSet types.String `tfsdk:"application_traffic_control_rule_set"` GprsGtpProfile types.String `tfsdk:"gprs_gtp_profile"` GprsSctpProfile types.String `tfsdk:"gprs_sctp_profile"` + Idp types.Bool `tfsdk:"idp"` IdpPolicy types.String `tfsdk:"idp_policy"` + RedirectWx types.Bool `tfsdk:"redirect_wx"` + ReverseRedirectWx types.Bool `tfsdk:"reverse_redirect_wx"` SecurityIntelligencePolicy types.String `tfsdk:"security_intelligence_policy"` + UtmPolicy types.String `tfsdk:"utm_policy"` SSLProxy *struct { ProfileName types.String `tfsdk:"profile_name"` } `tfsdk:"ssl_proxy"` UacPolicy *struct { CaptivePortal types.String `tfsdk:"captive_portal"` } `tfsdk:"uac_policy"` - UtmPolicy types.String `tfsdk:"utm_policy"` } func (block *securityPolicyBlockPolicyBlockPermitApplicationServices) isEmpty() bool { @@ -1043,6 +1043,8 @@ func (block *securityPolicyBlockPolicyBlockPermitApplicationServices) read( block.ReverseRedirectWx = types.BoolValue(true) case balt.CutPrefixInString(&itemTrim, "security-intelligence-policy "): block.SecurityIntelligencePolicy = types.StringValue(strings.Trim(itemTrim, "\"")) + case balt.CutPrefixInString(&itemTrim, "utm-policy "): + block.UtmPolicy = types.StringValue(strings.Trim(itemTrim, "\"")) case balt.CutPrefixInString(&itemTrim, "ssl-proxy"): if balt.CutPrefixInString(&itemTrim, " profile-name ") { block.SSLProxy = &struct { @@ -1067,8 +1069,6 @@ func (block *securityPolicyBlockPolicyBlockPermitApplicationServices) read( CaptivePortal types.String `tfsdk:"captive_portal"` }{} } - case balt.CutPrefixInString(&itemTrim, "utm-policy "): - block.UtmPolicy = types.StringValue(strings.Trim(itemTrim, "\"")) } } diff --git a/internal/providerfwk/resource_security_zone.go b/internal/providerfwk/resource_security_zone.go index 8d673056..28228a30 100644 --- a/internal/providerfwk/resource_security_zone.go +++ b/internal/providerfwk/resource_security_zone.go @@ -376,18 +376,18 @@ func (rsc *securityZone) Schema( } type securityZoneData struct { - AddressBookConfigureSingly types.Bool `tfsdk:"address_book_configure_singly"` - ApplicationTracking types.Bool `tfsdk:"application_tracking"` - ReverseReroute types.Bool `tfsdk:"reverse_reroute"` - SourceIdentityLog types.Bool `tfsdk:"source_identity_log"` - TCPRst types.Bool `tfsdk:"tcp_rst"` ID types.String `tfsdk:"id"` Name types.String `tfsdk:"name"` + AddressBookConfigureSingly types.Bool `tfsdk:"address_book_configure_singly"` AdvancePolicyBasedRoutingProfile types.String `tfsdk:"advance_policy_based_routing_profile"` + ApplicationTracking types.Bool `tfsdk:"application_tracking"` Description types.String `tfsdk:"description"` - Screen types.String `tfsdk:"screen"` InboundProtocols []types.String `tfsdk:"inbound_protocols"` InboundServices []types.String `tfsdk:"inbound_services"` + ReverseReroute types.Bool `tfsdk:"reverse_reroute"` + Screen types.String `tfsdk:"screen"` + SourceIdentityLog types.Bool `tfsdk:"source_identity_log"` + TCPRst types.Bool `tfsdk:"tcp_rst"` AddressBook []securityZoneBlockAddressBook `tfsdk:"address_book"` AddressBookDNS []securityZoneBlockAddressBookDNS `tfsdk:"address_book_dns"` AddressBookRange []securityZoneBlockAddressBookRange `tfsdk:"address_book_range"` @@ -397,18 +397,18 @@ type securityZoneData struct { } type securityZoneConfig struct { - AddressBookConfigureSingly types.Bool `tfsdk:"address_book_configure_singly"` - ApplicationTracking types.Bool `tfsdk:"application_tracking"` - ReverseReroute types.Bool `tfsdk:"reverse_reroute"` - SourceIdentityLog types.Bool `tfsdk:"source_identity_log"` - TCPRst types.Bool `tfsdk:"tcp_rst"` ID types.String `tfsdk:"id"` Name types.String `tfsdk:"name"` + AddressBookConfigureSingly types.Bool `tfsdk:"address_book_configure_singly"` AdvancePolicyBasedRoutingProfile types.String `tfsdk:"advance_policy_based_routing_profile"` + ApplicationTracking types.Bool `tfsdk:"application_tracking"` Description types.String `tfsdk:"description"` - Screen types.String `tfsdk:"screen"` InboundProtocols types.Set `tfsdk:"inbound_protocols"` InboundServices types.Set `tfsdk:"inbound_services"` + ReverseReroute types.Bool `tfsdk:"reverse_reroute"` + Screen types.String `tfsdk:"screen"` + SourceIdentityLog types.Bool `tfsdk:"source_identity_log"` + TCPRst types.Bool `tfsdk:"tcp_rst"` AddressBook types.Set `tfsdk:"address_book"` AddressBookDNS types.Set `tfsdk:"address_book_dns"` AddressBookRange types.Set `tfsdk:"address_book_range"` diff --git a/internal/providerfwk/resource_services_flowmonitoring_v9_template.go b/internal/providerfwk/resource_services_flowmonitoring_v9_template.go index 1792cac3..42fe06bf 100644 --- a/internal/providerfwk/resource_services_flowmonitoring_v9_template.go +++ b/internal/providerfwk/resource_services_flowmonitoring_v9_template.go @@ -271,47 +271,47 @@ func (rsc *servicesFlowMonitoringV9Template) Schema( } type servicesFlowMonitoringV9TemplateData struct { - FlowKeyFlowDirection types.Bool `tfsdk:"flow_key_flow_direction"` - FlowKeyOutputInterface types.Bool `tfsdk:"flow_key_output_interface"` - FlowKeyVlanID types.Bool `tfsdk:"flow_key_vlan_id"` - NexthopLearningEnable types.Bool `tfsdk:"nexthop_learning_enable"` - NexthopLearningDisable types.Bool `tfsdk:"nexthop_learning_disable"` - TunnelObservationIPv4 types.Bool `tfsdk:"tunnel_observation_ipv4"` - TunnelObservationIPv6 types.Bool `tfsdk:"tunnel_observation_ipv6"` ID types.String `tfsdk:"id"` Name types.String `tfsdk:"name"` Type types.String `tfsdk:"type"` FlowActiveTimeout types.Int64 `tfsdk:"flow_active_timeout"` FlowInactiveTimeout types.Int64 `tfsdk:"flow_inactive_timeout"` + FlowKeyFlowDirection types.Bool `tfsdk:"flow_key_flow_direction"` + FlowKeyOutputInterface types.Bool `tfsdk:"flow_key_output_interface"` + FlowKeyVlanID types.Bool `tfsdk:"flow_key_vlan_id"` IPTemplateExportExtension []types.String `tfsdk:"ip_template_export_extension"` MPLSTemplateLabelPosition []types.Int64 `tfsdk:"mpls_template_label_position"` + NexthopLearningEnable types.Bool `tfsdk:"nexthop_learning_enable"` + NexthopLearningDisable types.Bool `tfsdk:"nexthop_learning_disable"` OptionTemplateID types.Int64 `tfsdk:"option_template_id"` SourceID types.Int64 `tfsdk:"source_id"` TemplateID types.Int64 `tfsdk:"template_id"` OptionRefreshRate *servicesFlowMonitoringV9TemplateBlockRefreshRate `tfsdk:"option_refresh_rate"` TemplateRefreshRate *servicesFlowMonitoringV9TemplateBlockRefreshRate `tfsdk:"template_refresh_rate"` + TunnelObservationIPv4 types.Bool `tfsdk:"tunnel_observation_ipv4"` + TunnelObservationIPv6 types.Bool `tfsdk:"tunnel_observation_ipv6"` } type servicesFlowMonitoringV9TemplateConfig struct { - FlowKeyFlowDirection types.Bool `tfsdk:"flow_key_flow_direction"` - FlowKeyOutputInterface types.Bool `tfsdk:"flow_key_output_interface"` - FlowKeyVlanID types.Bool `tfsdk:"flow_key_vlan_id"` - NexthopLearningEnable types.Bool `tfsdk:"nexthop_learning_enable"` - NexthopLearningDisable types.Bool `tfsdk:"nexthop_learning_disable"` - TunnelObservationIPv4 types.Bool `tfsdk:"tunnel_observation_ipv4"` - TunnelObservationIPv6 types.Bool `tfsdk:"tunnel_observation_ipv6"` ID types.String `tfsdk:"id"` Name types.String `tfsdk:"name"` Type types.String `tfsdk:"type"` FlowActiveTimeout types.Int64 `tfsdk:"flow_active_timeout"` FlowInactiveTimeout types.Int64 `tfsdk:"flow_inactive_timeout"` + FlowKeyFlowDirection types.Bool `tfsdk:"flow_key_flow_direction"` + FlowKeyOutputInterface types.Bool `tfsdk:"flow_key_output_interface"` + FlowKeyVlanID types.Bool `tfsdk:"flow_key_vlan_id"` IPTemplateExportExtension types.Set `tfsdk:"ip_template_export_extension"` MPLSTemplateLabelPosition types.List `tfsdk:"mpls_template_label_position"` + NexthopLearningEnable types.Bool `tfsdk:"nexthop_learning_enable"` + NexthopLearningDisable types.Bool `tfsdk:"nexthop_learning_disable"` OptionTemplateID types.Int64 `tfsdk:"option_template_id"` SourceID types.Int64 `tfsdk:"source_id"` TemplateID types.Int64 `tfsdk:"template_id"` OptionRefreshRate *servicesFlowMonitoringV9TemplateBlockRefreshRate `tfsdk:"option_refresh_rate"` TemplateRefreshRate *servicesFlowMonitoringV9TemplateBlockRefreshRate `tfsdk:"template_refresh_rate"` + TunnelObservationIPv4 types.Bool `tfsdk:"tunnel_observation_ipv4"` + TunnelObservationIPv6 types.Bool `tfsdk:"tunnel_observation_ipv6"` } type servicesFlowMonitoringV9TemplateBlockRefreshRate struct { diff --git a/internal/providerfwk/resource_services_flowmonitoring_vipfix_template.go b/internal/providerfwk/resource_services_flowmonitoring_vipfix_template.go index e750a2d4..e22c8101 100644 --- a/internal/providerfwk/resource_services_flowmonitoring_vipfix_template.go +++ b/internal/providerfwk/resource_services_flowmonitoring_vipfix_template.go @@ -267,47 +267,47 @@ func (rsc *servicesFlowMonitoringVIPFixTemplate) Schema( } type servicesFlowMonitoringVIPFixTemplateData struct { - FlowKeyFlowDirection types.Bool `tfsdk:"flow_key_flow_direction"` - FlowKeyOutputInterface types.Bool `tfsdk:"flow_key_output_interface"` - FlowKeyVlanID types.Bool `tfsdk:"flow_key_vlan_id"` - NexthopLearningEnable types.Bool `tfsdk:"nexthop_learning_enable"` - NexthopLearningDisable types.Bool `tfsdk:"nexthop_learning_disable"` - TunnelObservationIPv4 types.Bool `tfsdk:"tunnel_observation_ipv4"` - TunnelObservationIPv6 types.Bool `tfsdk:"tunnel_observation_ipv6"` ID types.String `tfsdk:"id"` Name types.String `tfsdk:"name"` Type types.String `tfsdk:"type"` FlowActiveTimeout types.Int64 `tfsdk:"flow_active_timeout"` FlowInactiveTimeout types.Int64 `tfsdk:"flow_inactive_timeout"` + FlowKeyFlowDirection types.Bool `tfsdk:"flow_key_flow_direction"` + FlowKeyOutputInterface types.Bool `tfsdk:"flow_key_output_interface"` + FlowKeyVlanID types.Bool `tfsdk:"flow_key_vlan_id"` IPTemplateExportExtension []types.String `tfsdk:"ip_template_export_extension"` MPLSTemplateLabelPosition []types.Int64 `tfsdk:"mpls_template_label_position"` + NexthopLearningEnable types.Bool `tfsdk:"nexthop_learning_enable"` + NexthopLearningDisable types.Bool `tfsdk:"nexthop_learning_disable"` ObservationDomainID types.Int64 `tfsdk:"observation_domain_id"` OptionTemplateID types.Int64 `tfsdk:"option_template_id"` TemplateID types.Int64 `tfsdk:"template_id"` OptionRefreshRate *servicesFlowMonitoringVIPFixTemplateBlockRefreshRate `tfsdk:"option_refresh_rate"` TemplateRefreshRate *servicesFlowMonitoringVIPFixTemplateBlockRefreshRate `tfsdk:"template_refresh_rate"` + TunnelObservationIPv4 types.Bool `tfsdk:"tunnel_observation_ipv4"` + TunnelObservationIPv6 types.Bool `tfsdk:"tunnel_observation_ipv6"` } type servicesFlowMonitoringVIPFixTemplateConfig struct { - FlowKeyFlowDirection types.Bool `tfsdk:"flow_key_flow_direction"` - FlowKeyOutputInterface types.Bool `tfsdk:"flow_key_output_interface"` - FlowKeyVlanID types.Bool `tfsdk:"flow_key_vlan_id"` - NexthopLearningEnable types.Bool `tfsdk:"nexthop_learning_enable"` - NexthopLearningDisable types.Bool `tfsdk:"nexthop_learning_disable"` - TunnelObservationIPv4 types.Bool `tfsdk:"tunnel_observation_ipv4"` - TunnelObservationIPv6 types.Bool `tfsdk:"tunnel_observation_ipv6"` ID types.String `tfsdk:"id"` Name types.String `tfsdk:"name"` Type types.String `tfsdk:"type"` FlowActiveTimeout types.Int64 `tfsdk:"flow_active_timeout"` FlowInactiveTimeout types.Int64 `tfsdk:"flow_inactive_timeout"` + FlowKeyFlowDirection types.Bool `tfsdk:"flow_key_flow_direction"` + FlowKeyOutputInterface types.Bool `tfsdk:"flow_key_output_interface"` + FlowKeyVlanID types.Bool `tfsdk:"flow_key_vlan_id"` IPTemplateExportExtension types.Set `tfsdk:"ip_template_export_extension"` MPLSTemplateLabelPosition types.List `tfsdk:"mpls_template_label_position"` + NexthopLearningEnable types.Bool `tfsdk:"nexthop_learning_enable"` + NexthopLearningDisable types.Bool `tfsdk:"nexthop_learning_disable"` ObservationDomainID types.Int64 `tfsdk:"observation_domain_id"` OptionTemplateID types.Int64 `tfsdk:"option_template_id"` TemplateID types.Int64 `tfsdk:"template_id"` OptionRefreshRate *servicesFlowMonitoringVIPFixTemplateBlockRefreshRate `tfsdk:"option_refresh_rate"` TemplateRefreshRate *servicesFlowMonitoringVIPFixTemplateBlockRefreshRate `tfsdk:"template_refresh_rate"` + TunnelObservationIPv4 types.Bool `tfsdk:"tunnel_observation_ipv4"` + TunnelObservationIPv6 types.Bool `tfsdk:"tunnel_observation_ipv6"` } type servicesFlowMonitoringVIPFixTemplateBlockRefreshRate struct { diff --git a/internal/providerfwk/resource_snmp.go b/internal/providerfwk/resource_snmp.go index 0b09e59d..44613a76 100644 --- a/internal/providerfwk/resource_snmp.go +++ b/internal/providerfwk/resource_snmp.go @@ -272,46 +272,46 @@ func (rsc *snmp) Schema( } type snmpData struct { + ID types.String `tfsdk:"id"` CleanOnDestroy types.Bool `tfsdk:"clean_on_destroy"` ARP types.Bool `tfsdk:"arp"` ARPHostNameResolution types.Bool `tfsdk:"arp_host_name_resolution"` - FilterDuplicates types.Bool `tfsdk:"filter_duplicates"` - FilterInternalInterfaces types.Bool `tfsdk:"filter_internal_interfaces"` - IfCountWithFilterInterfaces types.Bool `tfsdk:"if_count_with_filter_interfaces"` - RoutingInstanceAccess types.Bool `tfsdk:"routing_instance_access"` - ID types.String `tfsdk:"id"` Contact types.String `tfsdk:"contact"` Description types.String `tfsdk:"description"` EngineID types.String `tfsdk:"engine_id"` + FilterDuplicates types.Bool `tfsdk:"filter_duplicates"` FilterInterfaces []types.String `tfsdk:"filter_interfaces"` + FilterInternalInterfaces types.Bool `tfsdk:"filter_internal_interfaces"` + IfCountWithFilterInterfaces types.Bool `tfsdk:"if_count_with_filter_interfaces"` Interface []types.String `tfsdk:"interface"` Location types.String `tfsdk:"location"` + RoutingInstanceAccess types.Bool `tfsdk:"routing_instance_access"` RoutingInstanceAccessList []types.String `tfsdk:"routing_instance_access_list"` HealthMonitor *snmpBlockHealthMonitor `tfsdk:"health_monitor"` } type snmpConfig struct { + ID types.String `tfsdk:"id"` CleanOnDestroy types.Bool `tfsdk:"clean_on_destroy"` ARP types.Bool `tfsdk:"arp"` ARPHostNameResolution types.Bool `tfsdk:"arp_host_name_resolution"` - FilterDuplicates types.Bool `tfsdk:"filter_duplicates"` - FilterInternalInterfaces types.Bool `tfsdk:"filter_internal_interfaces"` - IfCountWithFilterInterfaces types.Bool `tfsdk:"if_count_with_filter_interfaces"` - RoutingInstanceAccess types.Bool `tfsdk:"routing_instance_access"` - ID types.String `tfsdk:"id"` Contact types.String `tfsdk:"contact"` Description types.String `tfsdk:"description"` EngineID types.String `tfsdk:"engine_id"` + FilterDuplicates types.Bool `tfsdk:"filter_duplicates"` FilterInterfaces types.Set `tfsdk:"filter_interfaces"` + FilterInternalInterfaces types.Bool `tfsdk:"filter_internal_interfaces"` + IfCountWithFilterInterfaces types.Bool `tfsdk:"if_count_with_filter_interfaces"` Interface types.Set `tfsdk:"interface"` Location types.String `tfsdk:"location"` + RoutingInstanceAccess types.Bool `tfsdk:"routing_instance_access"` RoutingInstanceAccessList types.Set `tfsdk:"routing_instance_access_list"` HealthMonitor *snmpBlockHealthMonitor `tfsdk:"health_monitor"` } type snmpBlockHealthMonitor struct { - Idp types.Bool `tfsdk:"idp"` FallingThreshold types.Int64 `tfsdk:"falling_threshold"` + Idp types.Bool `tfsdk:"idp"` IdpFallingThreshold types.Int64 `tfsdk:"idp_falling_threshold"` IdpInterval types.Int64 `tfsdk:"idp_interval"` IdpRisingThreshold types.Int64 `tfsdk:"idp_rising_threshold"` diff --git a/internal/providerfwk/resource_snmp_community.go b/internal/providerfwk/resource_snmp_community.go index 230bbcf3..c5936740 100644 --- a/internal/providerfwk/resource_snmp_community.go +++ b/internal/providerfwk/resource_snmp_community.go @@ -180,10 +180,10 @@ func (rsc *snmpCommunity) Schema( } type snmpCommunityData struct { - AuthorizationReadOnly types.Bool `tfsdk:"authorization_read_only"` - AuthorizationReadWrite types.Bool `tfsdk:"authorization_read_write"` ID types.String `tfsdk:"id"` Name types.String `tfsdk:"name"` + AuthorizationReadOnly types.Bool `tfsdk:"authorization_read_only"` + AuthorizationReadWrite types.Bool `tfsdk:"authorization_read_write"` ClientListName types.String `tfsdk:"client_list_name"` Clients []types.String `tfsdk:"clients"` View types.String `tfsdk:"view"` @@ -191,10 +191,10 @@ type snmpCommunityData struct { } type snmpCommunityConfig struct { - AuthorizationReadOnly types.Bool `tfsdk:"authorization_read_only"` - AuthorizationReadWrite types.Bool `tfsdk:"authorization_read_write"` ID types.String `tfsdk:"id"` Name types.String `tfsdk:"name"` + AuthorizationReadOnly types.Bool `tfsdk:"authorization_read_only"` + AuthorizationReadWrite types.Bool `tfsdk:"authorization_read_write"` ClientListName types.String `tfsdk:"client_list_name"` Clients types.Set `tfsdk:"clients"` View types.String `tfsdk:"view"` diff --git a/internal/providerfwk/resource_static_route.go b/internal/providerfwk/resource_static_route.go index a6f93823..87ef3e64 100644 --- a/internal/providerfwk/resource_static_route.go +++ b/internal/providerfwk/resource_static_route.go @@ -338,12 +338,24 @@ func (rsc *staticRoute) Schema( } type staticRouteData struct { + ID types.String `tfsdk:"id"` + Destination types.String `tfsdk:"destination"` + RoutingInstance types.String `tfsdk:"routing_instance"` Active types.Bool `tfsdk:"active"` + ASPathAggregatorAddress types.String `tfsdk:"as_path_aggregator_address"` + ASPathAggregatorASNumber types.String `tfsdk:"as_path_aggregator_as_number"` ASPathAtomicAggregate types.Bool `tfsdk:"as_path_atomic_aggregate"` + ASPathOrigin types.String `tfsdk:"as_path_origin"` + ASPathPath types.String `tfsdk:"as_path_path"` + Community []types.String `tfsdk:"community"` Discard types.Bool `tfsdk:"discard"` Install types.Bool `tfsdk:"install"` NoInstall types.Bool `tfsdk:"no_install"` + Metric types.Int64 `tfsdk:"metric"` + NextHop []types.String `tfsdk:"next_hop"` + NextTable types.String `tfsdk:"next_table"` Passive types.Bool `tfsdk:"passive"` + Preference types.Int64 `tfsdk:"preference"` Readvertise types.Bool `tfsdk:"readvertise"` NoReadvertise types.Bool `tfsdk:"no_readvertise"` Receive types.Bool `tfsdk:"receive"` @@ -352,28 +364,28 @@ type staticRouteData struct { NoResolve types.Bool `tfsdk:"no_resolve"` Retain types.Bool `tfsdk:"retain"` NoRetain types.Bool `tfsdk:"no_retain"` - ID types.String `tfsdk:"id"` - Destination types.String `tfsdk:"destination"` - RoutingInstance types.String `tfsdk:"routing_instance"` - ASPathAggregatorAddress types.String `tfsdk:"as_path_aggregator_address"` - ASPathAggregatorASNumber types.String `tfsdk:"as_path_aggregator_as_number"` - ASPathOrigin types.String `tfsdk:"as_path_origin"` - ASPathPath types.String `tfsdk:"as_path_path"` - Community []types.String `tfsdk:"community"` - Metric types.Int64 `tfsdk:"metric"` - NextHop []types.String `tfsdk:"next_hop"` - NextTable types.String `tfsdk:"next_table"` - Preference types.Int64 `tfsdk:"preference"` QualifiedNextHop []staticRouteBlockQualifiedNextHop `tfsdk:"qualified_next_hop"` } type staticRouteConfig struct { + ID types.String `tfsdk:"id"` + Destination types.String `tfsdk:"destination"` + RoutingInstance types.String `tfsdk:"routing_instance"` Active types.Bool `tfsdk:"active"` + ASPathAggregatorAddress types.String `tfsdk:"as_path_aggregator_address"` + ASPathAggregatorASNumber types.String `tfsdk:"as_path_aggregator_as_number"` ASPathAtomicAggregate types.Bool `tfsdk:"as_path_atomic_aggregate"` + ASPathOrigin types.String `tfsdk:"as_path_origin"` + ASPathPath types.String `tfsdk:"as_path_path"` + Community types.List `tfsdk:"community"` Discard types.Bool `tfsdk:"discard"` Install types.Bool `tfsdk:"install"` NoInstall types.Bool `tfsdk:"no_install"` + Metric types.Int64 `tfsdk:"metric"` + NextHop types.List `tfsdk:"next_hop"` + NextTable types.String `tfsdk:"next_table"` Passive types.Bool `tfsdk:"passive"` + Preference types.Int64 `tfsdk:"preference"` Readvertise types.Bool `tfsdk:"readvertise"` NoReadvertise types.Bool `tfsdk:"no_readvertise"` Receive types.Bool `tfsdk:"receive"` @@ -382,18 +394,6 @@ type staticRouteConfig struct { NoResolve types.Bool `tfsdk:"no_resolve"` Retain types.Bool `tfsdk:"retain"` NoRetain types.Bool `tfsdk:"no_retain"` - ID types.String `tfsdk:"id"` - Destination types.String `tfsdk:"destination"` - RoutingInstance types.String `tfsdk:"routing_instance"` - ASPathAggregatorAddress types.String `tfsdk:"as_path_aggregator_address"` - ASPathAggregatorASNumber types.String `tfsdk:"as_path_aggregator_as_number"` - ASPathOrigin types.String `tfsdk:"as_path_origin"` - ASPathPath types.String `tfsdk:"as_path_path"` - Community types.List `tfsdk:"community"` - Metric types.Int64 `tfsdk:"metric"` - NextHop types.List `tfsdk:"next_hop"` - NextTable types.String `tfsdk:"next_table"` - Preference types.Int64 `tfsdk:"preference"` QualifiedNextHop types.List `tfsdk:"qualified_next_hop"` } diff --git a/internal/providerfwk/resource_switch_options.go b/internal/providerfwk/resource_switch_options.go index 566ba251..8d7c3ea3 100644 --- a/internal/providerfwk/resource_switch_options.go +++ b/internal/providerfwk/resource_switch_options.go @@ -108,8 +108,8 @@ func (rsc *switchOptions) Schema( } type switchOptionsData struct { - CleanOnDestroy types.Bool `tfsdk:"clean_on_destroy"` ID types.String `tfsdk:"id"` + CleanOnDestroy types.Bool `tfsdk:"clean_on_destroy"` ServiceID types.Int64 `tfsdk:"service_id"` VTEPSourceInterface types.String `tfsdk:"vtep_source_interface"` } diff --git a/internal/providerfwk/resource_system.go b/internal/providerfwk/resource_system.go index 4824b664..152ed146 100644 --- a/internal/providerfwk/resource_system.go +++ b/internal/providerfwk/resource_system.go @@ -1776,32 +1776,32 @@ func (rsc *system) Schema( //nolint:lll type systemData struct { + ID types.String `tfsdk:"id"` + AuthenticationOrder []types.String `tfsdk:"authentication_order"` AutoSnapshot types.Bool `tfsdk:"auto_snapshot"` DefaultAddressSelection types.Bool `tfsdk:"default_address_selection"` + DomainName types.String `tfsdk:"domain_name"` + HostName types.String `tfsdk:"host_name"` + MaxConfigurationRollbacks types.Int64 `tfsdk:"max_configuration_rollbacks"` + MaxConfigurationsOnFlash types.Int64 `tfsdk:"max_configurations_on_flash"` + NameServer []types.String `tfsdk:"name_server"` NoMulticastEcho types.Bool `tfsdk:"no_multicast_echo"` NoPingRecordRoute types.Bool `tfsdk:"no_ping_record_route"` NoPingTimestamp types.Bool `tfsdk:"no_ping_time_stamp"` NoRedirects types.Bool `tfsdk:"no_redirects"` NoRedirectsIPv6 types.Bool `tfsdk:"no_redirects_ipv6"` + RadiusOptionsAttributesNasID types.String `tfsdk:"radius_options_attributes_nas_id"` + RadiusOptionsAttributesNasIpaddress types.String `tfsdk:"radius_options_attributes_nas_ipaddress"` RadiusOptionsEnhancedAccounting types.Bool `tfsdk:"radius_options_enhanced_accounting"` RadiusOptionsPasswordProtocolMschapv2 types.Bool `tfsdk:"radius_options_password_protocol_mschapv2"` + TacplusOptionsAuthorizationTimeInterval types.Int64 `tfsdk:"tacplus_options_authorization_time_interval"` TacplusOptionsEnhancedAccounting types.Bool `tfsdk:"tacplus_options_enhanced_accounting"` TacplusOptionsExcludeCmdAttribute types.Bool `tfsdk:"tacplus_options_exclude_cmd_attribute"` TacplusOptionsNoCmdAttributeValue types.Bool `tfsdk:"tacplus_options_no_cmd_attribute_value"` + TacplusOptionsServiceName types.String `tfsdk:"tacplus_options_service_name"` TacplusOptionsStrictAuthorization types.Bool `tfsdk:"tacplus_options_strict_authorization"` TacplusOptionsNoStrictAuthorization types.Bool `tfsdk:"tacplus_options_no_strict_authorization"` TacplusOptionsTimestampAndTimezone types.Bool `tfsdk:"tacplus_options_timestamp_and_timezone"` - ID types.String `tfsdk:"id"` - AuthenticationOrder []types.String `tfsdk:"authentication_order"` - DomainName types.String `tfsdk:"domain_name"` - HostName types.String `tfsdk:"host_name"` - MaxConfigurationRollbacks types.Int64 `tfsdk:"max_configuration_rollbacks"` - MaxConfigurationsOnFlash types.Int64 `tfsdk:"max_configurations_on_flash"` - NameServer []types.String `tfsdk:"name_server"` - RadiusOptionsAttributesNasID types.String `tfsdk:"radius_options_attributes_nas_id"` - RadiusOptionsAttributesNasIpaddress types.String `tfsdk:"radius_options_attributes_nas_ipaddress"` - TacplusOptionsAuthorizationTimeInterval types.Int64 `tfsdk:"tacplus_options_authorization_time_interval"` - TacplusOptionsServiceName types.String `tfsdk:"tacplus_options_service_name"` TimeZone types.String `tfsdk:"time_zone"` TracingDestOverrideSyslogHost types.String `tfsdk:"tracing_dest_override_syslog_host"` Accounting *systemBlockAccounting `tfsdk:"accounting"` @@ -1819,32 +1819,32 @@ type systemData struct { //nolint:lll type systemConfig struct { + ID types.String `tfsdk:"id"` + AuthenticationOrder types.List `tfsdk:"authentication_order"` AutoSnapshot types.Bool `tfsdk:"auto_snapshot"` DefaultAddressSelection types.Bool `tfsdk:"default_address_selection"` + DomainName types.String `tfsdk:"domain_name"` + HostName types.String `tfsdk:"host_name"` + MaxConfigurationRollbacks types.Int64 `tfsdk:"max_configuration_rollbacks"` + MaxConfigurationsOnFlash types.Int64 `tfsdk:"max_configurations_on_flash"` + NameServer types.List `tfsdk:"name_server"` NoMulticastEcho types.Bool `tfsdk:"no_multicast_echo"` NoPingRecordRoute types.Bool `tfsdk:"no_ping_record_route"` NoPingTimestamp types.Bool `tfsdk:"no_ping_time_stamp"` NoRedirects types.Bool `tfsdk:"no_redirects"` NoRedirectsIPv6 types.Bool `tfsdk:"no_redirects_ipv6"` + RadiusOptionsAttributesNasID types.String `tfsdk:"radius_options_attributes_nas_id"` + RadiusOptionsAttributesNasIpaddress types.String `tfsdk:"radius_options_attributes_nas_ipaddress"` RadiusOptionsEnhancedAccounting types.Bool `tfsdk:"radius_options_enhanced_accounting"` RadiusOptionsPasswordProtocolMschapv2 types.Bool `tfsdk:"radius_options_password_protocol_mschapv2"` + TacplusOptionsAuthorizationTimeInterval types.Int64 `tfsdk:"tacplus_options_authorization_time_interval"` TacplusOptionsEnhancedAccounting types.Bool `tfsdk:"tacplus_options_enhanced_accounting"` TacplusOptionsExcludeCmdAttribute types.Bool `tfsdk:"tacplus_options_exclude_cmd_attribute"` TacplusOptionsNoCmdAttributeValue types.Bool `tfsdk:"tacplus_options_no_cmd_attribute_value"` + TacplusOptionsServiceName types.String `tfsdk:"tacplus_options_service_name"` TacplusOptionsStrictAuthorization types.Bool `tfsdk:"tacplus_options_strict_authorization"` TacplusOptionsNoStrictAuthorization types.Bool `tfsdk:"tacplus_options_no_strict_authorization"` TacplusOptionsTimestampAndTimezone types.Bool `tfsdk:"tacplus_options_timestamp_and_timezone"` - ID types.String `tfsdk:"id"` - AuthenticationOrder types.List `tfsdk:"authentication_order"` - DomainName types.String `tfsdk:"domain_name"` - HostName types.String `tfsdk:"host_name"` - MaxConfigurationRollbacks types.Int64 `tfsdk:"max_configuration_rollbacks"` - MaxConfigurationsOnFlash types.Int64 `tfsdk:"max_configurations_on_flash"` - NameServer types.List `tfsdk:"name_server"` - RadiusOptionsAttributesNasID types.String `tfsdk:"radius_options_attributes_nas_id"` - RadiusOptionsAttributesNasIpaddress types.String `tfsdk:"radius_options_attributes_nas_ipaddress"` - TacplusOptionsAuthorizationTimeInterval types.Int64 `tfsdk:"tacplus_options_authorization_time_interval"` - TacplusOptionsServiceName types.String `tfsdk:"tacplus_options_service_name"` TimeZone types.String `tfsdk:"time_zone"` TracingDestOverrideSyslogHost types.String `tfsdk:"tracing_dest_override_syslog_host"` Accounting *systemBlockAccountingConfig `tfsdk:"accounting"` @@ -1861,19 +1861,19 @@ type systemConfig struct { } type systemBlockAccounting struct { + Events []types.String `tfsdk:"events"` DestinationRadius types.Bool `tfsdk:"destination_radius"` DestinationTacplus types.Bool `tfsdk:"destination_tacplus"` EnhancedAvsMax types.Int64 `tfsdk:"enhanced_avs_max"` - Events []types.String `tfsdk:"events"` DestinationRadiusServer []systemBlockAccountingBlockDestinationRadiusServer `tfsdk:"destination_radius_server"` DestinationTacplusServer []systemBlockAccountingBlockDestinationTacplusServer `tfsdk:"destination_tacplus_server"` } type systemBlockAccountingConfig struct { + Events types.Set `tfsdk:"events"` DestinationRadius types.Bool `tfsdk:"destination_radius"` DestinationTacplus types.Bool `tfsdk:"destination_tacplus"` EnhancedAvsMax types.Int64 `tfsdk:"enhanced_avs_max"` - Events types.Set `tfsdk:"events"` DestinationRadiusServer types.List `tfsdk:"destination_radius_server"` DestinationTacplusServer types.List `tfsdk:"destination_tacplus_server"` } @@ -1896,24 +1896,24 @@ type systemBlockAccountingBlockDestinationRadiusServer struct { } type systemBlockAccountingBlockDestinationTacplusServer struct { - SingleConnection types.Bool `tfsdk:"single_connection"` Address types.String `tfsdk:"address"` Port types.Int64 `tfsdk:"port"` RoutingInstance types.String `tfsdk:"routing_instance"` Secret types.String `tfsdk:"secret"` + SingleConnection types.Bool `tfsdk:"single_connection"` SourceAddress types.String `tfsdk:"source_address"` Timeout types.Int64 `tfsdk:"timeout"` } type systemBlockArchivalConfiguration struct { - TransferOnCommit types.Bool `tfsdk:"transfer_on_commit"` TransferInterval types.Int64 `tfsdk:"transfer_interval"` + TransferOnCommit types.Bool `tfsdk:"transfer_on_commit"` ArchiveSite []systemBlockArchivalConfigurationBlockArchiveSite `tfsdk:"archive_site"` } type systemBlockArchivalConfigurationConfig struct { - TransferOnCommit types.Bool `tfsdk:"transfer_on_commit"` TransferInterval types.Int64 `tfsdk:"transfer_interval"` + TransferOnCommit types.Bool `tfsdk:"transfer_on_commit"` ArchiveSite types.List `tfsdk:"archive_site"` } @@ -1938,21 +1938,21 @@ type systemBlockInternetOptions struct { NoGrePathMtuDiscovery types.Bool `tfsdk:"no_gre_path_mtu_discovery"` IpipPathMtuDiscovery types.Bool `tfsdk:"ipip_path_mtu_discovery"` NoIpipPathMtuDiscovery types.Bool `tfsdk:"no_ipip_path_mtu_discovery"` + IPv6DuplicateAddrDetectionTransmits types.Int64 `tfsdk:"ipv6_duplicate_addr_detection_transmits"` IPv6PathMtuDiscovery types.Bool `tfsdk:"ipv6_path_mtu_discovery"` NoIPv6PathMtuDiscovery types.Bool `tfsdk:"no_ipv6_path_mtu_discovery"` + IPv6PathMtuDiscoveryTimeout types.Int64 `tfsdk:"ipv6_path_mtu_discovery_timeout"` IPv6RejectZeroHopLimit types.Bool `tfsdk:"ipv6_reject_zero_hop_limit"` NoIPv6RejectZeroHopLimit types.Bool `tfsdk:"no_ipv6_reject_zero_hop_limit"` + NoTCPReset types.String `tfsdk:"no_tcp_reset"` NoTCPRFC1323 types.Bool `tfsdk:"no_tcp_rfc1323"` NoTCPRFC1323Paws types.Bool `tfsdk:"no_tcp_rfc1323_paws"` PathMtuDiscovery types.Bool `tfsdk:"path_mtu_discovery"` NoPathMtuDiscovery types.Bool `tfsdk:"no_path_mtu_discovery"` + SourcePortUpperLimit types.Int64 `tfsdk:"source_port_upper_limit"` SourceQuench types.Bool `tfsdk:"source_quench"` NoSourceQuench types.Bool `tfsdk:"no_source_quench"` TCPDropSynfinSet types.Bool `tfsdk:"tcp_drop_synfin_set"` - IPv6DuplicateAddrDetectionTransmits types.Int64 `tfsdk:"ipv6_duplicate_addr_detection_transmits"` - IPv6PathMtuDiscoveryTimeout types.Int64 `tfsdk:"ipv6_path_mtu_discovery_timeout"` - NoTCPReset types.String `tfsdk:"no_tcp_reset"` - SourcePortUpperLimit types.Int64 `tfsdk:"source_port_upper_limit"` TCPMss types.Int64 `tfsdk:"tcp_mss"` IcmpV4RateLimit *systemBlockInternetOptionsBlockIcmpRateLimit `tfsdk:"icmpv4_rate_limit"` IcmpV6RateLimit *systemBlockInternetOptionsBlockIcmpRateLimit `tfsdk:"icmpv6_rate_limit"` @@ -2046,10 +2046,10 @@ func (block *systemBlockLoginBlockRetryOptions) isEmpty() bool { } type systemBlockNtp struct { - BroadcastClient types.Bool `tfsdk:"broadcast_client"` - MulticastClient types.Bool `tfsdk:"multicast_client"` BootServer types.String `tfsdk:"boot_server"` + BroadcastClient types.Bool `tfsdk:"broadcast_client"` IntervalRange types.Int64 `tfsdk:"interval_range"` + MulticastClient types.Bool `tfsdk:"multicast_client"` MulticastClientAddress types.String `tfsdk:"multicast_client_address"` ThresholdAction types.String `tfsdk:"threshold_action"` ThresholdValue types.Int64 `tfsdk:"threshold_value"` @@ -2060,15 +2060,15 @@ func (block *systemBlockNtp) isEmpty() bool { } type systemBlockPorts struct { + AuxiliaryAuthenticationOrder []types.String `tfsdk:"auxiliary_authentication_order"` AuxiliaryDisable types.Bool `tfsdk:"auxiliary_disable"` AuxiliaryInsecure types.Bool `tfsdk:"auxiliary_insecure"` AuxiliaryLogoutOnDisconnect types.Bool `tfsdk:"auxiliary_logout_on_disconnect"` + AuxiliaryType types.String `tfsdk:"auxiliary_type"` + ConsoleAuthenticationOrder []types.String `tfsdk:"console_authentication_order"` ConsoleDisable types.Bool `tfsdk:"console_disable"` ConsoleInsecure types.Bool `tfsdk:"console_insecure"` ConsoleLogoutOnDisconnect types.Bool `tfsdk:"console_logout_on_disconnect"` - AuxiliaryAuthenticationOrder []types.String `tfsdk:"auxiliary_authentication_order"` - AuxiliaryType types.String `tfsdk:"auxiliary_type"` - ConsoleAuthenticationOrder []types.String `tfsdk:"console_authentication_order"` ConsoleType types.String `tfsdk:"console_type"` } @@ -2077,15 +2077,15 @@ func (block *systemBlockPorts) isEmpty() bool { } type systemBlockPortsConfig struct { + AuxiliaryAuthenticationOrder types.List `tfsdk:"auxiliary_authentication_order"` AuxiliaryDisable types.Bool `tfsdk:"auxiliary_disable"` AuxiliaryInsecure types.Bool `tfsdk:"auxiliary_insecure"` AuxiliaryLogoutOnDisconnect types.Bool `tfsdk:"auxiliary_logout_on_disconnect"` + AuxiliaryType types.String `tfsdk:"auxiliary_type"` + ConsoleAuthenticationOrder types.List `tfsdk:"console_authentication_order"` ConsoleDisable types.Bool `tfsdk:"console_disable"` ConsoleInsecure types.Bool `tfsdk:"console_insecure"` ConsoleLogoutOnDisconnect types.Bool `tfsdk:"console_logout_on_disconnect"` - AuxiliaryAuthenticationOrder types.List `tfsdk:"auxiliary_authentication_order"` - AuxiliaryType types.String `tfsdk:"auxiliary_type"` - ConsoleAuthenticationOrder types.List `tfsdk:"console_authentication_order"` ConsoleType types.String `tfsdk:"console_type"` } @@ -2135,15 +2135,15 @@ func (block *systemBlockServicesBlockNetconfSSH) isEmpty() bool { } type systemBlockServicesBlockNetconfTraceoptions struct { - FileWorldReadable types.Bool `tfsdk:"file_world_readable"` - FileNoWorldReadable types.Bool `tfsdk:"file_no_world_readable"` - NoRemoteTrace types.Bool `tfsdk:"no_remote_trace"` - OnDemand types.Bool `tfsdk:"on_demand"` FileName types.String `tfsdk:"file_name"` FileFiles types.Int64 `tfsdk:"file_files"` FileMatch types.String `tfsdk:"file_match"` FileSize types.Int64 `tfsdk:"file_size"` + FileWorldReadable types.Bool `tfsdk:"file_world_readable"` + FileNoWorldReadable types.Bool `tfsdk:"file_no_world_readable"` Flag []types.String `tfsdk:"flag"` + NoRemoteTrace types.Bool `tfsdk:"no_remote_trace"` + OnDemand types.Bool `tfsdk:"on_demand"` } func (block *systemBlockServicesBlockNetconfTraceoptions) isEmpty() bool { @@ -2151,15 +2151,15 @@ func (block *systemBlockServicesBlockNetconfTraceoptions) isEmpty() bool { } type systemBlockServicesBlockNetconfTraceoptionsConfig struct { - FileWorldReadable types.Bool `tfsdk:"file_world_readable"` - FileNoWorldReadable types.Bool `tfsdk:"file_no_world_readable"` - NoRemoteTrace types.Bool `tfsdk:"no_remote_trace"` - OnDemand types.Bool `tfsdk:"on_demand"` FileName types.String `tfsdk:"file_name"` FileFiles types.Int64 `tfsdk:"file_files"` FileMatch types.String `tfsdk:"file_match"` FileSize types.Int64 `tfsdk:"file_size"` + FileWorldReadable types.Bool `tfsdk:"file_world_readable"` + FileNoWorldReadable types.Bool `tfsdk:"file_no_world_readable"` Flag types.Set `tfsdk:"flag"` + NoRemoteTrace types.Bool `tfsdk:"no_remote_trace"` + OnDemand types.Bool `tfsdk:"on_demand"` } func (block *systemBlockServicesBlockNetconfTraceoptionsConfig) isEmpty() bool { @@ -2167,11 +2167,6 @@ func (block *systemBlockServicesBlockNetconfTraceoptionsConfig) isEmpty() bool { } type systemBlockServicesBlockSSH struct { - LogKeyChanges types.Bool `tfsdk:"log_key_changes"` - NoPasswords types.Bool `tfsdk:"no_passwords"` - NoPublicKeys types.Bool `tfsdk:"no_public_keys"` - TCPForwarding types.Bool `tfsdk:"tcp_forwarding"` - NoTCPForwarding types.Bool `tfsdk:"no_tcp_forwarding"` AuthenticationOrder []types.String `tfsdk:"authentication_order"` Ciphers []types.String `tfsdk:"ciphers"` ClientAliveCountMax types.Int64 `tfsdk:"client_alive_count_max"` @@ -2180,13 +2175,18 @@ type systemBlockServicesBlockSSH struct { FingerprintHash types.String `tfsdk:"fingerprint_hash"` HostkeyAlgorithm []types.String `tfsdk:"hostkey_algorithm"` KeyExchange []types.String `tfsdk:"key_exchange"` + LogKeyChanges types.Bool `tfsdk:"log_key_changes"` Macs []types.String `tfsdk:"macs"` MaxPreAuthenticationPackets types.Int64 `tfsdk:"max_pre_authentication_packets"` MaxSessionsPerConnection types.Int64 `tfsdk:"max_sessions_per_connection"` + NoPasswords types.Bool `tfsdk:"no_passwords"` + NoPublicKeys types.Bool `tfsdk:"no_public_keys"` Port types.Int64 `tfsdk:"port"` ProtocolVersion []types.String `tfsdk:"protocol_version"` RateLimit types.Int64 `tfsdk:"rate_limit"` RootLogin types.String `tfsdk:"root_login"` + TCPForwarding types.Bool `tfsdk:"tcp_forwarding"` + NoTCPForwarding types.Bool `tfsdk:"no_tcp_forwarding"` } func (block *systemBlockServicesBlockSSH) isEmpty() bool { @@ -2194,11 +2194,6 @@ func (block *systemBlockServicesBlockSSH) isEmpty() bool { } type systemBlockServicesBlockSSHConfig struct { - LogKeyChanges types.Bool `tfsdk:"log_key_changes"` - NoPasswords types.Bool `tfsdk:"no_passwords"` - NoPublicKeys types.Bool `tfsdk:"no_public_keys"` - TCPForwarding types.Bool `tfsdk:"tcp_forwarding"` - NoTCPForwarding types.Bool `tfsdk:"no_tcp_forwarding"` AuthenticationOrder types.List `tfsdk:"authentication_order"` Ciphers types.Set `tfsdk:"ciphers"` ClientAliveCountMax types.Int64 `tfsdk:"client_alive_count_max"` @@ -2207,13 +2202,18 @@ type systemBlockServicesBlockSSHConfig struct { FingerprintHash types.String `tfsdk:"fingerprint_hash"` HostkeyAlgorithm types.Set `tfsdk:"hostkey_algorithm"` KeyExchange types.Set `tfsdk:"key_exchange"` + LogKeyChanges types.Bool `tfsdk:"log_key_changes"` Macs types.Set `tfsdk:"macs"` MaxPreAuthenticationPackets types.Int64 `tfsdk:"max_pre_authentication_packets"` MaxSessionsPerConnection types.Int64 `tfsdk:"max_sessions_per_connection"` + NoPasswords types.Bool `tfsdk:"no_passwords"` + NoPublicKeys types.Bool `tfsdk:"no_public_keys"` Port types.Int64 `tfsdk:"port"` ProtocolVersion types.Set `tfsdk:"protocol_version"` RateLimit types.Int64 `tfsdk:"rate_limit"` RootLogin types.String `tfsdk:"root_login"` + TCPForwarding types.Bool `tfsdk:"tcp_forwarding"` + NoTCPForwarding types.Bool `tfsdk:"no_tcp_forwarding"` } func (block *systemBlockServicesBlockSSHConfig) isEmpty() bool { @@ -2231,26 +2231,26 @@ type systemBlockServicesBlockWebManagementHTTPConfig struct { } type systemBlockServicesBlockWebManagementHTTPS struct { - SystemGeneratedCertificate types.Bool `tfsdk:"system_generated_certificate"` Interface []types.String `tfsdk:"interface"` LocalCertificate types.String `tfsdk:"local_certificate"` PkiLocalCertificate types.String `tfsdk:"pki_local_certificate"` Port types.Int64 `tfsdk:"port"` + SystemGeneratedCertificate types.Bool `tfsdk:"system_generated_certificate"` } type systemBlockServicesBlockWebManagementHTTPSConfig struct { - SystemGeneratedCertificate types.Bool `tfsdk:"system_generated_certificate"` Interface types.Set `tfsdk:"interface"` LocalCertificate types.String `tfsdk:"local_certificate"` PkiLocalCertificate types.String `tfsdk:"pki_local_certificate"` Port types.Int64 `tfsdk:"port"` + SystemGeneratedCertificate types.Bool `tfsdk:"system_generated_certificate"` } type systemBlockSyslog struct { - TimeFormatMillisecond types.Bool `tfsdk:"time_format_millisecond"` - TimeFormatYear types.Bool `tfsdk:"time_format_year"` LogRotateFrequency types.Int64 `tfsdk:"log_rotate_frequency"` SourceAddress types.String `tfsdk:"source_address"` + TimeFormatMillisecond types.Bool `tfsdk:"time_format_millisecond"` + TimeFormatYear types.Bool `tfsdk:"time_format_year"` Archive *systemBlockSyslogBlockArchive `tfsdk:"archive"` Console *systemBlockSyslogBlockConsole `tfsdk:"console"` } @@ -2262,10 +2262,10 @@ func (block *systemBlockSyslog) isEmpty() bool { type systemBlockSyslogBlockArchive struct { BinaryData types.Bool `tfsdk:"binary_data"` NoBinaryData types.Bool `tfsdk:"no_binary_data"` - WorldReadable types.Bool `tfsdk:"world_readable"` - NoWorldReadable types.Bool `tfsdk:"no_world_readable"` Files types.Int64 `tfsdk:"files"` Size types.Int64 `tfsdk:"size"` + WorldReadable types.Bool `tfsdk:"world_readable"` + NoWorldReadable types.Bool `tfsdk:"no_world_readable"` } type systemBlockSyslogBlockConsole struct { diff --git a/internal/providerfwk/resource_system_syslog_file.go b/internal/providerfwk/resource_system_syslog_file.go index 3bfb4c6c..8ef94a8a 100644 --- a/internal/providerfwk/resource_system_syslog_file.go +++ b/internal/providerfwk/resource_system_syslog_file.go @@ -366,10 +366,10 @@ func (rsc *systemSyslogFile) Schema( } type systemSyslogFileData struct { - AllowDuplicates types.Bool `tfsdk:"allow_duplicates"` - ExplicitPriority types.Bool `tfsdk:"explicit_priority"` ID types.String `tfsdk:"id"` Filename types.String `tfsdk:"filename"` + AllowDuplicates types.Bool `tfsdk:"allow_duplicates"` + ExplicitPriority types.Bool `tfsdk:"explicit_priority"` Match types.String `tfsdk:"match"` MatchStrings []types.String `tfsdk:"match_strings"` AnySeverity types.String `tfsdk:"any_severity"` @@ -392,10 +392,10 @@ type systemSyslogFileData struct { } type systemSyslogFileConfig struct { - AllowDuplicates types.Bool `tfsdk:"allow_duplicates"` - ExplicitPriority types.Bool `tfsdk:"explicit_priority"` ID types.String `tfsdk:"id"` Filename types.String `tfsdk:"filename"` + AllowDuplicates types.Bool `tfsdk:"allow_duplicates"` + ExplicitPriority types.Bool `tfsdk:"explicit_priority"` Match types.String `tfsdk:"match"` MatchStrings types.List `tfsdk:"match_strings"` AnySeverity types.String `tfsdk:"any_severity"` @@ -420,24 +420,24 @@ type systemSyslogFileConfig struct { type systemSyslogFileBlockArchive struct { BinaryData types.Bool `tfsdk:"binary_data"` NoBinaryData types.Bool `tfsdk:"no_binary_data"` - WorldReadable types.Bool `tfsdk:"world_readable"` - NoWorldReadable types.Bool `tfsdk:"no_world_readable"` Files types.Int64 `tfsdk:"files"` Size types.Int64 `tfsdk:"size"` StartTime types.String `tfsdk:"start_time"` TransferInterval types.Int64 `tfsdk:"transfer_interval"` + WorldReadable types.Bool `tfsdk:"world_readable"` + NoWorldReadable types.Bool `tfsdk:"no_world_readable"` Sites []systemSyslogFileBlockArchiveBlockSites `tfsdk:"sites"` } type systemSyslogFileBlockArchiveConfig struct { BinaryData types.Bool `tfsdk:"binary_data"` NoBinaryData types.Bool `tfsdk:"no_binary_data"` - WorldReadable types.Bool `tfsdk:"world_readable"` - NoWorldReadable types.Bool `tfsdk:"no_world_readable"` Files types.Int64 `tfsdk:"files"` Size types.Int64 `tfsdk:"size"` StartTime types.String `tfsdk:"start_time"` TransferInterval types.Int64 `tfsdk:"transfer_interval"` + WorldReadable types.Bool `tfsdk:"world_readable"` + NoWorldReadable types.Bool `tfsdk:"no_world_readable"` Sites types.List `tfsdk:"sites"` } diff --git a/internal/providerfwk/resource_system_syslog_host.go b/internal/providerfwk/resource_system_syslog_host.go index 7755d654..8ee648fc 100644 --- a/internal/providerfwk/resource_system_syslog_host.go +++ b/internal/providerfwk/resource_system_syslog_host.go @@ -296,11 +296,11 @@ func (rsc *systemSyslogHost) Schema( } type systemSyslogHostData struct { + ID types.String `tfsdk:"id"` + Host types.String `tfsdk:"host"` AllowDuplicates types.Bool `tfsdk:"allow_duplicates"` ExcludeHostname types.Bool `tfsdk:"exclude_hostname"` ExplicitPriority types.Bool `tfsdk:"explicit_priority"` - ID types.String `tfsdk:"id"` - Host types.String `tfsdk:"host"` FacilityOverride types.String `tfsdk:"facility_override"` LogPrefix types.String `tfsdk:"log_prefix"` Match types.String `tfsdk:"match"` diff --git a/internal/providerfwk/resource_system_syslog_user.go b/internal/providerfwk/resource_system_syslog_user.go index 81cc68a8..30f6fc57 100644 --- a/internal/providerfwk/resource_system_syslog_user.go +++ b/internal/providerfwk/resource_system_syslog_user.go @@ -233,9 +233,9 @@ func (rsc *systemSyslogUser) Schema( } type systemSyslogUserData struct { - AllowDuplicates types.Bool `tfsdk:"allow_duplicates"` ID types.String `tfsdk:"id"` Username types.String `tfsdk:"username"` + AllowDuplicates types.Bool `tfsdk:"allow_duplicates"` Match types.String `tfsdk:"match"` MatchStrings []types.String `tfsdk:"match_strings"` AnySeverity types.String `tfsdk:"any_severity"` diff --git a/internal/providerfwk/resource_system_tacplus_server.go b/internal/providerfwk/resource_system_tacplus_server.go index d4ff972d..3b9d01f4 100644 --- a/internal/providerfwk/resource_system_tacplus_server.go +++ b/internal/providerfwk/resource_system_tacplus_server.go @@ -144,12 +144,12 @@ func (rsc *systemTacplusServer) Schema( } type systemTacplusServerData struct { - SingleConnection types.Bool `tfsdk:"single_connection"` ID types.String `tfsdk:"id"` Address types.String `tfsdk:"address"` Port types.Int64 `tfsdk:"port"` RoutingInstance types.String `tfsdk:"routing_instance"` Secret types.String `tfsdk:"secret"` + SingleConnection types.Bool `tfsdk:"single_connection"` SourceAddress types.String `tfsdk:"source_address"` Timeout types.Int64 `tfsdk:"timeout"` } diff --git a/internal/providerfwk/resource_virtual_chassis.go b/internal/providerfwk/resource_virtual_chassis.go index 1ac7828e..d0213376 100644 --- a/internal/providerfwk/resource_virtual_chassis.go +++ b/internal/providerfwk/resource_virtual_chassis.go @@ -317,30 +317,30 @@ func (rsc *virtualChassis) Schema( } type virtualChassisData struct { + ID types.String `tfsdk:"id"` AutoSWUpdate types.Bool `tfsdk:"auto_sw_update"` + AutoSWUpdatePackageName types.String `tfsdk:"auto_sw_update_package_name"` GracefulRestartDisable types.Bool `tfsdk:"graceful_restart_disable"` + Identifier types.String `tfsdk:"identifier"` + MacPersistenceTimer types.String `tfsdk:"mac_persistence_timer"` NoSplitDetection types.Bool `tfsdk:"no_split_detection"` Preprovisioned types.Bool `tfsdk:"preprovisioned"` VcpNoHoldTime types.Bool `tfsdk:"vcp_no_hold_time"` - ID types.String `tfsdk:"id"` - AutoSWUpdatePackageName types.String `tfsdk:"auto_sw_update_package_name"` - Identifier types.String `tfsdk:"identifier"` - MacPersistenceTimer types.String `tfsdk:"mac_persistence_timer"` Alias []virtualChassisBlockAlias `tfsdk:"alias"` Member []virtualChassisBlockMember `tfsdk:"member"` Traceoptions *virtualChassisBlockTraceoptions `tfsdk:"traceoptions"` } type virtualChassisConfig struct { + ID types.String `tfsdk:"id"` AutoSWUpdate types.Bool `tfsdk:"auto_sw_update"` + AutoSWUpdatePackageName types.String `tfsdk:"auto_sw_update_package_name"` GracefulRestartDisable types.Bool `tfsdk:"graceful_restart_disable"` + Identifier types.String `tfsdk:"identifier"` + MacPersistenceTimer types.String `tfsdk:"mac_persistence_timer"` NoSplitDetection types.Bool `tfsdk:"no_split_detection"` Preprovisioned types.Bool `tfsdk:"preprovisioned"` VcpNoHoldTime types.Bool `tfsdk:"vcp_no_hold_time"` - ID types.String `tfsdk:"id"` - AutoSWUpdatePackageName types.String `tfsdk:"auto_sw_update_package_name"` - Identifier types.String `tfsdk:"identifier"` - MacPersistenceTimer types.String `tfsdk:"mac_persistence_timer"` Alias types.Set `tfsdk:"alias"` Member types.List `tfsdk:"member"` Traceoptions *virtualChassisBlockTraceoptionsConfig `tfsdk:"traceoptions"` @@ -352,10 +352,10 @@ type virtualChassisBlockAlias struct { } type virtualChassisBlockMember struct { - NoManagementVlan types.Bool `tfsdk:"no_management_vlan"` ID types.Int64 `tfsdk:"id"` Location types.String `tfsdk:"location"` MastershipPriority types.Int64 `tfsdk:"mastership_priority"` + NoManagementVlan types.Bool `tfsdk:"no_management_vlan"` Role types.String `tfsdk:"role"` SerialNumber types.String `tfsdk:"serial_number"` } @@ -383,13 +383,13 @@ func (block *virtualChassisBlockTraceoptionsConfig) isEmpty() bool { } type virtualChassisBlockTraceoptionsBlockFile struct { + Name types.String `tfsdk:"name"` + Files types.Int64 `tfsdk:"files"` NoStamp types.Bool `tfsdk:"no_stamp"` Replace types.Bool `tfsdk:"replace"` + Size types.Int64 `tfsdk:"size"` WorldReadable types.Bool `tfsdk:"world_readable"` NoWorldReadable types.Bool `tfsdk:"no_world_readable"` - Name types.String `tfsdk:"name"` - Files types.Int64 `tfsdk:"files"` - Size types.Int64 `tfsdk:"size"` } func (rsc *virtualChassis) ValidateConfig( diff --git a/internal/providerfwk/resourcedata_bgp.go b/internal/providerfwk/resourcedata_bgp.go index 4763ba1d..28143d8e 100644 --- a/internal/providerfwk/resourcedata_bgp.go +++ b/internal/providerfwk/resourcedata_bgp.go @@ -14,9 +14,9 @@ import ( ) type bgpBlockBfdLivenessDetection struct { - AuthenticationLooseCheck types.Bool `tfsdk:"authentication_loose_check"` AuthenticationAlgorithm types.String `tfsdk:"authentication_algorithm"` AuthenticationKeyChain types.String `tfsdk:"authentication_key_chain"` + AuthenticationLooseCheck types.Bool `tfsdk:"authentication_loose_check"` DetectionTimeThreshold types.Int64 `tfsdk:"detection_time_threshold"` HolddownInterval types.Int64 `tfsdk:"holddown_interval"` MinimumInterval types.Int64 `tfsdk:"minimum_interval"` @@ -33,8 +33,8 @@ func (block *bgpBlockBfdLivenessDetection) isEmpty() bool { } type bgpBlockBgpErrorTolerance struct { - NoMalformedRouteLimit types.Bool `tfsdk:"no_malformed_route_limit"` MalformedRouteLimit types.Int64 `tfsdk:"malformed_route_limit"` + NoMalformedRouteLimit types.Bool `tfsdk:"no_malformed_route_limit"` MalformedUpdateLogInterval types.Int64 `tfsdk:"malformed_update_log_interval"` } @@ -51,10 +51,10 @@ type bgpBlockFamily struct { } type bgpBlockFamilyBlockPrefixLimit struct { - TeardownIdleTimeoutForever types.Bool `tfsdk:"teardown_idle_timeout_forever"` Maximum types.Int64 `tfsdk:"maximum"` Teardown types.Int64 `tfsdk:"teardown"` TeardownIdleTimeout types.Int64 `tfsdk:"teardown_idle_timeout"` + TeardownIdleTimeoutForever types.Bool `tfsdk:"teardown_idle_timeout_forever"` } type bgpBlockGracefulRestart struct { diff --git a/internal/providerfwk/upgradestate_bgp_group.go b/internal/providerfwk/upgradestate_bgp_group.go index 09f2572d..453110eb 100644 --- a/internal/providerfwk/upgradestate_bgp_group.go +++ b/internal/providerfwk/upgradestate_bgp_group.go @@ -299,6 +299,10 @@ func upgradeBgpGroupStateV0toV1( ctx context.Context, req resource.UpgradeStateRequest, resp *resource.UpgradeStateResponse, ) { type modelV0 struct { + ID types.String `tfsdk:"id"` + Name types.String `tfsdk:"name"` + RoutingInstance types.String `tfsdk:"routing_instance"` + Type types.String `tfsdk:"type"` AcceptRemoteNexthop types.Bool `tfsdk:"accept_remote_nexthop"` AdvertiseExternal types.Bool `tfsdk:"advertise_external"` AdvertiseExternalConditional types.Bool `tfsdk:"advertise_external_conditional"` @@ -306,46 +310,42 @@ func upgradeBgpGroupStateV0toV1( AdvertisePeerAS types.Bool `tfsdk:"advertise_peer_as"` NoAdvertisePeerAS types.Bool `tfsdk:"no_advertise_peer_as"` ASOverride types.Bool `tfsdk:"as_override"` - Damping types.Bool `tfsdk:"damping"` - KeepAll types.Bool `tfsdk:"keep_all"` - KeepNone types.Bool `tfsdk:"keep_none"` - LocalASAlias types.Bool `tfsdk:"local_as_alias"` - LocalASNoPrependGlobalAS types.Bool `tfsdk:"local_as_no_prepend_global_as"` - LocalASPrivate types.Bool `tfsdk:"local_as_private"` - LogUpdown types.Bool `tfsdk:"log_updown"` - MetricOutIgp types.Bool `tfsdk:"metric_out_igp"` - MetricOutIgpDelayMedUpdate types.Bool `tfsdk:"metric_out_igp_delay_med_update"` - MetricOutMinimumIgp types.Bool `tfsdk:"metric_out_minimum_igp"` - MtuDiscovery types.Bool `tfsdk:"mtu_discovery"` - Multihop types.Bool `tfsdk:"multihop"` - Passive types.Bool `tfsdk:"passive"` - RemovePrivate types.Bool `tfsdk:"remove_private"` AuthenticationAlgorithm types.String `tfsdk:"authentication_algorithm"` AuthenticationKey types.String `tfsdk:"authentication_key"` AuthenticationKeyChain types.String `tfsdk:"authentication_key_chain"` Cluster types.String `tfsdk:"cluster"` + Damping types.Bool `tfsdk:"damping"` Export []types.String `tfsdk:"export"` HoldTime types.Int64 `tfsdk:"hold_time"` - ID types.String `tfsdk:"id"` Import []types.String `tfsdk:"import"` + KeepAll types.Bool `tfsdk:"keep_all"` + KeepNone types.Bool `tfsdk:"keep_none"` LocalAddress types.String `tfsdk:"local_address"` LocalAS types.String `tfsdk:"local_as"` + LocalASAlias types.Bool `tfsdk:"local_as_alias"` LocalASLoops types.Int64 `tfsdk:"local_as_loops"` + LocalASNoPrependGlobalAS types.Bool `tfsdk:"local_as_no_prepend_global_as"` + LocalASPrivate types.Bool `tfsdk:"local_as_private"` LocalInterface types.String `tfsdk:"local_interface"` LocalPreference types.Int64 `tfsdk:"local_preference"` + LogUpdown types.Bool `tfsdk:"log_updown"` MetricOut types.Int64 `tfsdk:"metric_out"` + MetricOutIgp types.Bool `tfsdk:"metric_out_igp"` + MetricOutIgpDelayMedUpdate types.Bool `tfsdk:"metric_out_igp_delay_med_update"` MetricOutIgpOffset types.Int64 `tfsdk:"metric_out_igp_offset"` + MetricOutMinimumIgp types.Bool `tfsdk:"metric_out_minimum_igp"` MetricOutMinimumIgpOffset types.Int64 `tfsdk:"metric_out_minimum_igp_offset"` - Name types.String `tfsdk:"name"` + MtuDiscovery types.Bool `tfsdk:"mtu_discovery"` + Multihop types.Bool `tfsdk:"multihop"` OutDelay types.Int64 `tfsdk:"out_delay"` + Passive types.Bool `tfsdk:"passive"` PeerAS types.String `tfsdk:"peer_as"` Preference types.Int64 `tfsdk:"preference"` - RoutingInstance types.String `tfsdk:"routing_instance"` - Type types.String `tfsdk:"type"` + RemovePrivate types.Bool `tfsdk:"remove_private"` BfdLivenessDetection []struct { - AuthenticationLooseCheck types.Bool `tfsdk:"authentication_loose_check"` AuthenticationAlgorithm types.String `tfsdk:"authentication_algorithm"` AuthenticationKeyChain types.String `tfsdk:"authentication_key_chain"` + AuthenticationLooseCheck types.Bool `tfsdk:"authentication_loose_check"` DetectionTimeThreshold types.Int64 `tfsdk:"detection_time_threshold"` HolddownInterval types.Int64 `tfsdk:"holddown_interval"` MinimumInterval types.Int64 `tfsdk:"minimum_interval"` diff --git a/internal/providerfwk/upgradestate_bgp_neighbor.go b/internal/providerfwk/upgradestate_bgp_neighbor.go index a3ad0691..0ac6791d 100644 --- a/internal/providerfwk/upgradestate_bgp_neighbor.go +++ b/internal/providerfwk/upgradestate_bgp_neighbor.go @@ -298,6 +298,10 @@ func upgradeBgpNeighborStateV0toV1( ctx context.Context, req resource.UpgradeStateRequest, resp *resource.UpgradeStateResponse, ) { type modelV0 struct { + ID types.String `tfsdk:"id"` + IP types.String `tfsdk:"ip"` + RoutingInstance types.String `tfsdk:"routing_instance"` + Group types.String `tfsdk:"group"` AcceptRemoteNexthop types.Bool `tfsdk:"accept_remote_nexthop"` AdvertiseExternal types.Bool `tfsdk:"advertise_external"` AdvertiseExternalConditional types.Bool `tfsdk:"advertise_external_conditional"` @@ -305,46 +309,42 @@ func upgradeBgpNeighborStateV0toV1( AdvertisePeerAS types.Bool `tfsdk:"advertise_peer_as"` NoAdvertisePeerAS types.Bool `tfsdk:"no_advertise_peer_as"` ASOverride types.Bool `tfsdk:"as_override"` - Damping types.Bool `tfsdk:"damping"` - KeepAll types.Bool `tfsdk:"keep_all"` - KeepNone types.Bool `tfsdk:"keep_none"` - LocalASAlias types.Bool `tfsdk:"local_as_alias"` - LocalASNoPrependGlobalAS types.Bool `tfsdk:"local_as_no_prepend_global_as"` - LocalASPrivate types.Bool `tfsdk:"local_as_private"` - LogUpdown types.Bool `tfsdk:"log_updown"` - MetricOutIgp types.Bool `tfsdk:"metric_out_igp"` - MetricOutIgpDelayMedUpdate types.Bool `tfsdk:"metric_out_igp_delay_med_update"` - MetricOutMinimumIgp types.Bool `tfsdk:"metric_out_minimum_igp"` - MtuDiscovery types.Bool `tfsdk:"mtu_discovery"` - Multihop types.Bool `tfsdk:"multihop"` - Passive types.Bool `tfsdk:"passive"` - RemovePrivate types.Bool `tfsdk:"remove_private"` AuthenticationAlgorithm types.String `tfsdk:"authentication_algorithm"` AuthenticationKey types.String `tfsdk:"authentication_key"` AuthenticationKeyChain types.String `tfsdk:"authentication_key_chain"` Cluster types.String `tfsdk:"cluster"` + Damping types.Bool `tfsdk:"damping"` Export []types.String `tfsdk:"export"` - Group types.String `tfsdk:"group"` HoldTime types.Int64 `tfsdk:"hold_time"` - ID types.String `tfsdk:"id"` Import []types.String `tfsdk:"import"` - IP types.String `tfsdk:"ip"` + KeepAll types.Bool `tfsdk:"keep_all"` + KeepNone types.Bool `tfsdk:"keep_none"` LocalAddress types.String `tfsdk:"local_address"` LocalAS types.String `tfsdk:"local_as"` + LocalASAlias types.Bool `tfsdk:"local_as_alias"` LocalASLoops types.Int64 `tfsdk:"local_as_loops"` + LocalASNoPrependGlobalAS types.Bool `tfsdk:"local_as_no_prepend_global_as"` + LocalASPrivate types.Bool `tfsdk:"local_as_private"` LocalInterface types.String `tfsdk:"local_interface"` LocalPreference types.Int64 `tfsdk:"local_preference"` + LogUpdown types.Bool `tfsdk:"log_updown"` MetricOut types.Int64 `tfsdk:"metric_out"` + MetricOutIgp types.Bool `tfsdk:"metric_out_igp"` + MetricOutIgpDelayMedUpdate types.Bool `tfsdk:"metric_out_igp_delay_med_update"` MetricOutIgpOffset types.Int64 `tfsdk:"metric_out_igp_offset"` + MetricOutMinimumIgp types.Bool `tfsdk:"metric_out_minimum_igp"` MetricOutMinimumIgpOffset types.Int64 `tfsdk:"metric_out_minimum_igp_offset"` + MtuDiscovery types.Bool `tfsdk:"mtu_discovery"` + Multihop types.Bool `tfsdk:"multihop"` OutDelay types.Int64 `tfsdk:"out_delay"` + Passive types.Bool `tfsdk:"passive"` PeerAS types.String `tfsdk:"peer_as"` Preference types.Int64 `tfsdk:"preference"` - RoutingInstance types.String `tfsdk:"routing_instance"` + RemovePrivate types.Bool `tfsdk:"remove_private"` BfdLivenessDetection []struct { - AuthenticationLooseCheck types.Bool `tfsdk:"authentication_loose_check"` AuthenticationAlgorithm types.String `tfsdk:"authentication_algorithm"` AuthenticationKeyChain types.String `tfsdk:"authentication_key_chain"` + AuthenticationLooseCheck types.Bool `tfsdk:"authentication_loose_check"` DetectionTimeThreshold types.Int64 `tfsdk:"detection_time_threshold"` HolddownInterval types.Int64 `tfsdk:"holddown_interval"` MinimumInterval types.Int64 `tfsdk:"minimum_interval"` diff --git a/internal/providerfwk/upgradestate_bridge_domain.go b/internal/providerfwk/upgradestate_bridge_domain.go index bf3b0360..fc7f4d64 100644 --- a/internal/providerfwk/upgradestate_bridge_domain.go +++ b/internal/providerfwk/upgradestate_bridge_domain.go @@ -95,26 +95,26 @@ func upgradeBridgeDomainStateV0toV1( ctx context.Context, req resource.UpgradeStateRequest, resp *resource.UpgradeStateResponse, ) { type modelV0 struct { - DomainTypeBridge types.Bool `tfsdk:"domain_type_bridge"` ID types.String `tfsdk:"id"` Name types.String `tfsdk:"name"` RoutingInstance types.String `tfsdk:"routing_instance"` CommunityVlans []types.String `tfsdk:"community_vlans"` Description types.String `tfsdk:"description"` DomainID types.Int64 `tfsdk:"domain_id"` + DomainTypeBridge types.Bool `tfsdk:"domain_type_bridge"` IsolatedVLAN types.Int64 `tfsdk:"isolated_vlan"` RoutingInterface types.String `tfsdk:"routing_interface"` ServiceID types.Int64 `tfsdk:"service_id"` VLANID types.Int64 `tfsdk:"vlan_id"` VLANIDList []types.String `tfsdk:"vlan_id_list"` VXLAN []struct { + VNI types.Int64 `tfsdk:"vni"` VNIExtendEvpn types.Bool `tfsdk:"vni_extend_evpn"` DecapsulateAcceptInnerVlan types.Bool `tfsdk:"decapsulate_accept_inner_vlan"` EncapsulateInnerVlan types.Bool `tfsdk:"encapsulate_inner_vlan"` IngressNodeReplication types.Bool `tfsdk:"ingress_node_replication"` - OvsdbManaged types.Bool `tfsdk:"ovsdb_managed"` - VNI types.Int64 `tfsdk:"vni"` MulticastGroup types.String `tfsdk:"multicast_group"` + OvsdbManaged types.Bool `tfsdk:"ovsdb_managed"` UnreachableVtepAgingTimer types.Int64 `tfsdk:"unreachable_vtep_aging_timer"` } `tfsdk:"vxlan"` } diff --git a/internal/providerfwk/upgradestate_eventoptions_policy.go b/internal/providerfwk/upgradestate_eventoptions_policy.go index c65a88d3..e970046f 100644 --- a/internal/providerfwk/upgradestate_eventoptions_policy.go +++ b/internal/providerfwk/upgradestate_eventoptions_policy.go @@ -245,16 +245,16 @@ func upgradeEventoptionsPolicyV0toV1( Events []types.String `tfsdk:"events"` Then []struct { Ignore types.Bool `tfsdk:"ignore"` - RaiseTrap types.Bool `tfsdk:"raise_trap"` PriorityOverrideFacility types.String `tfsdk:"priority_override_facility"` PriorityOverrideSeverity types.String `tfsdk:"priority_override_severity"` + RaiseTrap types.Bool `tfsdk:"raise_trap"` ChangeConfiguration []struct { + Commands []types.String `tfsdk:"commands"` CommitOptionsCheck types.Bool `tfsdk:"commit_options_check"` CommitOptionsCheckSynchronize types.Bool `tfsdk:"commit_options_check_synchronize"` CommitOptionsForce types.Bool `tfsdk:"commit_options_force"` - CommitOptionsSynchronize types.Bool `tfsdk:"commit_options_synchronize"` - Commands []types.String `tfsdk:"commands"` CommitOptionsLog types.String `tfsdk:"commit_options_log"` + CommitOptionsSynchronize types.Bool `tfsdk:"commit_options_synchronize"` RetryCount types.Int64 `tfsdk:"retry_count"` RetryInterval types.Int64 `tfsdk:"retry_interval"` Username types.String `tfsdk:"user_name"` diff --git a/internal/providerfwk/upgradestate_evpn.go b/internal/providerfwk/upgradestate_evpn.go index 7c525063..b561be62 100644 --- a/internal/providerfwk/upgradestate_evpn.go +++ b/internal/providerfwk/upgradestate_evpn.go @@ -73,18 +73,18 @@ func upgradeEvpnV0toV1( ctx context.Context, req resource.UpgradeStateRequest, resp *resource.UpgradeStateResponse, ) { type modelV0 struct { - RoutingInstanceEvpn types.Bool `tfsdk:"routing_instance_evpn"` ID types.String `tfsdk:"id"` RoutingInstance types.String `tfsdk:"routing_instance"` Encapsulation types.String `tfsdk:"encapsulation"` DefaultGateway types.String `tfsdk:"default_gateway"` MulticastMode types.String `tfsdk:"multicast_mode"` + RoutingInstanceEvpn types.Bool `tfsdk:"routing_instance_evpn"` SwitchOrRIOptions []struct { - VRFTargetAuto types.Bool `tfsdk:"vrf_target_auto"` RouteDistinguisher types.String `tfsdk:"route_distinguisher"` VRFExport []types.String `tfsdk:"vrf_export"` VRFImport []types.String `tfsdk:"vrf_import"` VRFTarget types.String `tfsdk:"vrf_target"` + VRFTargetAuto types.Bool `tfsdk:"vrf_target_auto"` VRFTargetExport types.String `tfsdk:"vrf_target_export"` VRFTargetImport types.String `tfsdk:"vrf_target_import"` } `tfsdk:"switch_or_ri_options"` diff --git a/internal/providerfwk/upgradestate_firewall_filter.go b/internal/providerfwk/upgradestate_firewall_filter.go index fb3d6988..e7e991e5 100644 --- a/internal/providerfwk/upgradestate_firewall_filter.go +++ b/internal/providerfwk/upgradestate_firewall_filter.go @@ -210,17 +210,14 @@ func upgradeFirewallFilterStateV0toV1( ctx context.Context, req resource.UpgradeStateRequest, resp *resource.UpgradeStateResponse, ) { type modelV0 struct { - InterfaceSpecific types.Bool `tfsdk:"interface_specific"` ID types.String `tfsdk:"id"` Name types.String `tfsdk:"name"` Family types.String `tfsdk:"family"` + InterfaceSpecific types.Bool `tfsdk:"interface_specific"` Term []struct { Name types.String `tfsdk:"name"` Filter types.String `tfsdk:"filter"` From []struct { - IsFragment types.Bool `tfsdk:"is_fragment"` - TCPEstablished types.Bool `tfsdk:"tcp_established"` - TCPInitial types.Bool `tfsdk:"tcp_initial"` Address []types.String `tfsdk:"address"` AddressExcept []types.String `tfsdk:"address_except"` DestinationAddress []types.String `tfsdk:"destination_address"` @@ -233,6 +230,7 @@ func upgradeFirewallFilterStateV0toV1( IcmpCodeExcept []types.String `tfsdk:"icmp_code_except"` IcmpType []types.String `tfsdk:"icmp_type"` IcmpTypeExcept []types.String `tfsdk:"icmp_type_except"` + IsFragment types.Bool `tfsdk:"is_fragment"` NextHeader []types.String `tfsdk:"next_header"` NextHeaderExcept []types.String `tfsdk:"next_header_except"` Port []types.String `tfsdk:"port"` @@ -247,19 +245,21 @@ func upgradeFirewallFilterStateV0toV1( SourcePortExcept []types.String `tfsdk:"source_port_except"` SourcePrefixList []types.String `tfsdk:"source_prefix_list"` SourcePrefixListExcept []types.String `tfsdk:"source_prefix_list_except"` + TCPEstablished types.Bool `tfsdk:"tcp_established"` TCPFlags types.String `tfsdk:"tcp_flags"` + TCPInitial types.Bool `tfsdk:"tcp_initial"` } `tfsdk:"from"` Then []struct { + Action types.String `tfsdk:"action"` + Count types.String `tfsdk:"count"` Log types.Bool `tfsdk:"log"` PacketMode types.Bool `tfsdk:"packet_mode"` + Policer types.String `tfsdk:"policer"` PortMirror types.Bool `tfsdk:"port_mirror"` + RoutingInstance types.String `tfsdk:"routing_instance"` Sample types.Bool `tfsdk:"sample"` ServiceAccounting types.Bool `tfsdk:"service_accounting"` Syslog types.Bool `tfsdk:"syslog"` - Action types.String `tfsdk:"action"` - Count types.String `tfsdk:"count"` - Policer types.String `tfsdk:"policer"` - RoutingInstance types.String `tfsdk:"routing_instance"` } `tfsdk:"then"` } `tfsdk:"term"` } diff --git a/internal/providerfwk/upgradestate_firewall_policer.go b/internal/providerfwk/upgradestate_firewall_policer.go index ed06dee2..6d4d9bf9 100644 --- a/internal/providerfwk/upgradestate_firewall_policer.go +++ b/internal/providerfwk/upgradestate_firewall_policer.go @@ -68,9 +68,9 @@ func upgradeFirewallPolicerStateV0toV1( ctx context.Context, req resource.UpgradeStateRequest, resp *resource.UpgradeStateResponse, ) { type modelV0 struct { - FilterSpecific types.Bool `tfsdk:"filter_specific"` ID types.String `tfsdk:"id"` Name types.String `tfsdk:"name"` + FilterSpecific types.Bool `tfsdk:"filter_specific"` IfExceeding []struct { BurstSizeLimit types.String `tfsdk:"burst_size_limit"` BandwidthPercent types.Int64 `tfsdk:"bandwidth_percent"` @@ -78,9 +78,9 @@ func upgradeFirewallPolicerStateV0toV1( } `tfsdk:"if_exceeding"` Then []struct { Discard types.Bool `tfsdk:"discard"` - OutOfProfile types.Bool `tfsdk:"out_of_profile"` ForwardingClass types.String `tfsdk:"forwarding_class"` LossPriority types.String `tfsdk:"loss_priority"` + OutOfProfile types.Bool `tfsdk:"out_of_profile"` } `tfsdk:"then"` } diff --git a/internal/providerfwk/upgradestate_forwardingoptions_sampling_instance.go b/internal/providerfwk/upgradestate_forwardingoptions_sampling_instance.go index 01480d34..7d44055a 100644 --- a/internal/providerfwk/upgradestate_forwardingoptions_sampling_instance.go +++ b/internal/providerfwk/upgradestate_forwardingoptions_sampling_instance.go @@ -376,9 +376,9 @@ func upgradeForwardingoptionsSamplingInstanceStateV0toV1( ) { //nolint:lll type modelV0 struct { - Disable types.Bool `tfsdk:"disable"` ID types.String `tfsdk:"id"` Name types.String `tfsdk:"name"` + Disable types.Bool `tfsdk:"disable"` FamilyInetInput []struct { MaxPacketsPerSecond types.Int64 `tfsdk:"max_packets_per_second"` MaximumPacketLength types.Int64 `tfsdk:"maximum_packet_length"` @@ -393,19 +393,19 @@ func upgradeForwardingoptionsSamplingInstanceStateV0toV1( InlineJflowExportRate types.Int64 `tfsdk:"inline_jflow_export_rate"` InlineJflowSourceAddress types.String `tfsdk:"inline_jflow_source_address"` FlowServer []struct { + Hostname types.String `tfsdk:"hostname"` + Port types.Int64 `tfsdk:"port"` AggregationAutonomousSystem types.Bool `tfsdk:"aggregation_autonomous_system"` AggregationDestinationPrefix types.Bool `tfsdk:"aggregation_destination_prefix"` AggregationProtocolPort types.Bool `tfsdk:"aggregation_protocol_port"` AggregationSourceDestinationPrefix types.Bool `tfsdk:"aggregation_source_destination_prefix"` AggregationSourceDestinationPrefixCaidaCompliant types.Bool `tfsdk:"aggregation_source_destination_prefix_caida_compliant"` AggregationSourcePrefix types.Bool `tfsdk:"aggregation_source_prefix"` - LocalDump types.Bool `tfsdk:"local_dump"` - NoLocalDump types.Bool `tfsdk:"no_local_dump"` - Hostname types.String `tfsdk:"hostname"` - Port types.Int64 `tfsdk:"port"` AutonomousSystemType types.String `tfsdk:"autonomous_system_type"` Dscp types.Int64 `tfsdk:"dscp"` ForwardingClass types.String `tfsdk:"forwarding_class"` + LocalDump types.Bool `tfsdk:"local_dump"` + NoLocalDump types.Bool `tfsdk:"no_local_dump"` RoutingInstance types.String `tfsdk:"routing_instance"` SourceAddress types.String `tfsdk:"source_address"` Version types.Int64 `tfsdk:"version"` @@ -428,19 +428,19 @@ func upgradeForwardingoptionsSamplingInstanceStateV0toV1( InlineJflowExportRate types.Int64 `tfsdk:"inline_jflow_export_rate"` InlineJflowSourceAddress types.String `tfsdk:"inline_jflow_source_address"` FlowServer []struct { + Hostname types.String `tfsdk:"hostname"` + Port types.Int64 `tfsdk:"port"` AggregationAutonomousSystem types.Bool `tfsdk:"aggregation_autonomous_system"` AggregationDestinationPrefix types.Bool `tfsdk:"aggregation_destination_prefix"` AggregationProtocolPort types.Bool `tfsdk:"aggregation_protocol_port"` AggregationSourceDestinationPrefix types.Bool `tfsdk:"aggregation_source_destination_prefix"` AggregationSourceDestinationPrefixCaidaCompliant types.Bool `tfsdk:"aggregation_source_destination_prefix_caida_compliant"` AggregationSourcePrefix types.Bool `tfsdk:"aggregation_source_prefix"` - LocalDump types.Bool `tfsdk:"local_dump"` - NoLocalDump types.Bool `tfsdk:"no_local_dump"` - Hostname types.String `tfsdk:"hostname"` - Port types.Int64 `tfsdk:"port"` AutonomousSystemType types.String `tfsdk:"autonomous_system_type"` Dscp types.Int64 `tfsdk:"dscp"` ForwardingClass types.String `tfsdk:"forwarding_class"` + LocalDump types.Bool `tfsdk:"local_dump"` + NoLocalDump types.Bool `tfsdk:"no_local_dump"` RoutingInstance types.String `tfsdk:"routing_instance"` SourceAddress types.String `tfsdk:"source_address"` Version9Template types.String `tfsdk:"version9_template"` @@ -461,19 +461,19 @@ func upgradeForwardingoptionsSamplingInstanceStateV0toV1( InlineJflowExportRate types.Int64 `tfsdk:"inline_jflow_export_rate"` InlineJflowSourceAddress types.String `tfsdk:"inline_jflow_source_address"` FlowServer []struct { + Hostname types.String `tfsdk:"hostname"` + Port types.Int64 `tfsdk:"port"` AggregationAutonomousSystem types.Bool `tfsdk:"aggregation_autonomous_system"` AggregationDestinationPrefix types.Bool `tfsdk:"aggregation_destination_prefix"` AggregationProtocolPort types.Bool `tfsdk:"aggregation_protocol_port"` AggregationSourceDestinationPrefix types.Bool `tfsdk:"aggregation_source_destination_prefix"` AggregationSourceDestinationPrefixCaidaCompliant types.Bool `tfsdk:"aggregation_source_destination_prefix_caida_compliant"` AggregationSourcePrefix types.Bool `tfsdk:"aggregation_source_prefix"` - LocalDump types.Bool `tfsdk:"local_dump"` - NoLocalDump types.Bool `tfsdk:"no_local_dump"` - Hostname types.String `tfsdk:"hostname"` - Port types.Int64 `tfsdk:"port"` AutonomousSystemType types.String `tfsdk:"autonomous_system_type"` Dscp types.Int64 `tfsdk:"dscp"` ForwardingClass types.String `tfsdk:"forwarding_class"` + LocalDump types.Bool `tfsdk:"local_dump"` + NoLocalDump types.Bool `tfsdk:"no_local_dump"` RoutingInstance types.String `tfsdk:"routing_instance"` SourceAddress types.String `tfsdk:"source_address"` Version9Template types.String `tfsdk:"version9_template"` diff --git a/internal/providerfwk/upgradestate_interface_logical.go b/internal/providerfwk/upgradestate_interface_logical.go index 3eecb7fa..fe360cd2 100644 --- a/internal/providerfwk/upgradestate_interface_logical.go +++ b/internal/providerfwk/upgradestate_interface_logical.go @@ -448,38 +448,38 @@ func upgradeInterfaceLogicalV0toV1( ctx context.Context, req resource.UpgradeStateRequest, resp *resource.UpgradeStateResponse, ) { type modelV0 struct { - St0AlsoOnDestroy types.Bool `tfsdk:"st0_also_on_destroy"` - VlanNoCompute types.Bool `tfsdk:"vlan_no_compute"` - Disable types.Bool `tfsdk:"disable"` ID types.String `tfsdk:"id"` Name types.String `tfsdk:"name"` + St0AlsoOnDestroy types.Bool `tfsdk:"st0_also_on_destroy"` + Disable types.Bool `tfsdk:"disable"` Description types.String `tfsdk:"description"` RoutingInstance types.String `tfsdk:"routing_instance"` SecurityInboundProtocols []types.String `tfsdk:"security_inbound_protocols"` SecurityInboundServices []types.String `tfsdk:"security_inbound_services"` SecurityZone types.String `tfsdk:"security_zone"` VlanID types.Int64 `tfsdk:"vlan_id"` + VlanNoCompute types.Bool `tfsdk:"vlan_no_compute"` FamilyInet []struct { - SamplingInput types.Bool `tfsdk:"sampling_input"` - SamplingOutput types.Bool `tfsdk:"sampling_output"` FilterInput types.String `tfsdk:"filter_input"` FilterOutput types.String `tfsdk:"filter_output"` Mtu types.Int64 `tfsdk:"mtu"` + SamplingInput types.Bool `tfsdk:"sampling_input"` + SamplingOutput types.Bool `tfsdk:"sampling_output"` Address []struct { + CidrIP types.String `tfsdk:"cidr_ip"` Preferred types.Bool `tfsdk:"preferred"` Primary types.Bool `tfsdk:"primary"` - CidrIP types.String `tfsdk:"cidr_ip"` VRRPGroup []struct { - AcceptData types.Bool `tfsdk:"accept_data"` - NoAcceptData types.Bool `tfsdk:"no_accept_data"` - Preempt types.Bool `tfsdk:"preempt"` - NoPreempt types.Bool `tfsdk:"no_preempt"` Identifier types.Int64 `tfsdk:"identifier"` VirtualAddress []types.String `tfsdk:"virtual_address"` + AcceptData types.Bool `tfsdk:"accept_data"` + NoAcceptData types.Bool `tfsdk:"no_accept_data"` AdvertiseInterval types.Int64 `tfsdk:"advertise_interval"` AdvertisementsThreshold types.Int64 `tfsdk:"advertisements_threshold"` AuthenticationKey types.String `tfsdk:"authentication_key"` AuthenticationType types.String `tfsdk:"authentication_type"` + Preempt types.Bool `tfsdk:"preempt"` + NoPreempt types.Bool `tfsdk:"no_preempt"` Priority types.Int64 `tfsdk:"priority"` TrackInterface []struct { Interface types.String `tfsdk:"interface"` @@ -494,23 +494,23 @@ func upgradeInterfaceLogicalV0toV1( } `tfsdk:"address"` DHCP []struct { SrxOldOptionName types.Bool `tfsdk:"srx_old_option_name"` - ClientIdentifierPrefixHostname types.Bool `tfsdk:"client_identifier_prefix_hostname"` - ClientIdentifierPrefixRoutingInstanceName types.Bool `tfsdk:"client_identifier_prefix_routing_instance_name"` - ForceDiscover types.Bool `tfsdk:"force_discover"` - LeaseTimeInfinite types.Bool `tfsdk:"lease_time_infinite"` - NoDNSInstall types.Bool `tfsdk:"no_dns_install"` - OptionsNoHostname types.Bool `tfsdk:"options_no_hostname"` - UpdateServer types.Bool `tfsdk:"update_server"` ClientIdentifierASCII types.String `tfsdk:"client_identifier_ascii"` ClientIdentifierHexadecimal types.String `tfsdk:"client_identifier_hexadecimal"` + ClientIdentifierPrefixHostname types.Bool `tfsdk:"client_identifier_prefix_hostname"` + ClientIdentifierPrefixRoutingInstanceName types.Bool `tfsdk:"client_identifier_prefix_routing_instance_name"` ClientIdentifierUseInterfaceDescription types.String `tfsdk:"client_identifier_use_interface_description"` ClientIdentifierUseridASCII types.String `tfsdk:"client_identifier_userid_ascii"` ClientIdentifierUseridHexadecimal types.String `tfsdk:"client_identifier_userid_hexadecimal"` + ForceDiscover types.Bool `tfsdk:"force_discover"` LeaseTime types.Int64 `tfsdk:"lease_time"` + LeaseTimeInfinite types.Bool `tfsdk:"lease_time_infinite"` Metric types.Int64 `tfsdk:"metric"` + NoDNSInstall types.Bool `tfsdk:"no_dns_install"` + OptionsNoHostname types.Bool `tfsdk:"options_no_hostname"` RetransmissionAttempt types.Int64 `tfsdk:"retransmission_attempt"` RetransmissionInterval types.Int64 `tfsdk:"retransmission_interval"` ServerAddress types.String `tfsdk:"server_address"` + UpdateServer types.Bool `tfsdk:"update_server"` VendorID types.String `tfsdk:"vendor_id"` } `tfsdk:"dhcp"` RPFCheck []struct { @@ -520,25 +520,25 @@ func upgradeInterfaceLogicalV0toV1( } `tfsdk:"family_inet"` FamilyInet6 []struct { DadDisable types.Bool `tfsdk:"dad_disable"` - SamplingInput types.Bool `tfsdk:"sampling_input"` - SamplingOutput types.Bool `tfsdk:"sampling_output"` FilterInput types.String `tfsdk:"filter_input"` FilterOutput types.String `tfsdk:"filter_output"` Mtu types.Int64 `tfsdk:"mtu"` + SamplingInput types.Bool `tfsdk:"sampling_input"` + SamplingOutput types.Bool `tfsdk:"sampling_output"` Address []struct { + CidrIP types.String `tfsdk:"cidr_ip"` Preferred types.Bool `tfsdk:"preferred"` Primary types.Bool `tfsdk:"primary"` - CidrIP types.String `tfsdk:"cidr_ip"` VRRPGroup []struct { - AcceptData types.Bool `tfsdk:"accept_data"` - NoAcceptData types.Bool `tfsdk:"no_accept_data"` - Preempt types.Bool `tfsdk:"preempt"` - NoPreempt types.Bool `tfsdk:"no_preempt"` Identifier types.Int64 `tfsdk:"identifier"` VirtualAddress []types.String `tfsdk:"virtual_address"` VirutalLinkLocalAddress types.String `tfsdk:"virtual_link_local_address"` + AcceptData types.Bool `tfsdk:"accept_data"` + NoAcceptData types.Bool `tfsdk:"no_accept_data"` AdvertiseInterval types.Int64 `tfsdk:"advertise_interval"` AdvertisementsThreshold types.Int64 `tfsdk:"advertisements_threshold"` + Preempt types.Bool `tfsdk:"preempt"` + NoPreempt types.Bool `tfsdk:"no_preempt"` Priority types.Int64 `tfsdk:"priority"` TrackInterface []struct { Interface types.String `tfsdk:"interface"` @@ -552,14 +552,14 @@ func upgradeInterfaceLogicalV0toV1( } `tfsdk:"vrrp_group"` } `tfsdk:"address"` DHCPv6Client []struct { + ClientIdentifierDuidType types.String `tfsdk:"client_identifier_duid_type"` + ClientType types.String `tfsdk:"client_type"` ClientIATypeNA types.Bool `tfsdk:"client_ia_type_na"` ClientIATypePD types.Bool `tfsdk:"client_ia_type_pd"` NoDNSInstall types.Bool `tfsdk:"no_dns_install"` - RapidCommit types.Bool `tfsdk:"rapid_commit"` - ClientIdentifierDuidType types.String `tfsdk:"client_identifier_duid_type"` - ClientType types.String `tfsdk:"client_type"` PrefixDelegatingPreferredPrefixLength types.Int64 `tfsdk:"prefix_delegating_preferred_prefix_length"` PrefixDelegatingSubPrefixLength types.Int64 `tfsdk:"prefix_delegating_sub_prefix_length"` + RapidCommit types.Bool `tfsdk:"rapid_commit"` ReqOption []types.String `tfsdk:"req_option"` RetransmissionAttempt types.Int64 `tfsdk:"retransmission_attempt"` UpdateRouterAdvertisementInterface []types.String `tfsdk:"update_router_advertisement_interface"` @@ -571,13 +571,13 @@ func upgradeInterfaceLogicalV0toV1( } `tfsdk:"rpf_check"` } `tfsdk:"family_inet6"` Tunnel []struct { + Destination types.String `tfsdk:"destination"` + Source types.String `tfsdk:"source"` AllowFragmentation types.Bool `tfsdk:"allow_fragmentation"` DoNotFragment types.Bool `tfsdk:"do_not_fragment"` + FlowLabel types.Int64 `tfsdk:"flow_label"` PathMtuDiscovery types.Bool `tfsdk:"path_mtu_discovery"` NoPathMtuDiscovery types.Bool `tfsdk:"no_path_mtu_discovery"` - Destination types.String `tfsdk:"destination"` - Source types.String `tfsdk:"source"` - FlowLabel types.Int64 `tfsdk:"flow_label"` RoutingInstanceDestination types.String `tfsdk:"routing_instance_destination"` TrafficClass types.Int64 `tfsdk:"traffic_class"` TTL types.Int64 `tfsdk:"ttl"` diff --git a/internal/providerfwk/upgradestate_interface_physical.go b/internal/providerfwk/upgradestate_interface_physical.go index c9060870..9d13e2bd 100644 --- a/internal/providerfwk/upgradestate_interface_physical.go +++ b/internal/providerfwk/upgradestate_interface_physical.go @@ -249,41 +249,41 @@ func upgradeInterfacePhysicalV0toV1( ctx context.Context, req resource.UpgradeStateRequest, resp *resource.UpgradeStateResponse, ) { type modelV0 struct { - NoDisableOnDestroy types.Bool `tfsdk:"no_disable_on_destroy"` - Disable types.Bool `tfsdk:"disable"` - Trunk types.Bool `tfsdk:"trunk"` - VlanTagging types.Bool `tfsdk:"vlan_tagging"` ID types.String `tfsdk:"id"` Name types.String `tfsdk:"name"` + NoDisableOnDestroy types.Bool `tfsdk:"no_disable_on_destroy"` Description types.String `tfsdk:"description"` + Disable types.Bool `tfsdk:"disable"` Mtu types.Int64 `tfsdk:"mtu"` + Trunk types.Bool `tfsdk:"trunk"` VlanMembers []types.String `tfsdk:"vlan_members"` VlanNative types.Int64 `tfsdk:"vlan_native"` + VlanTagging types.Bool `tfsdk:"vlan_tagging"` ESI []struct { - AutoDeriveLACP types.Bool `tfsdk:"auto_derive_lacp"` Mode types.String `tfsdk:"mode"` + AutoDeriveLACP types.Bool `tfsdk:"auto_derive_lacp"` DFElectionType types.String `tfsdk:"df_election_type"` Identifier types.String `tfsdk:"identifier"` SourceBMAC types.String `tfsdk:"source_bmac"` } `tfsdk:"esi"` EtherOpts []struct { + Ae8023ad types.String `tfsdk:"ae_8023ad"` AutoNegotiation types.Bool `tfsdk:"auto_negotiation"` NoAutoNegotiation types.Bool `tfsdk:"no_auto_negotiation"` FlowControl types.Bool `tfsdk:"flow_control"` NoFlowControl types.Bool `tfsdk:"no_flow_control"` Loopback types.Bool `tfsdk:"loopback"` NoLoopback types.Bool `tfsdk:"no_loopback"` - Ae8023ad types.String `tfsdk:"ae_8023ad"` RedundantParent types.String `tfsdk:"redundant_parent"` } `tfsdk:"ether_opts"` GigetherOpts []struct { + Ae8023ad types.String `tfsdk:"ae_8023ad"` AutoNegotiation types.Bool `tfsdk:"auto_negotiation"` NoAutoNegotiation types.Bool `tfsdk:"no_auto_negotiation"` FlowControl types.Bool `tfsdk:"flow_control"` NoFlowControl types.Bool `tfsdk:"no_flow_control"` Loopback types.Bool `tfsdk:"loopback"` NoLoopback types.Bool `tfsdk:"no_loopback"` - Ae8023ad types.String `tfsdk:"ae_8023ad"` RedundantParent types.String `tfsdk:"redundant_parent"` } `tfsdk:"gigether_opts"` ParentEtherOpts []struct { @@ -291,17 +291,16 @@ func upgradeInterfacePhysicalV0toV1( NoFlowControl types.Bool `tfsdk:"no_flow_control"` Loopback types.Bool `tfsdk:"loopback"` NoLoopback types.Bool `tfsdk:"no_loopback"` - SourceFiltering types.Bool `tfsdk:"source_filtering"` LinkSpeed types.String `tfsdk:"link_speed"` MinimumBandwidth types.String `tfsdk:"minimum_bandwidth"` MinimumLinks types.Int64 `tfsdk:"minimum_links"` RedundancyGroup types.Int64 `tfsdk:"redundancy_group"` SourceAddressFilter []types.String `tfsdk:"source_address_filter"` + SourceFiltering types.Bool `tfsdk:"source_filtering"` BFDLivenessDetection []struct { - AuthenticationLooseCheck types.Bool `tfsdk:"authentication_loose_check"` - NoAdaptation types.Bool `tfsdk:"no_adaptation"` LocalAddress types.String `tfsdk:"local_address"` AuthenticationAlgorithm types.String `tfsdk:"authentication_algorithm"` + AuthenticationLooseCheck types.Bool `tfsdk:"authentication_loose_check"` AuthenticationKeyChain types.String `tfsdk:"authentication_key_chain"` DetectionTimeThreshold types.Int64 `tfsdk:"detection_time_threshold"` HolddownInterval types.Int64 `tfsdk:"holddown_interval"` @@ -309,6 +308,7 @@ func upgradeInterfacePhysicalV0toV1( MinimumReceiveInterval types.Int64 `tfsdk:"minimum_receive_interval"` Multiplier types.Int64 `tfsdk:"multiplier"` Neighbor types.String `tfsdk:"neighbor"` + NoAdaptation types.Bool `tfsdk:"no_adaptation"` TransmitIntervalMinimumInterval types.Int64 `tfsdk:"transmit_interval_minimum_interval"` TransmitIntervalThreshold types.Int64 `tfsdk:"transmit_interval_threshold"` Version types.String `tfsdk:"version"` diff --git a/internal/providerfwk/upgradestate_policyoptions_policy_statement.go b/internal/providerfwk/upgradestate_policyoptions_policy_statement.go index 038b2244..50cdcf7e 100644 --- a/internal/providerfwk/upgradestate_policyoptions_policy_statement.go +++ b/internal/providerfwk/upgradestate_policyoptions_policy_statement.go @@ -228,9 +228,9 @@ func upgradePolicyoptionsPolicyStatementStateV0toV1( ctx context.Context, req resource.UpgradeStateRequest, resp *resource.UpgradeStateResponse, ) { type modelV0 struct { - AddItToForwardingTableExport types.Bool `tfsdk:"add_it_to_forwarding_table_export"` ID types.String `tfsdk:"id"` Name types.String `tfsdk:"name"` + AddItToForwardingTableExport types.Bool `tfsdk:"add_it_to_forwarding_table_export"` From []policyoptionsPolicyStatementBlockFrom `tfsdk:"from"` To []policyoptionsPolicyStatementBlockTo `tfsdk:"to"` Then []struct { diff --git a/internal/providerfwk/upgradestate_security.go b/internal/providerfwk/upgradestate_security.go index 5aed9dbd..d199828c 100644 --- a/internal/providerfwk/upgradestate_security.go +++ b/internal/providerfwk/upgradestate_security.go @@ -400,10 +400,10 @@ func (rsc *security) UpgradeState(_ context.Context) map[int64]resource.StateUpg "size": schema.Int64Attribute{ Optional: true, }, - "no_world_readable": schema.BoolAttribute{ + "world_readable": schema.BoolAttribute{ Optional: true, }, - "world_readable": schema.BoolAttribute{ + "no_world_readable": schema.BoolAttribute{ Optional: true, }, }, @@ -560,8 +560,8 @@ func upgradeSecurityV0toV1( ctx context.Context, req resource.UpgradeStateRequest, resp *resource.UpgradeStateResponse, ) { type modelV0 struct { - CleanOnDestroy types.Bool `tfsdk:"clean_on_destroy"` ID types.String `tfsdk:"id"` + CleanOnDestroy types.Bool `tfsdk:"clean_on_destroy"` Alg []struct { DNSDisable types.Bool `tfsdk:"dns_disable"` FtpDisable types.Bool `tfsdk:"ftp_disable"` @@ -586,11 +586,11 @@ func upgradeSecurityV0toV1( ForceIPReassembly types.Bool `tfsdk:"force_ip_reassembly"` IpsecPerformanceAcceleration types.Bool `tfsdk:"ipsec_performance_acceleration"` McastBufferEnhance types.Bool `tfsdk:"mcast_buffer_enhance"` - PreserveIncomingFragmentSize types.Bool `tfsdk:"preserve_incoming_fragment_size"` - SyncIcmpSession types.Bool `tfsdk:"sync_icmp_session"` PendingSessQueueLength types.String `tfsdk:"pending_sess_queue_length"` + PreserveIncomingFragmentSize types.Bool `tfsdk:"preserve_incoming_fragment_size"` RouteChangeTimeout types.Int64 `tfsdk:"route_change_timeout"` SynFloodProtectionMode types.String `tfsdk:"syn_flood_protection_mode"` + SyncIcmpSession types.Bool `tfsdk:"sync_icmp_session"` AdvancedOptions []struct { DropMatchingLinkLocalAddress types.Bool `tfsdk:"drop_matching_link_local_address"` DropMatchingReservedIPAddress types.Bool `tfsdk:"drop_matching_reserved_ip_address"` @@ -623,13 +623,13 @@ func upgradeSecurityV0toV1( } `tfsdk:"tcp_mss"` TCPSession []struct { FinInvalidateSession types.Bool `tfsdk:"fin_invalidate_session"` + MaximumWindow types.String `tfsdk:"maximum_window"` NoSequenceCheck types.Bool `tfsdk:"no_sequence_check"` NoSynCheck types.Bool `tfsdk:"no_syn_check"` NoSynCheckInTunnel types.Bool `tfsdk:"no_syn_check_in_tunnel"` RstInvalidateSession types.Bool `tfsdk:"rst_invalidate_session"` RstSequenceCheck types.Bool `tfsdk:"rst_sequence_check"` StrictSynCheck types.Bool `tfsdk:"strict_syn_check"` - MaximumWindow types.String `tfsdk:"maximum_window"` TCPInitialTimeout types.Int64 `tfsdk:"tcp_initial_timeout"` TimeWaitState []struct { ApplyToHalfCloseState types.Bool `tfsdk:"apply_to_half_close_state"` @@ -648,9 +648,9 @@ func upgradeSecurityV0toV1( } `tfsdk:"forwarding_process"` IdpSecurityPackage []struct { AutomaticEnable types.Bool `tfsdk:"automatic_enable"` - InstallIgnoreVersionCheck types.Bool `tfsdk:"install_ignore_version_check"` AutomaticInterval types.Int64 `tfsdk:"automatic_interval"` AutomaticStartTime types.String `tfsdk:"automatic_start_time"` + InstallIgnoreVersionCheck types.Bool `tfsdk:"install_ignore_version_check"` ProxyProfile types.String `tfsdk:"proxy_profile"` SourceAddress types.String `tfsdk:"source_address"` URL types.String `tfsdk:"url"` @@ -680,26 +680,26 @@ func upgradeSecurityV0toV1( NoRemoteTrace types.Bool `tfsdk:"no_remote_trace"` RateLimit types.Int64 `tfsdk:"rate_limit"` File []struct { - NoWorldReadable types.Bool `tfsdk:"no_world_readable"` - WorldReadable types.Bool `tfsdk:"world_readable"` Name types.String `tfsdk:"name"` Files types.Int64 `tfsdk:"files"` Match types.String `tfsdk:"match"` Size types.Int64 `tfsdk:"size"` + WorldReadable types.Bool `tfsdk:"world_readable"` + NoWorldReadable types.Bool `tfsdk:"no_world_readable"` } `tfsdk:"file"` } `tfsdk:"ike_traceoptions"` Log []struct { Disable types.Bool `tfsdk:"disable"` - Report types.Bool `tfsdk:"report"` - UtcTimestamp types.Bool `tfsdk:"utc_timestamp"` EventRate types.Int64 `tfsdk:"event_rate"` FacilityOverride types.String `tfsdk:"facility_override"` Format types.String `tfsdk:"format"` MaxDatabaseRecord types.Int64 `tfsdk:"max_database_record"` Mode types.String `tfsdk:"mode"` RateCap types.Int64 `tfsdk:"rate_cap"` + Report types.Bool `tfsdk:"report"` SourceAddress types.String `tfsdk:"source_address"` SourceInterface types.String `tfsdk:"source_interface"` + UtcTimestamp types.Bool `tfsdk:"utc_timestamp"` File []struct { Files types.Int64 `tfsdk:"files"` Name types.String `tfsdk:"name"` diff --git a/internal/providerfwk/upgradestate_security_global_policy.go b/internal/providerfwk/upgradestate_security_global_policy.go index fb14ac4e..0f3647a8 100644 --- a/internal/providerfwk/upgradestate_security_global_policy.go +++ b/internal/providerfwk/upgradestate_security_global_policy.go @@ -147,38 +147,38 @@ func upgradeSecurityGlobalPolicyV0toV1( type modelV0 struct { ID types.String `tfsdk:"id"` Policy []struct { - Count types.Bool `tfsdk:"count"` - LogInit types.Bool `tfsdk:"log_init"` - LogClose types.Bool `tfsdk:"log_close"` - MatchDestinationAddressExcluded types.Bool `tfsdk:"match_destination_address_excluded"` - MatchSourceAddressExcluded types.Bool `tfsdk:"match_source_address_excluded"` Name types.String `tfsdk:"name"` - Then types.String `tfsdk:"then"` - MatchSourceEndUserProfile types.String `tfsdk:"match_source_end_user_profile"` MatchSourceAddress []types.String `tfsdk:"match_source_address"` MatchDestinationAddress []types.String `tfsdk:"match_destination_address"` MatchFromZone []types.String `tfsdk:"match_from_zone"` MatchToZone []types.String `tfsdk:"match_to_zone"` + Then types.String `tfsdk:"then"` + Count types.Bool `tfsdk:"count"` + LogInit types.Bool `tfsdk:"log_init"` + LogClose types.Bool `tfsdk:"log_close"` MatchApplication []types.String `tfsdk:"match_application"` + MatchDestinationAddressExcluded types.Bool `tfsdk:"match_destination_address_excluded"` MatchDynamicApplication []types.String `tfsdk:"match_dynamic_application"` + MatchSourceAddressExcluded types.Bool `tfsdk:"match_source_address_excluded"` + MatchSourceEndUserProfile types.String `tfsdk:"match_source_end_user_profile"` PermitApplicationServices []struct { - Idp types.Bool `tfsdk:"idp"` - RedirectWx types.Bool `tfsdk:"redirect_wx"` - ReverseRedirectWx types.Bool `tfsdk:"reverse_redirect_wx"` AdvancedAntiMalwarePolicy types.String `tfsdk:"advanced_anti_malware_policy"` ApplicationFirewallRuleSet types.String `tfsdk:"application_firewall_rule_set"` ApplicationTrafficControlRuleSet types.String `tfsdk:"application_traffic_control_rule_set"` GprsGtpProfile types.String `tfsdk:"gprs_gtp_profile"` GprsSctpProfile types.String `tfsdk:"gprs_sctp_profile"` + Idp types.Bool `tfsdk:"idp"` IdpPolicy types.String `tfsdk:"idp_policy"` + RedirectWx types.Bool `tfsdk:"redirect_wx"` + ReverseRedirectWx types.Bool `tfsdk:"reverse_redirect_wx"` SecurityIntelligencePolicy types.String `tfsdk:"security_intelligence_policy"` + UtmPolicy types.String `tfsdk:"utm_policy"` SSLProxy []struct { ProfileName types.String `tfsdk:"profile_name"` } `tfsdk:"ssl_proxy"` UacPolicy []struct { CaptivePortal types.String `tfsdk:"captive_portal"` } `tfsdk:"uac_policy"` - UtmPolicy types.String `tfsdk:"utm_policy"` } `tfsdk:"permit_application_services"` } `tfsdk:"policy"` } diff --git a/internal/providerfwk/upgradestate_security_ike_gateway.go b/internal/providerfwk/upgradestate_security_ike_gateway.go index 7ecbc033..88e10be8 100644 --- a/internal/providerfwk/upgradestate_security_ike_gateway.go +++ b/internal/providerfwk/upgradestate_security_ike_gateway.go @@ -150,26 +150,16 @@ func upgradeSecurityIkeGatewayV0toV1( ctx context.Context, req resource.UpgradeStateRequest, resp *resource.UpgradeStateResponse, ) { type modelV0 struct { - GeneralIkeID types.Bool `tfsdk:"general_ike_id"` - NoNatTraversal types.Bool `tfsdk:"no_nat_traversal"` ID types.String `tfsdk:"id"` Name types.String `tfsdk:"name"` ExternalInterface types.String `tfsdk:"external_interface"` Policy types.String `tfsdk:"policy"` Address []types.String `tfsdk:"address"` + GeneralIkeID types.Bool `tfsdk:"general_ike_id"` LocalAddress types.String `tfsdk:"local_address"` + NoNatTraversal types.Bool `tfsdk:"no_nat_traversal"` Version types.String `tfsdk:"version"` - Aaa []struct { - AccessProfile types.String `tfsdk:"access_profile"` - ClientPassword types.String `tfsdk:"client_password"` - ClientUsername types.String `tfsdk:"client_username"` - } `tfsdk:"aaa"` - DeadPeerDetection []struct { - Interval types.Int64 `tfsdk:"interval"` - SendMode types.String `tfsdk:"send_mode"` - Threshold types.Int64 `tfsdk:"threshold"` - } `tfsdk:"dead_peer_detection"` - DynamicRemote []struct { + DynamicRemote []struct { ConnectionsLimit types.Int64 `tfsdk:"connections_limit"` Hostname types.String `tfsdk:"hostname"` IkeUserType types.String `tfsdk:"ike_user_type"` @@ -182,6 +172,16 @@ func upgradeSecurityIkeGatewayV0toV1( Wildcard types.String `tfsdk:"wildcard"` } `tfsdk:"distinguished_name"` } `tfsdk:"dynamic_remote"` + Aaa []struct { + AccessProfile types.String `tfsdk:"access_profile"` + ClientPassword types.String `tfsdk:"client_password"` + ClientUsername types.String `tfsdk:"client_username"` + } `tfsdk:"aaa"` + DeadPeerDetection []struct { + Interval types.Int64 `tfsdk:"interval"` + SendMode types.String `tfsdk:"send_mode"` + Threshold types.Int64 `tfsdk:"threshold"` + } `tfsdk:"dead_peer_detection"` LocalIdentity []struct { Type types.String `tfsdk:"type"` Value types.String `tfsdk:"value"` diff --git a/internal/providerfwk/upgradestate_security_ipsec_vpn.go b/internal/providerfwk/upgradestate_security_ipsec_vpn.go index 1d117db1..94c18261 100644 --- a/internal/providerfwk/upgradestate_security_ipsec_vpn.go +++ b/internal/providerfwk/upgradestate_security_ipsec_vpn.go @@ -114,10 +114,10 @@ func upgradeSecurityIpsecVpnV0toV1( RemoteIP types.String `tfsdk:"remote_ip"` } `tfsdk:"traffic_selector"` VpnMonitor []struct { - Optimized types.Bool `tfsdk:"optimized"` - SourceInterfaceAuto types.Bool `tfsdk:"source_interface_auto"` DestinationIP types.String `tfsdk:"destination_ip"` + Optimized types.Bool `tfsdk:"optimized"` SourceInterface types.String `tfsdk:"source_interface"` + SourceInterfaceAuto types.Bool `tfsdk:"source_interface_auto"` } `tfsdk:"vpn_monitor"` } diff --git a/internal/providerfwk/upgradestate_security_nat_static.go b/internal/providerfwk/upgradestate_security_nat_static.go index 55a4d85d..27708dd5 100644 --- a/internal/providerfwk/upgradestate_security_nat_static.go +++ b/internal/providerfwk/upgradestate_security_nat_static.go @@ -107,9 +107,9 @@ func upgradeSecurityNatStaticV0toV1( ctx context.Context, req resource.UpgradeStateRequest, resp *resource.UpgradeStateResponse, ) { type modelV0 struct { - ConfigureRulesSingly types.Bool `tfsdk:"configure_rules_singly"` ID types.String `tfsdk:"id"` Name types.String `tfsdk:"name"` + ConfigureRulesSingly types.Bool `tfsdk:"configure_rules_singly"` Description types.String `tfsdk:"description"` From []struct { Type types.String `tfsdk:"type"` diff --git a/internal/providerfwk/upgradestate_security_policy.go b/internal/providerfwk/upgradestate_security_policy.go index 2611759d..90d6b1df 100644 --- a/internal/providerfwk/upgradestate_security_policy.go +++ b/internal/providerfwk/upgradestate_security_policy.go @@ -150,29 +150,29 @@ func upgradeSecurityPolicyV0toV1( FromZone types.String `tfsdk:"from_zone"` ToZone types.String `tfsdk:"to_zone"` Policy []struct { + Name types.String `tfsdk:"name"` + MatchSourceAddress []types.String `tfsdk:"match_source_address"` + MatchDestinationAddress []types.String `tfsdk:"match_destination_address"` + Then types.String `tfsdk:"then"` Count types.Bool `tfsdk:"count"` LogInit types.Bool `tfsdk:"log_init"` LogClose types.Bool `tfsdk:"log_close"` + MatchApplication []types.String `tfsdk:"match_application"` MatchDestinationAddressExcluded types.Bool `tfsdk:"match_destination_address_excluded"` + MatchDynamicApplication []types.String `tfsdk:"match_dynamic_application"` MatchSourceAddressExcluded types.Bool `tfsdk:"match_source_address_excluded"` - Name types.String `tfsdk:"name"` - Then types.String `tfsdk:"then"` MatchSourceEndUserProfile types.String `tfsdk:"match_source_end_user_profile"` PermitTunnelIpsecVpn types.String `tfsdk:"permit_tunnel_ipsec_vpn"` - MatchSourceAddress []types.String `tfsdk:"match_source_address"` - MatchDestinationAddress []types.String `tfsdk:"match_destination_address"` - MatchApplication []types.String `tfsdk:"match_application"` - MatchDynamicApplication []types.String `tfsdk:"match_dynamic_application"` PermitApplicationServices []struct { - Idp types.Bool `tfsdk:"idp"` - RedirectWx types.Bool `tfsdk:"redirect_wx"` - ReverseRedirectWx types.Bool `tfsdk:"reverse_redirect_wx"` AdvancedAntiMalwarePolicy types.String `tfsdk:"advanced_anti_malware_policy"` ApplicationFirewallRuleSet types.String `tfsdk:"application_firewall_rule_set"` ApplicationTrafficControlRuleSet types.String `tfsdk:"application_traffic_control_rule_set"` GprsGtpProfile types.String `tfsdk:"gprs_gtp_profile"` GprsSctpProfile types.String `tfsdk:"gprs_sctp_profile"` + Idp types.Bool `tfsdk:"idp"` IdpPolicy types.String `tfsdk:"idp_policy"` + RedirectWx types.Bool `tfsdk:"redirect_wx"` + ReverseRedirectWx types.Bool `tfsdk:"reverse_redirect_wx"` SecurityIntelligencePolicy types.String `tfsdk:"security_intelligence_policy"` SSLProxy []struct { ProfileName types.String `tfsdk:"profile_name"` diff --git a/internal/providerfwk/upgradestate_services_flowmonitoring_vipfix_template.go b/internal/providerfwk/upgradestate_services_flowmonitoring_vipfix_template.go index edb8cc4c..d9bec583 100644 --- a/internal/providerfwk/upgradestate_services_flowmonitoring_vipfix_template.go +++ b/internal/providerfwk/upgradestate_services_flowmonitoring_vipfix_template.go @@ -84,21 +84,21 @@ func upgradeServicesFlowMonitoringVIPFixTemplateStateV0toV1( ctx context.Context, req resource.UpgradeStateRequest, resp *resource.UpgradeStateResponse, ) { type modelV0 struct { - FlowKeyFlowDirection types.Bool `tfsdk:"flow_key_flow_direction"` - FlowKeyVlanID types.Bool `tfsdk:"flow_key_vlan_id"` - NexthopLearningEnable types.Bool `tfsdk:"nexthop_learning_enable"` - NexthopLearningDisable types.Bool `tfsdk:"nexthop_learning_disable"` - TunnelObservationIPv4 types.Bool `tfsdk:"tunnel_observation_ipv4"` - TunnelObservationIPv6 types.Bool `tfsdk:"tunnel_observation_ipv6"` ID types.String `tfsdk:"id"` Name types.String `tfsdk:"name"` Type types.String `tfsdk:"type"` FlowActiveTimeout types.Int64 `tfsdk:"flow_active_timeout"` FlowInactiveTimeout types.Int64 `tfsdk:"flow_inactive_timeout"` + FlowKeyFlowDirection types.Bool `tfsdk:"flow_key_flow_direction"` + FlowKeyVlanID types.Bool `tfsdk:"flow_key_vlan_id"` IPTemplateExportExtension []types.String `tfsdk:"ip_template_export_extension"` + NexthopLearningEnable types.Bool `tfsdk:"nexthop_learning_enable"` + NexthopLearningDisable types.Bool `tfsdk:"nexthop_learning_disable"` ObservationDomainID types.Int64 `tfsdk:"observation_domain_id"` OptionTemplateID types.Int64 `tfsdk:"option_template_id"` TemplateID types.Int64 `tfsdk:"template_id"` + TunnelObservationIPv4 types.Bool `tfsdk:"tunnel_observation_ipv4"` + TunnelObservationIPv6 types.Bool `tfsdk:"tunnel_observation_ipv6"` OptionRefreshRate []struct { Packets types.Int64 `tfsdk:"packets"` Seconds types.Int64 `tfsdk:"seconds"` diff --git a/internal/providerfwk/upgradestate_snmp.go b/internal/providerfwk/upgradestate_snmp.go index e9aba4dc..4a54d5e2 100644 --- a/internal/providerfwk/upgradestate_snmp.go +++ b/internal/providerfwk/upgradestate_snmp.go @@ -101,24 +101,24 @@ func upgradeSnmpV0toV1( ctx context.Context, req resource.UpgradeStateRequest, resp *resource.UpgradeStateResponse, ) { type modelV0 struct { + ID types.String `tfsdk:"id"` CleanOnDestroy types.Bool `tfsdk:"clean_on_destroy"` ARP types.Bool `tfsdk:"arp"` ARPHostNameResolution types.Bool `tfsdk:"arp_host_name_resolution"` - FilterDuplicates types.Bool `tfsdk:"filter_duplicates"` - FilterInternalInterfaces types.Bool `tfsdk:"filter_internal_interfaces"` - IfCountWithFilterInterfaces types.Bool `tfsdk:"if_count_with_filter_interfaces"` - RoutingInstanceAccess types.Bool `tfsdk:"routing_instance_access"` - ID types.String `tfsdk:"id"` Contact types.String `tfsdk:"contact"` Description types.String `tfsdk:"description"` EngineID types.String `tfsdk:"engine_id"` + FilterDuplicates types.Bool `tfsdk:"filter_duplicates"` FilterInterfaces []types.String `tfsdk:"filter_interfaces"` + FilterInternalInterfaces types.Bool `tfsdk:"filter_internal_interfaces"` + IfCountWithFilterInterfaces types.Bool `tfsdk:"if_count_with_filter_interfaces"` Interface []types.String `tfsdk:"interface"` Location types.String `tfsdk:"location"` + RoutingInstanceAccess types.Bool `tfsdk:"routing_instance_access"` RoutingInstanceAccessList []types.String `tfsdk:"routing_instance_access_list"` HealthMonitor []struct { - Idp types.Bool `tfsdk:"idp"` FallingThreshold types.Int64 `tfsdk:"falling_threshold"` + Idp types.Bool `tfsdk:"idp"` IdpFallingThreshold types.Int64 `tfsdk:"idp_falling_threshold"` IdpInterval types.Int64 `tfsdk:"idp_interval"` IdpRisingThreshold types.Int64 `tfsdk:"idp_rising_threshold"` diff --git a/internal/providerfwk/upgradestate_system.go b/internal/providerfwk/upgradestate_system.go index e28a6aca..f34744b5 100644 --- a/internal/providerfwk/upgradestate_system.go +++ b/internal/providerfwk/upgradestate_system.go @@ -648,28 +648,28 @@ func upgradeSystemV0toV1( ctx context.Context, req resource.UpgradeStateRequest, resp *resource.UpgradeStateResponse, ) { type modelV0 struct { + ID types.String `tfsdk:"id"` + AuthenticationOrder []types.String `tfsdk:"authentication_order"` AutoSnapshot types.Bool `tfsdk:"auto_snapshot"` DefaultAddressSelection types.Bool `tfsdk:"default_address_selection"` + DomainName types.String `tfsdk:"domain_name"` + HostName types.String `tfsdk:"host_name"` + MaxConfigurationRollbacks types.Int64 `tfsdk:"max_configuration_rollbacks"` + MaxConfigurationsOnFlash types.Int64 `tfsdk:"max_configurations_on_flash"` + NameServer []types.String `tfsdk:"name_server"` NoMulticastEcho types.Bool `tfsdk:"no_multicast_echo"` NoPingRecordRoute types.Bool `tfsdk:"no_ping_record_route"` NoPingTimestamp types.Bool `tfsdk:"no_ping_time_stamp"` NoRedirects types.Bool `tfsdk:"no_redirects"` NoRedirectsIPv6 types.Bool `tfsdk:"no_redirects_ipv6"` + RadiusOptionsAttributesNasIpaddress types.String `tfsdk:"radius_options_attributes_nas_ipaddress"` RadiusOptionsEnhancedAccounting types.Bool `tfsdk:"radius_options_enhanced_accounting"` RadiusOptionsPasswordProtocolMschapv2 types.Bool `tfsdk:"radius_options_password_protocol_mschapv2"` - ID types.String `tfsdk:"id"` - AuthenticationOrder []types.String `tfsdk:"authentication_order"` - DomainName types.String `tfsdk:"domain_name"` - HostName types.String `tfsdk:"host_name"` - MaxConfigurationRollbacks types.Int64 `tfsdk:"max_configuration_rollbacks"` - MaxConfigurationsOnFlash types.Int64 `tfsdk:"max_configurations_on_flash"` - NameServer []types.String `tfsdk:"name_server"` - RadiusOptionsAttributesNasIpaddress types.String `tfsdk:"radius_options_attributes_nas_ipaddress"` TimeZone types.String `tfsdk:"time_zone"` TracingDestOverrideSyslogHost types.String `tfsdk:"tracing_dest_override_syslog_host"` ArchivalConfiguration []struct { - TransferOnCommit types.Bool `tfsdk:"transfer_on_commit"` TransferInterval types.Int64 `tfsdk:"transfer_interval"` + TransferOnCommit types.Bool `tfsdk:"transfer_on_commit"` ArchiveSite []struct { URL types.String `tfsdk:"url"` Password types.String `tfsdk:"password"` @@ -684,21 +684,21 @@ func upgradeSystemV0toV1( NoGrePathMtuDiscovery types.Bool `tfsdk:"no_gre_path_mtu_discovery"` IpipPathMtuDiscovery types.Bool `tfsdk:"ipip_path_mtu_discovery"` NoIpipPathMtuDiscovery types.Bool `tfsdk:"no_ipip_path_mtu_discovery"` + IPv6DuplicateAddrDetectionTransmits types.Int64 `tfsdk:"ipv6_duplicate_addr_detection_transmits"` IPv6PathMtuDiscovery types.Bool `tfsdk:"ipv6_path_mtu_discovery"` NoIPv6PathMtuDiscovery types.Bool `tfsdk:"no_ipv6_path_mtu_discovery"` + IPv6PathMtuDiscoveryTimeout types.Int64 `tfsdk:"ipv6_path_mtu_discovery_timeout"` IPv6RejectZeroHopLimit types.Bool `tfsdk:"ipv6_reject_zero_hop_limit"` NoIPv6RejectZeroHopLimit types.Bool `tfsdk:"no_ipv6_reject_zero_hop_limit"` + NoTCPReset types.String `tfsdk:"no_tcp_reset"` NoTCPRFC1323 types.Bool `tfsdk:"no_tcp_rfc1323"` NoTCPRFC1323Paws types.Bool `tfsdk:"no_tcp_rfc1323_paws"` PathMtuDiscovery types.Bool `tfsdk:"path_mtu_discovery"` NoPathMtuDiscovery types.Bool `tfsdk:"no_path_mtu_discovery"` + SourcePortUpperLimit types.Int64 `tfsdk:"source_port_upper_limit"` SourceQuench types.Bool `tfsdk:"source_quench"` NoSourceQuench types.Bool `tfsdk:"no_source_quench"` TCPDropSynfinSet types.Bool `tfsdk:"tcp_drop_synfin_set"` - IPv6DuplicateAddrDetectionTransmits types.Int64 `tfsdk:"ipv6_duplicate_addr_detection_transmits"` - IPv6PathMtuDiscoveryTimeout types.Int64 `tfsdk:"ipv6_path_mtu_discovery_timeout"` - NoTCPReset types.String `tfsdk:"no_tcp_reset"` - SourcePortUpperLimit types.Int64 `tfsdk:"source_port_upper_limit"` TCPMss types.Int64 `tfsdk:"tcp_mss"` IcmpV4RateLimit []struct { BucketSize types.Int64 `tfsdk:"bucket_size"` @@ -744,24 +744,24 @@ func upgradeSystemV0toV1( } `tfsdk:"retry_options"` } `tfsdk:"login"` Ntp []struct { - BroadcastClient types.Bool `tfsdk:"broadcast_client"` - MulticastClient types.Bool `tfsdk:"multicast_client"` BootServer types.String `tfsdk:"boot_server"` + BroadcastClient types.Bool `tfsdk:"broadcast_client"` IntervalRange types.Int64 `tfsdk:"interval_range"` + MulticastClient types.Bool `tfsdk:"multicast_client"` MulticastClientAddress types.String `tfsdk:"multicast_client_address"` ThresholdAction types.String `tfsdk:"threshold_action"` ThresholdValue types.Int64 `tfsdk:"threshold_value"` } `tfsdk:"ntp"` Ports []struct { + AuxiliaryAuthenticationOrder []types.String `tfsdk:"auxiliary_authentication_order"` AuxiliaryDisable types.Bool `tfsdk:"auxiliary_disable"` AuxiliaryInsecure types.Bool `tfsdk:"auxiliary_insecure"` AuxiliaryLogoutOnDisconnect types.Bool `tfsdk:"auxiliary_logout_on_disconnect"` + AuxiliaryType types.String `tfsdk:"auxiliary_type"` + ConsoleAuthenticationOrder []types.String `tfsdk:"console_authentication_order"` ConsoleDisable types.Bool `tfsdk:"console_disable"` ConsoleInsecure types.Bool `tfsdk:"console_insecure"` ConsoleLogoutOnDisconnect types.Bool `tfsdk:"console_logout_on_disconnect"` - AuxiliaryAuthenticationOrder []types.String `tfsdk:"auxiliary_authentication_order"` - AuxiliaryType types.String `tfsdk:"auxiliary_type"` - ConsoleAuthenticationOrder []types.String `tfsdk:"console_authentication_order"` ConsoleType types.String `tfsdk:"console_type"` } `tfsdk:"ports"` Services []struct { @@ -772,22 +772,17 @@ func upgradeSystemV0toV1( RateLimit types.Int64 `tfsdk:"rate_limit"` } `tfsdk:"netconf_ssh"` NetconfTraceoptions []struct { - FileWorldReadable types.Bool `tfsdk:"file_world_readable"` - FileNoWorldReadable types.Bool `tfsdk:"file_no_world_readable"` - NoRemoteTrace types.Bool `tfsdk:"no_remote_trace"` - OnDemand types.Bool `tfsdk:"on_demand"` FileName types.String `tfsdk:"file_name"` FileFiles types.Int64 `tfsdk:"file_files"` FileMatch types.String `tfsdk:"file_match"` FileSize types.Int64 `tfsdk:"file_size"` + FileWorldReadable types.Bool `tfsdk:"file_world_readable"` + FileNoWorldReadable types.Bool `tfsdk:"file_no_world_readable"` Flag []types.String `tfsdk:"flag"` + NoRemoteTrace types.Bool `tfsdk:"no_remote_trace"` + OnDemand types.Bool `tfsdk:"on_demand"` } `tfsdk:"netconf_traceoptions"` SSH []struct { - LogKeyChanges types.Bool `tfsdk:"log_key_changes"` - NoPasswords types.Bool `tfsdk:"no_passwords"` - NoPublicKeys types.Bool `tfsdk:"no_public_keys"` - TCPForwarding types.Bool `tfsdk:"tcp_forwarding"` - NoTCPForwarding types.Bool `tfsdk:"no_tcp_forwarding"` AuthenticationOrder []types.String `tfsdk:"authentication_order"` Ciphers []types.String `tfsdk:"ciphers"` ClientAliveCountMax types.Int64 `tfsdk:"client_alive_count_max"` @@ -796,38 +791,43 @@ func upgradeSystemV0toV1( FingerprintHash types.String `tfsdk:"fingerprint_hash"` HostkeyAlgorithm []types.String `tfsdk:"hostkey_algorithm"` KeyExchange []types.String `tfsdk:"key_exchange"` + LogKeyChanges types.Bool `tfsdk:"log_key_changes"` Macs []types.String `tfsdk:"macs"` MaxPreAuthenticationPackets types.Int64 `tfsdk:"max_pre_authentication_packets"` MaxSessionsPerConnection types.Int64 `tfsdk:"max_sessions_per_connection"` + NoPasswords types.Bool `tfsdk:"no_passwords"` + NoPublicKeys types.Bool `tfsdk:"no_public_keys"` Port types.Int64 `tfsdk:"port"` ProtocolVersion []types.String `tfsdk:"protocol_version"` RateLimit types.Int64 `tfsdk:"rate_limit"` RootLogin types.String `tfsdk:"root_login"` + TCPForwarding types.Bool `tfsdk:"tcp_forwarding"` + NoTCPForwarding types.Bool `tfsdk:"no_tcp_forwarding"` } `tfsdk:"ssh"` WebManagementHTTP []struct { Interface []types.String `tfsdk:"interface"` Port types.Int64 `tfsdk:"port"` } `tfsdk:"web_management_http"` WebManagementHTTPS []struct { - SystemGeneratedCertificate types.Bool `tfsdk:"system_generated_certificate"` Interface []types.String `tfsdk:"interface"` LocalCertificate types.String `tfsdk:"local_certificate"` PkiLocalCertificate types.String `tfsdk:"pki_local_certificate"` Port types.Int64 `tfsdk:"port"` + SystemGeneratedCertificate types.Bool `tfsdk:"system_generated_certificate"` } `tfsdk:"web_management_https"` } `tfsdk:"services"` Syslog []struct { - TimeFormatMillisecond types.Bool `tfsdk:"time_format_millisecond"` - TimeFormatYear types.Bool `tfsdk:"time_format_year"` LogRotateFrequency types.Int64 `tfsdk:"log_rotate_frequency"` SourceAddress types.String `tfsdk:"source_address"` + TimeFormatMillisecond types.Bool `tfsdk:"time_format_millisecond"` + TimeFormatYear types.Bool `tfsdk:"time_format_year"` Archive []struct { BinaryData types.Bool `tfsdk:"binary_data"` NoBinaryData types.Bool `tfsdk:"no_binary_data"` - WorldReadable types.Bool `tfsdk:"world_readable"` - NoWorldReadable types.Bool `tfsdk:"no_world_readable"` Files types.Int64 `tfsdk:"files"` Size types.Int64 `tfsdk:"size"` + WorldReadable types.Bool `tfsdk:"world_readable"` + NoWorldReadable types.Bool `tfsdk:"no_world_readable"` } `tfsdk:"archive"` Console []struct { AnySeverity types.String `tfsdk:"any_severity"` diff --git a/internal/providerfwk/upgradestate_system_syslog_file.go b/internal/providerfwk/upgradestate_system_syslog_file.go index 85e8d3ba..2c76eed8 100644 --- a/internal/providerfwk/upgradestate_system_syslog_file.go +++ b/internal/providerfwk/upgradestate_system_syslog_file.go @@ -147,10 +147,10 @@ func upgradeSystemSyslogFileV0toV1( ctx context.Context, req resource.UpgradeStateRequest, resp *resource.UpgradeStateResponse, ) { type modelV0 struct { - AllowDuplicates types.Bool `tfsdk:"allow_duplicates"` - ExplicitPriority types.Bool `tfsdk:"explicit_priority"` ID types.String `tfsdk:"id"` Filename types.String `tfsdk:"filename"` + AllowDuplicates types.Bool `tfsdk:"allow_duplicates"` + ExplicitPriority types.Bool `tfsdk:"explicit_priority"` Match types.String `tfsdk:"match"` MatchStrings []types.String `tfsdk:"match_strings"` AnySeverity types.String `tfsdk:"any_severity"` @@ -171,12 +171,12 @@ func upgradeSystemSyslogFileV0toV1( Archive []struct { BinaryData types.Bool `tfsdk:"binary_data"` NoBinaryData types.Bool `tfsdk:"no_binary_data"` - WorldReadable types.Bool `tfsdk:"world_readable"` - NoWorldReadable types.Bool `tfsdk:"no_world_readable"` Files types.Int64 `tfsdk:"files"` Size types.Int64 `tfsdk:"size"` StartTime types.String `tfsdk:"start_time"` TransferInterval types.Int64 `tfsdk:"transfer_interval"` + WorldReadable types.Bool `tfsdk:"world_readable"` + NoWorldReadable types.Bool `tfsdk:"no_world_readable"` Sites []struct { URL types.String `tfsdk:"url"` Password types.String `tfsdk:"password"` diff --git a/internal/providerfwk/upgradestate_system_syslog_host.go b/internal/providerfwk/upgradestate_system_syslog_host.go index dcb7a946..5d5bd4df 100644 --- a/internal/providerfwk/upgradestate_system_syslog_host.go +++ b/internal/providerfwk/upgradestate_system_syslog_host.go @@ -114,11 +114,11 @@ func upgradeSystemSyslogHostV0toV1( ctx context.Context, req resource.UpgradeStateRequest, resp *resource.UpgradeStateResponse, ) { type modelV0 struct { + ID types.String `tfsdk:"id"` + Host types.String `tfsdk:"host"` AllowDuplicates types.Bool `tfsdk:"allow_duplicates"` ExcludeHostname types.Bool `tfsdk:"exclude_hostname"` ExplicitPriority types.Bool `tfsdk:"explicit_priority"` - ID types.String `tfsdk:"id"` - Host types.String `tfsdk:"host"` FacilityOverride types.String `tfsdk:"facility_override"` LogPrefix types.String `tfsdk:"log_prefix"` Match types.String `tfsdk:"match"` From 712c17c9ca2c89b9966a486abbe7b67f1decad82 Mon Sep 17 00:00:00 2001 From: Jeremy Muriel Date: Mon, 25 Mar 2024 09:29:49 +0100 Subject: [PATCH 03/25] tests: add additional rules with revive linter and fix errors from import-shadowing and unhandled-error rules --- .golangci.yml | 31 +++++++++++++++++++ internal/junos/session.go | 2 +- internal/tfdata/check_asblock.go | 8 ++--- internal/tfvalidator/string_rune_exclusion.go | 6 ++-- 4 files changed, 39 insertions(+), 8 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 2d942ac0..08d126ad 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -60,6 +60,37 @@ linters-settings: disable: - fieldalignment - shadow + revive: + rules: + # defaults + - name: blank-imports + - name: context-as-argument + - name: context-keys-type + - name: dot-imports + - name: empty-block + - name: error-naming + - name: error-return + - name: error-strings + - name: errorf + - name: exported + - name: increment-decrement + - name: indent-error-flow + - name: package-comments + - name: range + - name: receiver-naming + - name: redefines-builtin-id + - name: superfluous-else + - name: time-naming + - name: unexported-return + - name: unreachable-code + - name: unused-parameter + - name: var-declaration + - name: var-naming + # additionals + - name: confusing-naming + - name: import-alias-naming + - name: import-shadowing + - name: unhandled-error issues: exclude-rules: - text: "github.com/jeremmfr/terraform-provider-junos/internal" diff --git a/internal/junos/session.go b/internal/junos/session.go index dfc13711..5f4762d3 100644 --- a/internal/junos/session.go +++ b/internal/junos/session.go @@ -113,7 +113,7 @@ toretry: } s, err := netconf.NewSSHSession(conn, sshOpts.ClientConfig) if err != nil { - conn.Close() + _ = conn.Close() select { case <-ctx.Done(): return nil, fmt.Errorf("initializing SSH session to %s: %w", host, err) diff --git a/internal/tfdata/check_asblock.go b/internal/tfdata/check_asblock.go index cd4b815d..2f249492 100644 --- a/internal/tfdata/check_asblock.go +++ b/internal/tfdata/check_asblock.go @@ -25,8 +25,8 @@ func CheckBlockIsEmpty[B any](block B, excludeFields ...string) bool { continue } - if attr, ok := fieldValue.Interface().(attr.Value); ok { - if !attr.IsNull() { + if attrValue, ok := fieldValue.Interface().(attr.Value); ok { + if !attrValue.IsNull() { return false } @@ -72,8 +72,8 @@ func CheckBlockHasKnownValue[B any](block B, excludeFields ...string) bool { continue } - if attr, ok := fieldValue.Interface().(attr.Value); ok { - if !attr.IsNull() && !attr.IsUnknown() { + if attrValue, ok := fieldValue.Interface().(attr.Value); ok { + if !attrValue.IsNull() && !attrValue.IsUnknown() { return true } diff --git a/internal/tfvalidator/string_rune_exclusion.go b/internal/tfvalidator/string_rune_exclusion.go index 248d19ae..f0b52ef1 100644 --- a/internal/tfvalidator/string_rune_exclusion.go +++ b/internal/tfvalidator/string_rune_exclusion.go @@ -19,10 +19,10 @@ type StringRuneExclusionValidator struct { } func StringRuneExclusion(runes ...rune) StringRuneExclusionValidator { - var validator StringRuneExclusionValidator - validator.runes = append(validator.runes, runes...) + var v StringRuneExclusionValidator + v.runes = append(v.runes, runes...) - return validator + return v } func StringDoubleQuoteExclusion() StringRuneExclusionValidator { From ad74734aaf44cb012ac728346f64afd4ae914199 Mon Sep 17 00:00:00 2001 From: Jeremy Muriel Date: Tue, 26 Mar 2024 09:02:37 +0100 Subject: [PATCH 04/25] r/iccp_peer, r/oam_gretunnel_interface: fix junos name avoid the word 'protocol' --- docs/resources/oam_gretunnel_interface.md | 4 ++-- internal/providerfwk/resource_iccp_peer.go | 2 +- internal/providerfwk/resource_oam_gretunnel_interface.go | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/resources/oam_gretunnel_interface.md b/docs/resources/oam_gretunnel_interface.md index 1ebd2c85..a70ecfa4 100644 --- a/docs/resources/oam_gretunnel_interface.md +++ b/docs/resources/oam_gretunnel_interface.md @@ -4,12 +4,12 @@ page_title: "Junos: junos_oam_gretunnel_interface" # junos_oam_gretunnel_interface -Provides a protocol oam gre-tunnel interface resource. +Provides a oam gre-tunnel interface resource. ## Example Usage ```hcl -# Add protocol oam gre-tunnel interface +# Add oam gre-tunnel interface resource "junos_oam_gretunnel_interface" "gr1" { name = "gr-1/1/10.1" hold_time = 30 diff --git a/internal/providerfwk/resource_iccp_peer.go b/internal/providerfwk/resource_iccp_peer.go index cdcb3606..c00a9be4 100644 --- a/internal/providerfwk/resource_iccp_peer.go +++ b/internal/providerfwk/resource_iccp_peer.go @@ -45,7 +45,7 @@ func (rsc *iccpPeer) typeName() string { } func (rsc *iccpPeer) junosName() string { - return "protocols iccp peer" + return "iccp peer" } func (rsc *iccpPeer) junosClient() *junos.Client { diff --git a/internal/providerfwk/resource_oam_gretunnel_interface.go b/internal/providerfwk/resource_oam_gretunnel_interface.go index 2a75422f..97d1c64e 100644 --- a/internal/providerfwk/resource_oam_gretunnel_interface.go +++ b/internal/providerfwk/resource_oam_gretunnel_interface.go @@ -44,7 +44,7 @@ func (rsc *oamGretunnelInterface) typeName() string { } func (rsc *oamGretunnelInterface) junosName() string { - return "protocol oam gre-tunnel interface" + return "oam gre-tunnel interface" } func (rsc *oamGretunnelInterface) junosClient() *junos.Client { From 88c0ba2d62b9266b171e39fb055af7b12a6bd1e7 Mon Sep 17 00:00:00 2001 From: Jeremy Muriel Date: Tue, 26 Mar 2024 09:04:41 +0100 Subject: [PATCH 05/25] r/bridge_domain, r/forwardingoptions_sampling_instance: fix errors when create with no default routing-instance --- .../providerfwk/resource_bridge_domain.go | 30 ++++++++++++++----- ...rce_forwardingoptions_sampling_instance.go | 30 ++++++++++++++----- 2 files changed, 44 insertions(+), 16 deletions(-) diff --git a/internal/providerfwk/resource_bridge_domain.go b/internal/providerfwk/resource_bridge_domain.go index 8580cc63..9ef51235 100644 --- a/internal/providerfwk/resource_bridge_domain.go +++ b/internal/providerfwk/resource_bridge_domain.go @@ -422,10 +422,17 @@ func (rsc *bridgeDomain) Create( return false } if domainExists { - resp.Diagnostics.AddError( - tfdiag.DuplicateConfigErrSummary, - defaultResourceAlreadyExistsMessage(rsc, plan.Name), - ) + if v := plan.RoutingInstance.ValueString(); v != "" && v != junos.DefaultW { + resp.Diagnostics.AddError( + tfdiag.DuplicateConfigErrSummary, + defaultResourceAlreadyExistsInRoutingInstanceMessage(rsc, plan.Name, v), + ) + } else { + resp.Diagnostics.AddError( + tfdiag.DuplicateConfigErrSummary, + defaultResourceAlreadyExistsMessage(rsc, plan.Name), + ) + } return false } @@ -445,10 +452,17 @@ func (rsc *bridgeDomain) Create( return false } if !domainExists { - resp.Diagnostics.AddError( - tfdiag.NotFoundErrSummary, - defaultResourceDoesNotExistsAfterCommitMessage(rsc, plan.Name), - ) + if v := plan.RoutingInstance.ValueString(); v != "" && v != junos.DefaultW { + resp.Diagnostics.AddError( + tfdiag.NotFoundErrSummary, + defaultResourceDoesNotExistsInRoutingInstanceAfterCommitMessage(rsc, plan.Name, v), + ) + } else { + resp.Diagnostics.AddError( + tfdiag.NotFoundErrSummary, + defaultResourceDoesNotExistsAfterCommitMessage(rsc, plan.Name), + ) + } return false } diff --git a/internal/providerfwk/resource_forwardingoptions_sampling_instance.go b/internal/providerfwk/resource_forwardingoptions_sampling_instance.go index 442b6a94..a48a0004 100644 --- a/internal/providerfwk/resource_forwardingoptions_sampling_instance.go +++ b/internal/providerfwk/resource_forwardingoptions_sampling_instance.go @@ -1133,10 +1133,17 @@ func (rsc *forwardingoptionsSamplingInstance) Create( return false } if instanceExists { - resp.Diagnostics.AddError( - tfdiag.DuplicateConfigErrSummary, - defaultResourceAlreadyExistsMessage(rsc, plan.Name), - ) + if v := plan.RoutingInstance.ValueString(); v != "" && v != junos.DefaultW { + resp.Diagnostics.AddError( + tfdiag.DuplicateConfigErrSummary, + defaultResourceAlreadyExistsInRoutingInstanceMessage(rsc, plan.Name, v), + ) + } else { + resp.Diagnostics.AddError( + tfdiag.DuplicateConfigErrSummary, + defaultResourceAlreadyExistsMessage(rsc, plan.Name), + ) + } return false } @@ -1156,10 +1163,17 @@ func (rsc *forwardingoptionsSamplingInstance) Create( return false } if !instanceExists { - resp.Diagnostics.AddError( - tfdiag.NotFoundErrSummary, - defaultResourceDoesNotExistsAfterCommitMessage(rsc, plan.Name), - ) + if v := plan.RoutingInstance.ValueString(); v != "" && v != junos.DefaultW { + resp.Diagnostics.AddError( + tfdiag.NotFoundErrSummary, + defaultResourceDoesNotExistsInRoutingInstanceAfterCommitMessage(rsc, plan.Name, v), + ) + } else { + resp.Diagnostics.AddError( + tfdiag.NotFoundErrSummary, + defaultResourceDoesNotExistsAfterCommitMessage(rsc, plan.Name), + ) + } return false } From f29ce2fd38f87ea3b27a3f042512dd73d0509772 Mon Sep 17 00:00:00 2001 From: Jeremy Muriel Date: Tue, 26 Mar 2024 09:21:52 +0100 Subject: [PATCH 06/25] r/firewall_filter: reduce useless big capacity of slice --- internal/providerfwk/resource_firewall_filter.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/providerfwk/resource_firewall_filter.go b/internal/providerfwk/resource_firewall_filter.go index efae953b..0e613b2f 100644 --- a/internal/providerfwk/resource_firewall_filter.go +++ b/internal/providerfwk/resource_firewall_filter.go @@ -1944,7 +1944,7 @@ func (block *firewallFilterBlockTermBlockFrom) configSet( } func (block *firewallFilterBlockTermBlockThen) configSet(setPrefix string) []string { - configSet := make([]string, 0, 100) + configSet := make([]string, 0, 1) setPrefix += "then " if v := block.Action.ValueString(); v != "" { From 62ffa5a32d3fd85479379d06f161a69f5c1de480 Mon Sep 17 00:00:00 2001 From: Jeremy Muriel Date: Mon, 1 Apr 2024 16:12:08 +0200 Subject: [PATCH 07/25] r/ospf_area: use new provider via framework --- .changes/ospf-with-fwk.md | 12 + docs/resources/ospf_area.md | 55 +- internal/providerfwk/provider.go | 1 + internal/providerfwk/resource_ospf_area.go | 2738 +++++++++++++++++ .../providerfwk/resource_ospf_area_test.go | 172 ++ .../TestAccResourceOspfArea_basic/1/main.tf | 34 + .../1/variables.tf | 3 + .../TestAccResourceOspfArea_basic/10/main.tf | 86 + .../10/variables.tf | 3 + .../TestAccResourceOspfArea_basic/2/main.tf | 150 + .../2/variables.tf | 7 + .../TestAccResourceOspfArea_basic/7/main.tf | 12 + .../TestAccResourceOspfArea_basic/8/main.tf | 25 + .../TestAccResourceOspfArea_basic/9/main.tf | 39 + .../9/variables.tf | 3 + .../1/main.tf | 150 + .../1/provider.tf | 10 + .../1/variables.tf | 7 + .../2/main.tf | 1 + .../2/variables.tf | 1 + .../providerfwk/upgradestate_ospf_area.go | 647 ++++ .../upgradestate_ospf_area_test.go | 49 + internal/providersdk/func_common.go | 23 - internal/providersdk/provider.go | 11 +- internal/providersdk/resource_ospf_area.go | 1909 ------------ .../providersdk/resource_ospf_area_test.go | 498 --- 26 files changed, 4185 insertions(+), 2461 deletions(-) create mode 100644 .changes/ospf-with-fwk.md create mode 100644 internal/providerfwk/resource_ospf_area.go create mode 100644 internal/providerfwk/resource_ospf_area_test.go create mode 100644 internal/providerfwk/testdata/TestAccResourceOspfArea_basic/1/main.tf create mode 100644 internal/providerfwk/testdata/TestAccResourceOspfArea_basic/1/variables.tf create mode 100644 internal/providerfwk/testdata/TestAccResourceOspfArea_basic/10/main.tf create mode 100644 internal/providerfwk/testdata/TestAccResourceOspfArea_basic/10/variables.tf create mode 100644 internal/providerfwk/testdata/TestAccResourceOspfArea_basic/2/main.tf create mode 100644 internal/providerfwk/testdata/TestAccResourceOspfArea_basic/2/variables.tf create mode 100644 internal/providerfwk/testdata/TestAccResourceOspfArea_basic/7/main.tf create mode 100644 internal/providerfwk/testdata/TestAccResourceOspfArea_basic/8/main.tf create mode 100644 internal/providerfwk/testdata/TestAccResourceOspfArea_basic/9/main.tf create mode 100644 internal/providerfwk/testdata/TestAccResourceOspfArea_basic/9/variables.tf create mode 100644 internal/providerfwk/testdata/TestAccUpgradeStateResourceOspfArea_V0toV1_basic/1/main.tf create mode 100644 internal/providerfwk/testdata/TestAccUpgradeStateResourceOspfArea_V0toV1_basic/1/provider.tf create mode 100644 internal/providerfwk/testdata/TestAccUpgradeStateResourceOspfArea_V0toV1_basic/1/variables.tf create mode 120000 internal/providerfwk/testdata/TestAccUpgradeStateResourceOspfArea_V0toV1_basic/2/main.tf create mode 120000 internal/providerfwk/testdata/TestAccUpgradeStateResourceOspfArea_V0toV1_basic/2/variables.tf create mode 100644 internal/providerfwk/upgradestate_ospf_area.go create mode 100644 internal/providerfwk/upgradestate_ospf_area_test.go delete mode 100644 internal/providersdk/resource_ospf_area.go delete mode 100644 internal/providersdk/resource_ospf_area_test.go diff --git a/.changes/ospf-with-fwk.md b/.changes/ospf-with-fwk.md new file mode 100644 index 00000000..12b348f6 --- /dev/null +++ b/.changes/ospf-with-fwk.md @@ -0,0 +1,12 @@ + +FEATURES: + +ENHANCEMENTS: + +* **resource/junos_ospf_area**: resource now use new [terraform-plugin-framework](https://github.com/hashicorp/terraform-plugin-framework) + some of config errors are now sent during Plan instead of during Apply + optional boolean attributes doesn't accept value *false* + optional string attributes doesn't accept *empty* value + the resource schema has been upgraded to have one-blocks in single mode instead of list + +BUG FIXES: diff --git a/docs/resources/ospf_area.md b/docs/resources/ospf_area.md index 872c980b..1c5acaee 100644 --- a/docs/resources/ospf_area.md +++ b/docs/resources/ospf_area.md @@ -25,19 +25,19 @@ resource "junos_ospf_area" "demo_area" { The following arguments are supported: - **area_id** (Required, String, Forces new resource) - The id of ospf area. -- **routing_instance** (Optional, String, Forces new resource) - Routing instance for area. - Need to be `default` or name of routing instance. - Defaults to `default`. -- **realm** (Optional, String, Forces new resource) - OSPFv3 realm configuration. - Need to be `ipv4-unicast`, `ipv4-multicast` or `ipv6-multicast`. - `version` need to be `v3`. + Area ID. - **version** (Optional, String, Forces new resource) Version of ospf. Need to be `v2` or `v3`. Defaults to `v2`. +- **realm** (Optional, String, Forces new resource) + OSPFv3 realm configuration. + Need to be `ipv4-unicast`, `ipv4-multicast` or `ipv6-multicast`. + `version` need to be `v3`. +- **routing_instance** (Optional, String, Forces new resource) + Routing instance for ospf area. + Need to be `default` or name of routing instance. + Defaults to `default`. - **interface** (Required, Block List) For each interface or interface-range to declare. - **name** (Required, String) @@ -68,7 +68,8 @@ The following arguments are supported: - **hello_interval** (Optional, Number) Hello interval (seconds). - **interface_type** (Optional, String) - Type of interface. + Type of interface. + Need to be `nbma`, `p2mp`, `p2mp-over-lan` or `p2p`. - **ipsec_sa** (Optional, String) IPSec security association name. - **ipv4_adjacency_segment_protected_type** (Optional, String) @@ -117,11 +118,11 @@ The following arguments are supported: - **secondary** (Optional, Boolean) Treat interface as secondary. - **strict_bfd** (Optional, Boolean) - Enable strict bfd over this interface + Enable strict bfd over this interface. - **te_metric** (Optional, Number) Traffic engineering metric (1..4294967295). - **transit_delay** (Optional, Number) - Transit delay (seconds) (1..65535). + Transit delay (1..65535 seconds). - **area_range** (Optional, Block Set) For each `range`, configure area range. See [below for nested schema](#area_range-arguments). @@ -129,15 +130,19 @@ The following arguments are supported: Configure context identifier in support of edge protection. Conflict with `no_context_identifier_advertisement`. - **inter_area_prefix_export** (Optional, List of String) - Export policy for Inter Area Prefix LSAs. + Export policy for Inter Area Prefix LSAs. + `version` need to be `v3`. - **inter_area_prefix_import** (Optional, List of String) - Import policy for Inter Area Prefix LSAs. + Import policy for Inter Area Prefix LSAs. + `version` need to be `v3`. - **network_summary_export** (Optional, List of String) - Export policy for Type 3 Summary LSAs. + Export policy for Type 3 Summary LSAs. + `version` need to be `v2`. - **network_summary_import** (Optional, List of String) - Import policy for Type 3 Summary LSAs. + Import policy for Type 3 Summary LSAs. + `version` need to be `v2`. - **no_context_identifier_advertisement** (Optional, Boolean) - Disable context identifier advertisments in this area. + Disable context identifier advertisements in this area. Conflict with `context_identifier`. - **nssa** (Optional, Block) Configure a not-so-stubby area. @@ -148,19 +153,19 @@ The following arguments are supported: - **default_lsa** (Optional, Block) Configure a default LSA. See [below for nested schema](#default_lsa-arguments-for-nssa). - - **no_summaries** (Optional, Boolean) - Don't flood summary LSAs into this NSSA area. - **summaries** (Optional, Boolean) Flood summary LSAs into this NSSA area. + - **no_summaries** (Optional, Boolean) + Don't flood summary LSAs into this NSSA area. - **stub** (Optional, Block) Configure a stub area. Conflict with `nssa`. - **default_metric** (Optional, Number) Metric for the default route in this stub area (1..16777215). - - **no_summaries** (Optional, Boolean) - Don't flood summary LSAs into this stub area. - **summaries** (Optional, Boolean) Flood summary LSAs into this stub area. + - **no_summaries** (Optional, Boolean) + Don't flood summary LSAs into this stub area. - **virtual_link** (Optional, Block Set) For each combination of `neighbor_id` and `transit_area`, configure virtual link. - **neighbor_id** (Required, String) @@ -170,7 +175,7 @@ The following arguments are supported: Transit area in common with virtual neighbor. Need to be in IPv4 format. - **dead_interval** (Optional, Number) - Dead interval (seconds) (1..65535). + Dead interval (1..65535 seconds). - **demand_circuit** (Optional, Boolean) Interface functions as a demand circuit. - **disable** (Optional, Boolean) @@ -178,15 +183,15 @@ The following arguments are supported: - **flood_reduction** (Optional, Boolean) Enable flood reduction. - **hello_interval** (Optional, Number) - Hello interval (seconds) (1..255). + Hello interval (1..255 seconds). - **ipsec_sa** (Optional, String) IPSec security association name. - **mtu** (Optional, Number) Maximum OSPF packet size (128..65535). - **retransmit_interval** (Optional, Number) - Retransmission interval (seconds) (1..65535). + Retransmission interval (1..65535 seconds). - **transit_delay** (Optional, Number) - Transit delay (seconds) (1..65535). + Transit delay (1..65535 seconds). --- diff --git a/internal/providerfwk/provider.go b/internal/providerfwk/provider.go index 19c77350..2069cf31 100644 --- a/internal/providerfwk/provider.go +++ b/internal/providerfwk/provider.go @@ -252,6 +252,7 @@ func (p *junosProvider) Resources(_ context.Context) []func() resource.Resource newMultichassisResource, newMultichassisProtectionPeerResource, newOamGretunnelInterfaceResource, + newOspfAreaResource, newPolicyoptionsASPathResource, newPolicyoptionsASPathGroupResource, newPolicyoptionsCommunityResource, diff --git a/internal/providerfwk/resource_ospf_area.go b/internal/providerfwk/resource_ospf_area.go new file mode 100644 index 00000000..c004a06f --- /dev/null +++ b/internal/providerfwk/resource_ospf_area.go @@ -0,0 +1,2738 @@ +package providerfwk + +import ( + "context" + "errors" + "fmt" + "regexp" + "strings" + + "github.com/jeremmfr/terraform-provider-junos/internal/junos" + "github.com/jeremmfr/terraform-provider-junos/internal/tfdata" + "github.com/jeremmfr/terraform-provider-junos/internal/tfdiag" + "github.com/jeremmfr/terraform-provider-junos/internal/tfplanmodifier" + "github.com/jeremmfr/terraform-provider-junos/internal/tfvalidator" + "github.com/jeremmfr/terraform-provider-junos/internal/utils" + + "github.com/hashicorp/terraform-plugin-framework-validators/int64validator" + "github.com/hashicorp/terraform-plugin-framework-validators/listvalidator" + "github.com/hashicorp/terraform-plugin-framework-validators/setvalidator" + "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/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" + balt "github.com/jeremmfr/go-utils/basicalter" +) + +// Ensure the implementation satisfies the expected interfaces. +var ( + _ resource.Resource = &ospfArea{} + _ resource.ResourceWithConfigure = &ospfArea{} + _ resource.ResourceWithValidateConfig = &ospfArea{} + _ resource.ResourceWithImportState = &ospfArea{} + _ resource.ResourceWithUpgradeState = &ospfArea{} +) + +type ospfArea struct { + client *junos.Client +} + +func newOspfAreaResource() resource.Resource { + return &ospfArea{} +} + +func (rsc *ospfArea) typeName() string { + return providerName + "_ospf_area" +} + +func (rsc *ospfArea) junosName() string { + return "ospf|ospf3 area" +} + +func (rsc *ospfArea) junosClient() *junos.Client { + return rsc.client +} + +func (rsc *ospfArea) Metadata( + _ context.Context, _ resource.MetadataRequest, resp *resource.MetadataResponse, +) { + resp.TypeName = rsc.typeName() +} + +func (rsc *ospfArea) Configure( + ctx context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse, +) { + // Prevent panic if the provider has not been configured. + if req.ProviderData == nil { + return + } + client, ok := req.ProviderData.(*junos.Client) + if !ok { + unexpectedResourceConfigureType(ctx, req, resp) + + return + } + rsc.client = client +} + +func (rsc *ospfArea) Schema( + _ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse, +) { + resp.Schema = schema.Schema{ + Version: 1, + Description: defaultResourceSchemaDescription(rsc), + Attributes: map[string]schema.Attribute{ + "id": schema.StringAttribute{ + Computed: true, + Description: "An identifier for the resource with format " + + "`" + junos.IDSeparator + "" + + junos.IDSeparator + "` or " + + "`" + junos.IDSeparator + "" + + junos.IDSeparator + "" + junos.IDSeparator + "`.", + PlanModifiers: []planmodifier.String{ + stringplanmodifier.UseStateForUnknown(), + }, + }, + "area_id": schema.StringAttribute{ + Required: true, + Description: "Area ID.", + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + }, + Validators: []validator.String{ + stringvalidator.Any( + tfvalidator.StringIPAddress().IPv4Only(), + stringvalidator.RegexMatches(regexp.MustCompile( + `^\d+$`), + "should be usually in the IP format (but a number is accepted)", + ), + ), + }, + }, + "version": schema.StringAttribute{ + Optional: true, + Computed: true, + Default: stringdefault.StaticString("v2"), + Description: "Version of ospf.", + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + }, + Validators: []validator.String{ + stringvalidator.OneOf("v2", "v3"), + }, + }, + "realm": schema.StringAttribute{ + Optional: true, + Description: "OSPFv3 realm configuration.", + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + }, + Validators: []validator.String{ + stringvalidator.OneOf("ipv4-unicast", "ipv4-multicast", "ipv6-multicast"), + }, + }, + "routing_instance": schema.StringAttribute{ + Optional: true, + Computed: true, + Default: stringdefault.StaticString(junos.DefaultW), + Description: "Routing instance for ospf area.", + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + }, + Validators: []validator.String{ + stringvalidator.LengthBetween(1, 63), + tfvalidator.StringFormat(tfvalidator.DefaultFormat), + }, + }, + "context_identifier": schema.SetAttribute{ + ElementType: types.StringType, + Optional: true, + Description: "Configure context identifier in support of edge protection.", + Validators: []validator.Set{ + setvalidator.SizeAtLeast(1), + setvalidator.ValueStringsAre( + tfvalidator.StringIPAddress().IPv4Only(), + ), + }, + }, + "inter_area_prefix_export": schema.ListAttribute{ + ElementType: types.StringType, + Optional: true, + Description: "Export policy for Inter Area Prefix LSAs.", + Validators: []validator.List{ + listvalidator.SizeAtLeast(1), + listvalidator.ValueStringsAre( + stringvalidator.LengthBetween(1, 250), + tfvalidator.StringDoubleQuoteExclusion(), + ), + }, + }, + "inter_area_prefix_import": schema.ListAttribute{ + ElementType: types.StringType, + Optional: true, + Description: "Import policy for Inter Area Prefix LSAs.", + Validators: []validator.List{ + listvalidator.SizeAtLeast(1), + listvalidator.ValueStringsAre( + stringvalidator.LengthBetween(1, 250), + tfvalidator.StringDoubleQuoteExclusion(), + ), + }, + }, + "network_summary_export": schema.ListAttribute{ + ElementType: types.StringType, + Optional: true, + Description: "Export policy for Type 3 Summary LSAs.", + Validators: []validator.List{ + listvalidator.SizeAtLeast(1), + listvalidator.ValueStringsAre( + stringvalidator.LengthBetween(1, 250), + tfvalidator.StringDoubleQuoteExclusion(), + ), + }, + }, + "network_summary_import": schema.ListAttribute{ + ElementType: types.StringType, + Optional: true, + Description: "Import policy for Type 3 Summary LSAs.", + Validators: []validator.List{ + listvalidator.SizeAtLeast(1), + listvalidator.ValueStringsAre( + stringvalidator.LengthBetween(1, 250), + tfvalidator.StringDoubleQuoteExclusion(), + ), + }, + }, + "no_context_identifier_advertisement": schema.BoolAttribute{ + Optional: true, + Description: "Disable context identifier advertisements in this area.", + Validators: []validator.Bool{ + tfvalidator.BoolTrue(), + }, + }, + }, + Blocks: map[string]schema.Block{ + "interface": schema.ListNestedBlock{ + Description: "For each interface or interface-range to declare.", + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "name": schema.StringAttribute{ + Required: true, + Description: "Name of interface or interface-range.", + Validators: []validator.String{ + stringvalidator.LengthAtLeast(1), + tfvalidator.StringFormat(tfvalidator.InterfaceFormat), + }, + }, + "authentication_simple_password": schema.StringAttribute{ + Optional: true, + Sensitive: true, + Description: "Authentication key.", + Validators: []validator.String{ + stringvalidator.LengthAtLeast(1), + tfvalidator.StringDoubleQuoteExclusion(), + }, + }, + "dead_interval": schema.Int64Attribute{ + Optional: true, + Description: "Dead interval (seconds).", + Validators: []validator.Int64{ + int64validator.Between(1, 65535), + }, + }, + "demand_circuit": schema.BoolAttribute{ + Optional: true, + Description: "Interface functions as a demand circuit.", + Validators: []validator.Bool{ + tfvalidator.BoolTrue(), + }, + }, + "disable": schema.BoolAttribute{ + Optional: true, + Description: "Disable OSPF on this interface.", + Validators: []validator.Bool{ + tfvalidator.BoolTrue(), + }, + }, + "dynamic_neighbors": schema.BoolAttribute{ + Optional: true, + Description: "Learn neighbors dynamically on a p2mp interface.", + Validators: []validator.Bool{ + tfvalidator.BoolTrue(), + }, + }, + "flood_reduction": schema.BoolAttribute{ + Optional: true, + Description: "Enable flood reduction.", + Validators: []validator.Bool{ + tfvalidator.BoolTrue(), + }, + }, + "hello_interval": schema.Int64Attribute{ + Optional: true, + Description: "Hello interval (seconds).", + Validators: []validator.Int64{ + int64validator.Between(1, 255), + }, + }, + "interface_type": schema.StringAttribute{ + Optional: true, + Description: "Type of interface.", + Validators: []validator.String{ + stringvalidator.OneOf("nbma", "p2mp", "p2mp-over-lan", "p2p"), + }, + }, + "ipsec_sa": schema.StringAttribute{ + Optional: true, + Description: "IPSec security association name.", + Validators: []validator.String{ + stringvalidator.LengthBetween(1, 32), + tfvalidator.StringDoubleQuoteExclusion(), + }, + }, + "ipv4_adjacency_segment_protected_type": schema.StringAttribute{ + Optional: true, + Description: "Type to define adjacency SID is eligible for protection.", + Validators: []validator.String{ + stringvalidator.OneOf("dynamic", "index", "label"), + }, + }, + "ipv4_adjacency_segment_protected_value": schema.StringAttribute{ + Optional: true, + Description: "Value for index or label to define adjacency SID is eligible for protection.", + Validators: []validator.String{ + stringvalidator.RegexMatches(regexp.MustCompile( + `^\d+$`), + "should be a numeric value", + ), + }, + }, + "ipv4_adjacency_segment_unprotected_type": schema.StringAttribute{ + Optional: true, + Description: "Type to define adjacency SID uneligible for protection.", + Validators: []validator.String{ + stringvalidator.OneOf("dynamic", "index", "label"), + }, + }, + "ipv4_adjacency_segment_unprotected_value": schema.StringAttribute{ + Optional: true, + Description: "Value for index or label to define adjacency SID uneligible for protection.", + Validators: []validator.String{ + stringvalidator.RegexMatches(regexp.MustCompile( + `^\d+$`), + "should be a numeric value", + ), + }, + }, + "link_protection": schema.BoolAttribute{ + Optional: true, + Description: "Protect interface from link faults only.", + Validators: []validator.Bool{ + tfvalidator.BoolTrue(), + }, + }, + "metric": schema.Int64Attribute{ + Optional: true, + Description: "Interface metric.", + Validators: []validator.Int64{ + int64validator.Between(1, 65535), + }, + }, + "mtu": schema.Int64Attribute{ + Optional: true, + Description: "Maximum OSPF packet size.", + Validators: []validator.Int64{ + int64validator.Between(128, 65535), + }, + }, + "no_advertise_adjacency_segment": schema.BoolAttribute{ + Optional: true, + Description: "Do not advertise an adjacency segment for this interface.", + Validators: []validator.Bool{ + tfvalidator.BoolTrue(), + }, + }, + "no_eligible_backup": schema.BoolAttribute{ + Optional: true, + Description: "Not eligible to backup traffic from protected interfaces.", + Validators: []validator.Bool{ + tfvalidator.BoolTrue(), + }, + }, + "no_eligible_remote_backup": schema.BoolAttribute{ + Optional: true, + Description: "Not eligible for Remote-LFA backup traffic from protected interfaces.", + Validators: []validator.Bool{ + tfvalidator.BoolTrue(), + }, + }, + "no_interface_state_traps": schema.BoolAttribute{ + Optional: true, + Description: "Do not send interface state change traps.", + Validators: []validator.Bool{ + tfvalidator.BoolTrue(), + }, + }, + "no_neighbor_down_notification": schema.BoolAttribute{ + Optional: true, + Description: "Don't inform other protocols about neighbor down events.", + Validators: []validator.Bool{ + tfvalidator.BoolTrue(), + }, + }, + "node_link_protection": schema.BoolAttribute{ + Optional: true, + Description: "Protect interface from both link and node faults.", + Validators: []validator.Bool{ + tfvalidator.BoolTrue(), + }, + }, + "passive": schema.BoolAttribute{ + Optional: true, + Description: "Do not run OSPF, but advertise it.", + Validators: []validator.Bool{ + tfvalidator.BoolTrue(), + }, + }, + "passive_traffic_engineering_remote_node_id": schema.StringAttribute{ + Optional: true, + Description: "Advertise TE link information, remote address of the link.", + Validators: []validator.String{ + tfvalidator.StringIPAddress(), + }, + }, + "passive_traffic_engineering_remote_node_router_id": schema.StringAttribute{ + Optional: true, + Description: "Advertise TE link information, TE Router-ID of the remote node.", + Validators: []validator.String{ + tfvalidator.StringIPAddress(), + }, + }, + "poll_interval": schema.Int64Attribute{ + Optional: true, + Description: "Poll interval for NBMA interfaces.", + Validators: []validator.Int64{ + int64validator.Between(1, 65535), + }, + }, + "priority": schema.Int64Attribute{ + Optional: true, + Description: "Designated router priority.", + Validators: []validator.Int64{ + int64validator.Between(0, 255), + }, + }, + "retransmit_interval": schema.Int64Attribute{ + Optional: true, + Description: "Retransmission interval (seconds).", + Validators: []validator.Int64{ + int64validator.Between(1, 65535), + }, + }, + "secondary": schema.BoolAttribute{ + Optional: true, + Description: "Treat interface as secondary.", + Validators: []validator.Bool{ + tfvalidator.BoolTrue(), + }, + }, + "strict_bfd": schema.BoolAttribute{ + Optional: true, + Description: "Enable strict bfd over this interface.", + Validators: []validator.Bool{ + tfvalidator.BoolTrue(), + }, + }, + "te_metric": schema.Int64Attribute{ + Optional: true, + Description: "Traffic engineering metric.", + Validators: []validator.Int64{ + int64validator.Between(1, 4294967295), + }, + }, + "transit_delay": schema.Int64Attribute{ + Optional: true, + Description: "Transit delay (seconds).", + Validators: []validator.Int64{ + int64validator.Between(1, 65535), + }, + }, + }, + Blocks: map[string]schema.Block{ + "authentication_md5": schema.ListNestedBlock{ + Description: "For each key_id, MD5 authentication key.", + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "key_id": schema.Int64Attribute{ + Required: true, + Description: "Key ID for MD5 authentication.", + Validators: []validator.Int64{ + int64validator.Between(0, 255), + }, + }, + "key": schema.StringAttribute{ + Required: true, + Sensitive: true, + Description: "MD5 authentication key value.", + Validators: []validator.String{ + stringvalidator.LengthAtLeast(1), + tfvalidator.StringDoubleQuoteExclusion(), + }, + }, + "start_time": schema.StringAttribute{ + Optional: true, + Description: "Start time for key transmission.", + Validators: []validator.String{ + stringvalidator.RegexMatches(regexp.MustCompile( + `^\d{4}\-\d\d?\-\d\d?\.\d{2}:\d{2}:\d{2}$`), + "must be in the format 'YYYY-MM-DD.HH:MM:SS'", + ), + }, + }, + }, + }, + }, + "bandwidth_based_metrics": schema.SetNestedBlock{ + Description: "For each bandwidth, configure bandwidth based metrics.", + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "bandwidth": schema.StringAttribute{ + Required: true, + Description: "Bandwidth threshold.", + Validators: []validator.String{ + stringvalidator.RegexMatches(regexp.MustCompile( + `^(\d)+(m|k|g)?$`), + `must be a bandwidth ^(\d)+(m|k|g)?$`), + }, + }, + "metric": schema.Int64Attribute{ + Required: true, + Description: "Metric associated with specified bandwidth.", + Validators: []validator.Int64{ + int64validator.Between(1, 65535), + }, + }, + }, + }, + }, + "bfd_liveness_detection": schema.SingleNestedBlock{ + Description: "Bidirectional Forwarding Detection options.", + Attributes: map[string]schema.Attribute{ + "authentication_algorithm": schema.StringAttribute{ + Optional: true, + Description: "Authentication algorithm name.", + Validators: []validator.String{ + stringvalidator.LengthAtLeast(1), + tfvalidator.StringFormat(tfvalidator.DefaultFormat), + }, + }, + "authentication_key_chain": schema.StringAttribute{ + Optional: true, + Description: "Authentication key chain name.", + Validators: []validator.String{ + stringvalidator.LengthBetween(1, 128), + tfvalidator.StringDoubleQuoteExclusion(), + }, + }, + "authentication_loose_check": schema.BoolAttribute{ + Optional: true, + Description: "Verify authentication only if authentication is negotiated.", + Validators: []validator.Bool{ + tfvalidator.BoolTrue(), + }, + }, + "detection_time_threshold": schema.Int64Attribute{ + Optional: true, + Description: "High detection-time triggering a trap (milliseconds).", + Validators: []validator.Int64{ + int64validator.Between(1, 4294967295), + }, + }, + "full_neighbors_only": schema.BoolAttribute{ + Optional: true, + Description: "Setup BFD sessions only to Full neighbors.", + Validators: []validator.Bool{ + tfvalidator.BoolTrue(), + }, + }, + "holddown_interval": schema.Int64Attribute{ + Optional: true, + Description: "Time to hold the session-UP notification to the client (milliseconds).", + Validators: []validator.Int64{ + int64validator.Between(1, 255000), + }, + }, + "minimum_interval": schema.Int64Attribute{ + Optional: true, + Description: "Minimum transmit and receive interval (milliseconds).", + Validators: []validator.Int64{ + int64validator.Between(1, 255000), + }, + }, + "minimum_receive_interval": schema.Int64Attribute{ + Optional: true, + Description: "Minimum receive interval (milliseconds).", + Validators: []validator.Int64{ + int64validator.Between(1, 255000), + }, + }, + "multiplier": schema.Int64Attribute{ + Optional: true, + Description: "Detection time multiplier.", + Validators: []validator.Int64{ + int64validator.Between(1, 255), + }, + }, + "no_adaptation": schema.BoolAttribute{ + Optional: true, + Description: "Disable adaptation.", + Validators: []validator.Bool{ + tfvalidator.BoolTrue(), + }, + }, + "transmit_interval_minimum_interval": schema.Int64Attribute{ + Optional: true, + Description: "Minimum transmit interval (milliseconds).", + Validators: []validator.Int64{ + int64validator.Between(1, 255000), + }, + }, + "transmit_interval_threshold": schema.Int64Attribute{ + Optional: true, + Description: "High transmit interval triggering a trap (milliseconds).", + Validators: []validator.Int64{ + int64validator.Between(1, 4294967295), + }, + }, + "version": schema.StringAttribute{ + Optional: true, + Description: "BFD protocol version number.", + Validators: []validator.String{ + stringvalidator.OneOf("0", "1", "automatic"), + }, + }, + }, + PlanModifiers: []planmodifier.Object{ + tfplanmodifier.BlockRemoveNull(), + }, + }, + "neighbor": schema.SetNestedBlock{ + Description: "For each address, configure NBMA neighbor.", + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "address": schema.StringAttribute{ + Required: true, + Description: "Address of neighbor.", + Validators: []validator.String{ + tfvalidator.StringIPAddress(), + }, + }, + "eligible": schema.BoolAttribute{ + Optional: true, + Description: "Eligible to be DR on an NBMA network.", + Validators: []validator.Bool{ + tfvalidator.BoolTrue(), + }, + }, + }, + }, + }, + }, + }, + }, + "area_range": schema.SetNestedBlock{ + Description: "For each `range`, configure area range.", + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "range": schema.StringAttribute{ + Required: true, + Description: "Range to summarize routes in this area.", + Validators: []validator.String{ + tfvalidator.StringCIDRNetwork(), + }, + }, + "exact": schema.BoolAttribute{ + Optional: true, + Description: "Enforce exact match for advertisement of this area range.", + Validators: []validator.Bool{ + tfvalidator.BoolTrue(), + }, + }, + "override_metric": schema.Int64Attribute{ + Optional: true, + Description: "Override the dynamic metric for this area-range.", + Validators: []validator.Int64{ + int64validator.Between(1, 16777215), + }, + }, + "restrict": schema.BoolAttribute{ + Optional: true, + Description: "Restrict advertisement of this area range.", + Validators: []validator.Bool{ + tfvalidator.BoolTrue(), + }, + }, + }, + }, + }, + "nssa": schema.SingleNestedBlock{ + Description: "Configure a not-so-stubby area.", + Attributes: map[string]schema.Attribute{ + "summaries": schema.BoolAttribute{ + Optional: true, + Description: "Flood summary LSAs into this NSSA area.", + Validators: []validator.Bool{ + tfvalidator.BoolTrue(), + }, + }, + "no_summaries": schema.BoolAttribute{ + Optional: true, + Description: "Don't flood summary LSAs into this NSSA area.", + Validators: []validator.Bool{ + tfvalidator.BoolTrue(), + }, + }, + }, + Blocks: map[string]schema.Block{ + "area_range": schema.SetNestedBlock{ + Description: "For each `range`, configure area range.", + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "range": schema.StringAttribute{ + Required: true, + Description: "Range to summarize routes in this area.", + Validators: []validator.String{ + tfvalidator.StringCIDRNetwork(), + }, + }, + "exact": schema.BoolAttribute{ + Optional: true, + Description: "Enforce exact match for advertisement of this area range.", + Validators: []validator.Bool{ + tfvalidator.BoolTrue(), + }, + }, + "override_metric": schema.Int64Attribute{ + Optional: true, + Description: "Override the dynamic metric for this area-range.", + Validators: []validator.Int64{ + int64validator.Between(1, 16777215), + }, + }, + "restrict": schema.BoolAttribute{ + Optional: true, + Description: "Restrict advertisement of this area range.", + Validators: []validator.Bool{ + tfvalidator.BoolTrue(), + }, + }, + }, + }, + }, + "default_lsa": schema.SingleNestedBlock{ + Description: "Configure a default LSA.", + Attributes: map[string]schema.Attribute{ + "default_metric": schema.Int64Attribute{ + Optional: true, + Description: "Metric for the default route in this area.", + Validators: []validator.Int64{ + int64validator.Between(1, 16777215), + }, + }, + "metric_type": schema.Int64Attribute{ + Optional: true, + Description: "External metric type for the default type 7 LSA.", + Validators: []validator.Int64{ + int64validator.Between(1, 2), + }, + }, + "type_7": schema.BoolAttribute{ + Optional: true, + Description: "Flood type 7 default LSA if no-summaries is configured.", + Validators: []validator.Bool{ + tfvalidator.BoolTrue(), + }, + }, + }, + PlanModifiers: []planmodifier.Object{ + tfplanmodifier.BlockRemoveNull(), + }, + }, + }, + PlanModifiers: []planmodifier.Object{ + tfplanmodifier.BlockRemoveNull(), + }, + }, + "stub": schema.SingleNestedBlock{ + Description: "onfigure a stub area.", + Attributes: map[string]schema.Attribute{ + "default_metric": schema.Int64Attribute{ + Optional: true, + Description: "Metric for the default route in this stub area.", + Validators: []validator.Int64{ + int64validator.Between(1, 16777215), + }, + }, + "summaries": schema.BoolAttribute{ + Optional: true, + Description: "Flood summary LSAs into this stub area.", + Validators: []validator.Bool{ + tfvalidator.BoolTrue(), + }, + }, + "no_summaries": schema.BoolAttribute{ + Optional: true, + Description: "Don't flood summary LSAs into this stub area.", + Validators: []validator.Bool{ + tfvalidator.BoolTrue(), + }, + }, + }, + PlanModifiers: []planmodifier.Object{ + tfplanmodifier.BlockRemoveNull(), + }, + }, + "virtual_link": schema.SetNestedBlock{ + Description: "For each combination of `neighbor_id` and `transit_area`, configure virtual link.", + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "neighbor_id": schema.StringAttribute{ + Required: true, + Description: "Router ID of a virtual neighbor.", + Validators: []validator.String{ + tfvalidator.StringIPAddress().IPv4Only(), + }, + }, + "transit_area": schema.StringAttribute{ + Required: true, + Description: "Transit area in common with virtual neighbor.", + Validators: []validator.String{ + tfvalidator.StringIPAddress().IPv4Only(), + }, + }, + "dead_interval": schema.Int64Attribute{ + Optional: true, + Description: "Dead interval (seconds).", + Validators: []validator.Int64{ + int64validator.Between(1, 65535), + }, + }, + "demand_circuit": schema.BoolAttribute{ + Optional: true, + Description: "Interface functions as a demand circuit.", + Validators: []validator.Bool{ + tfvalidator.BoolTrue(), + }, + }, + "disable": schema.BoolAttribute{ + Optional: true, + Description: "Disable this virtual link.", + Validators: []validator.Bool{ + tfvalidator.BoolTrue(), + }, + }, + "flood_reduction": schema.BoolAttribute{ + Optional: true, + Description: "Enable flood reduction.", + Validators: []validator.Bool{ + tfvalidator.BoolTrue(), + }, + }, + "hello_interval": schema.Int64Attribute{ + Optional: true, + Description: "Hello interval (seconds).", + Validators: []validator.Int64{ + int64validator.Between(1, 255), + }, + }, + "ipsec_sa": schema.StringAttribute{ + Optional: true, + Description: "IPSec security association name.", + Validators: []validator.String{ + stringvalidator.LengthBetween(1, 32), + tfvalidator.StringDoubleQuoteExclusion(), + }, + }, + "mtu": schema.Int64Attribute{ + Optional: true, + Description: "Maximum OSPF packet size.", + Validators: []validator.Int64{ + int64validator.Between(128, 65535), + }, + }, + "retransmit_interval": schema.Int64Attribute{ + Optional: true, + Description: "Retransmission interval (seconds).", + Validators: []validator.Int64{ + int64validator.Between(1, 65535), + }, + }, + "transit_delay": schema.Int64Attribute{ + Optional: true, + Description: "Transit delay (seconds).", + Validators: []validator.Int64{ + int64validator.Between(1, 65535), + }, + }, + }, + }, + }, + }, + } +} + +type ospfAreaData struct { + ID types.String `tfsdk:"id"` + AreaID types.String `tfsdk:"area_id"` + Version types.String `tfsdk:"version"` + Realm types.String `tfsdk:"realm"` + RoutingInstance types.String `tfsdk:"routing_instance"` + ContextIdentifier []types.String `tfsdk:"context_identifier"` + InterAreaPrefixExport []types.String `tfsdk:"inter_area_prefix_export"` + InterAreaPrefixImport []types.String `tfsdk:"inter_area_prefix_import"` + NetworkSummaryExport []types.String `tfsdk:"network_summary_export"` + NetworkSummaryImport []types.String `tfsdk:"network_summary_import"` + NoContextIdentifierAdvertisement types.Bool `tfsdk:"no_context_identifier_advertisement"` + Interface []ospfAreaBlockInterface `tfsdk:"interface"` + AreaRange []ospfAreaBlockAreaRange `tfsdk:"area_range"` + Nssa *ospfAreaBlockNssa `tfsdk:"nssa"` + Stub *ospfAreaBlockStub `tfsdk:"stub"` + VirtualLink []ospfAreaBlockVirtualLink `tfsdk:"virtual_link"` +} + +type ospfAreaConfig struct { + ID types.String `tfsdk:"id"` + AreaID types.String `tfsdk:"area_id"` + Version types.String `tfsdk:"version"` + Realm types.String `tfsdk:"realm"` + RoutingInstance types.String `tfsdk:"routing_instance"` + ContextIdentifier types.Set `tfsdk:"context_identifier"` + InterAreaPrefixExport types.List `tfsdk:"inter_area_prefix_export"` + InterAreaPrefixImport types.List `tfsdk:"inter_area_prefix_import"` + NetworkSummaryExport types.List `tfsdk:"network_summary_export"` + NetworkSummaryImport types.List `tfsdk:"network_summary_import"` + NoContextIdentifierAdvertisement types.Bool `tfsdk:"no_context_identifier_advertisement"` + Interface types.List `tfsdk:"interface"` + AreaRange types.Set `tfsdk:"area_range"` + Nssa *ospfAreaBlockNssaConfig `tfsdk:"nssa"` + Stub *ospfAreaBlockStub `tfsdk:"stub"` + VirtualLink types.Set `tfsdk:"virtual_link"` +} + +//nolint:lll +type ospfAreaBlockInterface struct { + Name types.String `tfsdk:"name"` + AuthenticationSimplePassword types.String `tfsdk:"authentication_simple_password"` + DeadInterval types.Int64 `tfsdk:"dead_interval"` + DemandCircuit types.Bool `tfsdk:"demand_circuit"` + Disable types.Bool `tfsdk:"disable"` + DynamicNeighbors types.Bool `tfsdk:"dynamic_neighbors"` + FloodReduction types.Bool `tfsdk:"flood_reduction"` + HelloInterval types.Int64 `tfsdk:"hello_interval"` + InterfaceType types.String `tfsdk:"interface_type"` + IpsecSA types.String `tfsdk:"ipsec_sa"` + IPv4AdjacencySegmentProtectedType types.String `tfsdk:"ipv4_adjacency_segment_protected_type"` + IPv4AdjacencySegmentProtectedValue types.String `tfsdk:"ipv4_adjacency_segment_protected_value"` + IPv4AdjacencySegmentUnprotectedType types.String `tfsdk:"ipv4_adjacency_segment_unprotected_type"` + IPv4AdjacencySegmentUnprotectedValue types.String `tfsdk:"ipv4_adjacency_segment_unprotected_value"` + LinkProtection types.Bool `tfsdk:"link_protection"` + Metric types.Int64 `tfsdk:"metric"` + Mtu types.Int64 `tfsdk:"mtu"` + NoAdvertiseAdjacencySegment types.Bool `tfsdk:"no_advertise_adjacency_segment"` + NoEligibleBackup types.Bool `tfsdk:"no_eligible_backup"` + NoEligibleRemoteBackup types.Bool `tfsdk:"no_eligible_remote_backup"` + NoInterfaceStateTraps types.Bool `tfsdk:"no_interface_state_traps"` + NoNeighborDownNotification types.Bool `tfsdk:"no_neighbor_down_notification"` + NodeLinkProtection types.Bool `tfsdk:"node_link_protection"` + Passive types.Bool `tfsdk:"passive"` + PassiveTrafficEngineeringRemoteNodeID types.String `tfsdk:"passive_traffic_engineering_remote_node_id"` + PassiveTrafficEngineeringRemoteNodeRouterID types.String `tfsdk:"passive_traffic_engineering_remote_node_router_id"` + PollInterval types.Int64 `tfsdk:"poll_interval"` + Priority types.Int64 `tfsdk:"priority"` + RetransmitInterval types.Int64 `tfsdk:"retransmit_interval"` + Secondary types.Bool `tfsdk:"secondary"` + StrictBfd types.Bool `tfsdk:"strict_bfd"` + TeMetric types.Int64 `tfsdk:"te_metric"` + TransitDelay types.Int64 `tfsdk:"transit_delay"` + AuthenticationMD5 []ospfAreaBlockInterfaceBlockAuthenticationMD5 `tfsdk:"authentication_md5"` + BandwidthBasedMetrics []ospfAreaBlockInterfaceBlockBandwidthBasedMetrics `tfsdk:"bandwidth_based_metrics"` + BfdLivenessDetection *ospfAreaBlockInterfaceBlockBfdLivenessDetection `tfsdk:"bfd_liveness_detection"` + Neighbor []ospfAreaBlockInterfaceBlockNeighbor `tfsdk:"neighbor"` +} + +//nolint:lll +type ospfAreaBlockInterfaceConfig struct { + Name types.String `tfsdk:"name"` + AuthenticationSimplePassword types.String `tfsdk:"authentication_simple_password"` + DeadInterval types.Int64 `tfsdk:"dead_interval"` + DemandCircuit types.Bool `tfsdk:"demand_circuit"` + Disable types.Bool `tfsdk:"disable"` + DynamicNeighbors types.Bool `tfsdk:"dynamic_neighbors"` + FloodReduction types.Bool `tfsdk:"flood_reduction"` + HelloInterval types.Int64 `tfsdk:"hello_interval"` + InterfaceType types.String `tfsdk:"interface_type"` + IpsecSA types.String `tfsdk:"ipsec_sa"` + IPv4AdjacencySegmentProtectedType types.String `tfsdk:"ipv4_adjacency_segment_protected_type"` + IPv4AdjacencySegmentProtectedValue types.String `tfsdk:"ipv4_adjacency_segment_protected_value"` + IPv4AdjacencySegmentUnprotectedType types.String `tfsdk:"ipv4_adjacency_segment_unprotected_type"` + IPv4AdjacencySegmentUnprotectedValue types.String `tfsdk:"ipv4_adjacency_segment_unprotected_value"` + LinkProtection types.Bool `tfsdk:"link_protection"` + Metric types.Int64 `tfsdk:"metric"` + Mtu types.Int64 `tfsdk:"mtu"` + NoAdvertiseAdjacencySegment types.Bool `tfsdk:"no_advertise_adjacency_segment"` + NoEligibleBackup types.Bool `tfsdk:"no_eligible_backup"` + NoEligibleRemoteBackup types.Bool `tfsdk:"no_eligible_remote_backup"` + NoInterfaceStateTraps types.Bool `tfsdk:"no_interface_state_traps"` + NoNeighborDownNotification types.Bool `tfsdk:"no_neighbor_down_notification"` + NodeLinkProtection types.Bool `tfsdk:"node_link_protection"` + Passive types.Bool `tfsdk:"passive"` + PassiveTrafficEngineeringRemoteNodeID types.String `tfsdk:"passive_traffic_engineering_remote_node_id"` + PassiveTrafficEngineeringRemoteNodeRouterID types.String `tfsdk:"passive_traffic_engineering_remote_node_router_id"` + PollInterval types.Int64 `tfsdk:"poll_interval"` + Priority types.Int64 `tfsdk:"priority"` + RetransmitInterval types.Int64 `tfsdk:"retransmit_interval"` + Secondary types.Bool `tfsdk:"secondary"` + StrictBfd types.Bool `tfsdk:"strict_bfd"` + TeMetric types.Int64 `tfsdk:"te_metric"` + TransitDelay types.Int64 `tfsdk:"transit_delay"` + AuthenticationMD5 types.List `tfsdk:"authentication_md5"` + BandwidthBasedMetrics types.Set `tfsdk:"bandwidth_based_metrics"` + BfdLivenessDetection *ospfAreaBlockInterfaceBlockBfdLivenessDetection `tfsdk:"bfd_liveness_detection"` + Neighbor types.Set `tfsdk:"neighbor"` +} + +type ospfAreaBlockInterfaceBlockAuthenticationMD5 struct { + KeyID types.Int64 `tfsdk:"key_id"` + Key types.String `tfsdk:"key"` + StartTime types.String `tfsdk:"start_time"` +} + +type ospfAreaBlockInterfaceBlockBandwidthBasedMetrics struct { + Bandwidth types.String `tfsdk:"bandwidth"` + Metric types.Int64 `tfsdk:"metric"` +} + +type ospfAreaBlockInterfaceBlockBfdLivenessDetection struct { + AuthenticationAlgorithm types.String `tfsdk:"authentication_algorithm"` + AuthenticationKeyChain types.String `tfsdk:"authentication_key_chain"` + AuthenticationLooseCheck types.Bool `tfsdk:"authentication_loose_check"` + DetectionTimeThreshold types.Int64 `tfsdk:"detection_time_threshold"` + FullNeighborsOnly types.Bool `tfsdk:"full_neighbors_only"` + HolddownInterval types.Int64 `tfsdk:"holddown_interval"` + MinimumInterval types.Int64 `tfsdk:"minimum_interval"` + MinimumReceiveInterval types.Int64 `tfsdk:"minimum_receive_interval"` + Multiplier types.Int64 `tfsdk:"multiplier"` + NoAdaptation types.Bool `tfsdk:"no_adaptation"` + TransmitIntervalMinimumInterval types.Int64 `tfsdk:"transmit_interval_minimum_interval"` + TransmitIntervalThreshold types.Int64 `tfsdk:"transmit_interval_threshold"` + Version types.String `tfsdk:"version"` +} + +func (block *ospfAreaBlockInterfaceBlockBfdLivenessDetection) isEmpty() bool { + return tfdata.CheckBlockIsEmpty(block) +} + +type ospfAreaBlockInterfaceBlockNeighbor struct { + Address types.String `tfsdk:"address"` + Eligbile types.Bool `tfsdk:"eligible"` +} + +type ospfAreaBlockAreaRange struct { + Range types.String `tfsdk:"range"` + Exact types.Bool `tfsdk:"exact"` + OverrideMetric types.Int64 `tfsdk:"override_metric"` + Restrict types.Bool `tfsdk:"restrict"` +} + +type ospfAreaBlockNssa struct { + Summaries types.Bool `tfsdk:"summaries"` + NoSummaries types.Bool `tfsdk:"no_summaries"` + AreaRange []ospfAreaBlockAreaRange `tfsdk:"area_range"` + DefaultLsa *ospfAreaBlockNssaBlockDefaultLsa `tfsdk:"default_lsa"` +} + +type ospfAreaBlockNssaConfig struct { + Summaries types.Bool `tfsdk:"summaries"` + NoSummaries types.Bool `tfsdk:"no_summaries"` + AreaRange types.Set `tfsdk:"area_range"` + DefaultLsa *ospfAreaBlockNssaBlockDefaultLsa `tfsdk:"default_lsa"` +} + +func (block *ospfAreaBlockNssaConfig) hasKnownValue() bool { + return tfdata.CheckBlockHasKnownValue(block) +} + +type ospfAreaBlockNssaBlockDefaultLsa struct { + DefaultMetric types.Int64 `tfsdk:"default_metric"` + MetricType types.Int64 `tfsdk:"metric_type"` + Type7 types.Bool `tfsdk:"type_7"` +} + +type ospfAreaBlockStub struct { + DefaultMetric types.Int64 `tfsdk:"default_metric"` + Summaries types.Bool `tfsdk:"summaries"` + NoSummaries types.Bool `tfsdk:"no_summaries"` +} + +func (block *ospfAreaBlockStub) hasKnownValue() bool { + return tfdata.CheckBlockHasKnownValue(block) +} + +type ospfAreaBlockVirtualLink struct { + NeighborID types.String `tfsdk:"neighbor_id"` + TransitArea types.String `tfsdk:"transit_area"` + DeadInterval types.Int64 `tfsdk:"dead_interval"` + DemandCircuit types.Bool `tfsdk:"demand_circuit"` + Disable types.Bool `tfsdk:"disable"` + FloodReduction types.Bool `tfsdk:"flood_reduction"` + HelloInterval types.Int64 `tfsdk:"hello_interval"` + IpsecSA types.String `tfsdk:"ipsec_sa"` + Mtu types.Int64 `tfsdk:"mtu"` + RetransmitInterval types.Int64 `tfsdk:"retransmit_interval"` + TransitDelay types.Int64 `tfsdk:"transit_delay"` +} + +func (rsc *ospfArea) ValidateConfig( + ctx context.Context, req resource.ValidateConfigRequest, resp *resource.ValidateConfigResponse, +) { + var config ospfAreaConfig + resp.Diagnostics.Append(req.Config.Get(ctx, &config)...) + if resp.Diagnostics.HasError() { + return + } + + if !config.Version.IsNull() && !config.Version.IsUnknown() { + switch config.Version.ValueString() { + case "v2": + if !config.Realm.IsNull() && !config.Realm.IsUnknown() { + resp.Diagnostics.AddAttributeError( + path.Root("realm"), + tfdiag.ConflictConfigErrSummary, + "realm cannot be configured when version = v2", + ) + } + if !config.InterAreaPrefixExport.IsNull() && !config.InterAreaPrefixExport.IsUnknown() { + resp.Diagnostics.AddAttributeError( + path.Root("inter_area_prefix_export"), + tfdiag.ConflictConfigErrSummary, + "inter_area_prefix_export cannot be configured when version = v2", + ) + } + if !config.InterAreaPrefixImport.IsNull() && !config.InterAreaPrefixImport.IsUnknown() { + resp.Diagnostics.AddAttributeError( + path.Root("inter_area_prefix_import"), + tfdiag.ConflictConfigErrSummary, + "inter_area_prefix_import cannot be configured when version = v2", + ) + } + case "v3": + if !config.NetworkSummaryExport.IsNull() && !config.NetworkSummaryExport.IsUnknown() { + resp.Diagnostics.AddAttributeError( + path.Root("network_summary_export"), + tfdiag.ConflictConfigErrSummary, + "network_summary_export cannot be configured when version = v3", + ) + } + if !config.NetworkSummaryImport.IsNull() && !config.NetworkSummaryImport.IsUnknown() { + resp.Diagnostics.AddAttributeError( + path.Root("network_summary_import"), + tfdiag.ConflictConfigErrSummary, + "network_summary_import cannot be configured when version = v3", + ) + } + } + } + if !config.ContextIdentifier.IsNull() && !config.ContextIdentifier.IsUnknown() && + !config.NoContextIdentifierAdvertisement.IsNull() && !config.NoContextIdentifierAdvertisement.IsUnknown() { + resp.Diagnostics.AddAttributeError( + path.Root("context_identifier"), + tfdiag.ConflictConfigErrSummary, + "context_identifier and no_context_identifier_advertisement cannot be configured together", + ) + } + if config.Interface.IsNull() { + resp.Diagnostics.AddAttributeError( + path.Root("interface"), + tfdiag.MissingConfigErrSummary, + "interface block must be specified", + ) + } else if !config.Interface.IsUnknown() { + var configInterface []ospfAreaBlockInterfaceConfig + asDiags := config.Interface.ElementsAs(ctx, &configInterface, false) + if asDiags.HasError() { + resp.Diagnostics.Append(asDiags...) + + return + } + + interfaceName := make(map[string]struct{}) + for i, block := range configInterface { + if !block.Name.IsUnknown() { + name := block.Name.ValueString() + if _, ok := interfaceName[name]; ok { + resp.Diagnostics.AddAttributeError( + path.Root("interface").AtListIndex(i).AtName("name"), + tfdiag.DuplicateConfigErrSummary, + fmt.Sprintf("multiple interface blocks with the same name %q", name), + ) + } + interfaceName[name] = struct{}{} + } + if !block.AuthenticationSimplePassword.IsNull() && !block.AuthenticationSimplePassword.IsUnknown() && + !block.AuthenticationMD5.IsNull() && !block.AuthenticationMD5.IsUnknown() { + resp.Diagnostics.AddAttributeError( + path.Root("interface").AtListIndex(i).AtName("authentication_simple_password"), + tfdiag.ConflictConfigErrSummary, + fmt.Sprintf("authentication_simple_password and authentication_md5 cannot be configured together"+ + " in interface block %q", block.Name.ValueString()), + ) + } + if !block.IPv4AdjacencySegmentProtectedValue.IsNull() && !block.IPv4AdjacencySegmentProtectedValue.IsUnknown() && + block.IPv4AdjacencySegmentProtectedType.IsNull() { + resp.Diagnostics.AddAttributeError( + path.Root("interface").AtListIndex(i).AtName("ipv4_adjacency_segment_protected_value"), + tfdiag.MissingConfigErrSummary, + fmt.Sprintf("ipv4_adjacency_segment_protected_type must be specified with ipv4_adjacency_segment_protected_value"+ + " in interface block %q", block.Name.ValueString()), + ) + } + if !block.IPv4AdjacencySegmentUnprotectedValue.IsNull() && !block.IPv4AdjacencySegmentUnprotectedValue.IsUnknown() && + block.IPv4AdjacencySegmentUnprotectedType.IsNull() { + resp.Diagnostics.AddAttributeError( + path.Root("interface").AtListIndex(i).AtName("ipv4_adjacency_segment_unprotected_value"), + tfdiag.MissingConfigErrSummary, + fmt.Sprintf("ipv4_adjacency_segment_unprotected_type must be specified"+ + " with ipv4_adjacency_segment_unprotected_value"+ + " in interface block %q", block.Name.ValueString()), + ) + } + if block.Passive.IsNull() { + if !block.PassiveTrafficEngineeringRemoteNodeID.IsNull() && + !block.PassiveTrafficEngineeringRemoteNodeID.IsUnknown() { + resp.Diagnostics.AddAttributeError( + path.Root("interface").AtListIndex(i).AtName("passive_traffic_engineering_remote_node_id"), + tfdiag.MissingConfigErrSummary, + fmt.Sprintf("passive must be specified with passive_traffic_engineering_remote_node_id"+ + " in interface block %q", block.Name.ValueString()), + ) + } + if !block.PassiveTrafficEngineeringRemoteNodeRouterID.IsNull() && + !block.PassiveTrafficEngineeringRemoteNodeRouterID.IsUnknown() { + resp.Diagnostics.AddAttributeError( + path.Root("interface").AtListIndex(i).AtName("passive_traffic_engineering_remote_node_router_id"), + tfdiag.MissingConfigErrSummary, + fmt.Sprintf("passive must be specified with passive_traffic_engineering_remote_node_router_id"+ + " in interface block %q", block.Name.ValueString()), + ) + } + } + + if !block.AuthenticationMD5.IsNull() && !block.AuthenticationMD5.IsUnknown() { + var configAuthenticationMD5 []ospfAreaBlockInterfaceBlockAuthenticationMD5 + asDiags := block.AuthenticationMD5.ElementsAs(ctx, &configAuthenticationMD5, false) + if asDiags.HasError() { + resp.Diagnostics.Append(asDiags...) + + return + } + + authenticationMD5KeyID := make(map[int64]struct{}) + for ii, blockAuthenticationMD5 := range configAuthenticationMD5 { + if blockAuthenticationMD5.KeyID.IsUnknown() { + continue + } + keyID := blockAuthenticationMD5.KeyID.ValueInt64() + if _, ok := authenticationMD5KeyID[keyID]; ok { + resp.Diagnostics.AddAttributeError( + path.Root("interface").AtListIndex(i).AtName("authentication_md5").AtListIndex(ii).AtName("key_id"), + tfdiag.DuplicateConfigErrSummary, + fmt.Sprintf("multiple authentication_md5 blocks with the same key_id %d"+ + " in interface block %q", keyID, block.Name.ValueString()), + ) + } + authenticationMD5KeyID[keyID] = struct{}{} + } + } + if !block.BandwidthBasedMetrics.IsNull() && !block.BandwidthBasedMetrics.IsUnknown() { + var configBandwidthBasedMetrics []ospfAreaBlockInterfaceBlockBandwidthBasedMetrics + asDiags := block.BandwidthBasedMetrics.ElementsAs(ctx, &configBandwidthBasedMetrics, false) + if asDiags.HasError() { + resp.Diagnostics.Append(asDiags...) + + return + } + + bandwidthBasedMetricsBandwidth := make(map[string]struct{}) + for _, blockBandwidthBasedMetrics := range configBandwidthBasedMetrics { + if blockBandwidthBasedMetrics.Bandwidth.IsUnknown() { + continue + } + bandwidth := blockBandwidthBasedMetrics.Bandwidth.ValueString() + if _, ok := bandwidthBasedMetricsBandwidth[bandwidth]; ok { + resp.Diagnostics.AddAttributeError( + path.Root("interface").AtListIndex(i).AtName("bandwidth_based_metrics"), + tfdiag.DuplicateConfigErrSummary, + fmt.Sprintf("multiple bandwidth_based_metrics blocks with the same bandwidth %q"+ + " in interface block %q", bandwidth, block.Name.ValueString()), + ) + } + bandwidthBasedMetricsBandwidth[bandwidth] = struct{}{} + } + } + if block.BfdLivenessDetection != nil { + if block.BfdLivenessDetection.isEmpty() { + resp.Diagnostics.AddAttributeError( + path.Root("interface").AtListIndex(i).AtName("bfd_liveness_detection").AtName("*"), + tfdiag.MissingConfigErrSummary, + fmt.Sprintf("bfd_liveness_detection block is empty"+ + " in interface block %q", block.Name.ValueString()), + ) + } + } + if !block.Neighbor.IsNull() && !block.Neighbor.IsUnknown() { + var configNeighbor []ospfAreaBlockInterfaceBlockNeighbor + asDiags := block.Neighbor.ElementsAs(ctx, &configNeighbor, false) + if asDiags.HasError() { + resp.Diagnostics.Append(asDiags...) + + return + } + + neighborAddress := make(map[string]struct{}) + for _, blockNeighbor := range configNeighbor { + if blockNeighbor.Address.IsUnknown() { + continue + } + address := blockNeighbor.Address.ValueString() + if _, ok := neighborAddress[address]; ok { + resp.Diagnostics.AddAttributeError( + path.Root("interface").AtListIndex(i).AtName("neighbor"), + tfdiag.DuplicateConfigErrSummary, + fmt.Sprintf("multiple neighbor blocks with the same address %q"+ + " in interface block %q", address, block.Name.ValueString()), + ) + } + neighborAddress[address] = struct{}{} + } + } + } + } + if !config.AreaRange.IsNull() && !config.AreaRange.IsUnknown() { + var configAreaRange []ospfAreaBlockAreaRange + asDiags := config.AreaRange.ElementsAs(ctx, &configAreaRange, false) + if asDiags.HasError() { + resp.Diagnostics.Append(asDiags...) + + return + } + + areaRangeRange := make(map[string]struct{}) + for _, block := range configAreaRange { + if block.Range.IsUnknown() { + continue + } + rangeValue := block.Range.ValueString() + if _, ok := areaRangeRange[rangeValue]; ok { + resp.Diagnostics.AddAttributeError( + path.Root("area_range"), + tfdiag.DuplicateConfigErrSummary, + fmt.Sprintf("multiple area_range blocks with the same range %q", rangeValue), + ) + } + areaRangeRange[rangeValue] = struct{}{} + } + } + if config.Nssa != nil && config.Nssa.hasKnownValue() && + config.Stub != nil && config.Stub.hasKnownValue() { + resp.Diagnostics.AddAttributeError( + path.Root("nssa"), + tfdiag.ConflictConfigErrSummary, + "nssa and stub cannot be configured together", + ) + } + if config.Nssa != nil { + if !config.Nssa.Summaries.IsNull() && !config.Nssa.Summaries.IsUnknown() && + !config.Nssa.NoSummaries.IsNull() && !config.Nssa.NoSummaries.IsUnknown() { + resp.Diagnostics.AddAttributeError( + path.Root("nssa").AtName("summaries"), + tfdiag.ConflictConfigErrSummary, + "summaries and no_summaries cannot be configured together"+ + " in nssa block", + ) + } + if !config.Nssa.AreaRange.IsNull() && !config.Nssa.AreaRange.IsUnknown() { + var configAreaRange []ospfAreaBlockAreaRange + asDiags := config.Nssa.AreaRange.ElementsAs(ctx, &configAreaRange, false) + if asDiags.HasError() { + resp.Diagnostics.Append(asDiags...) + + return + } + + areaRangeRange := make(map[string]struct{}) + for _, block := range configAreaRange { + if block.Range.IsUnknown() { + continue + } + rangeValue := block.Range.ValueString() + if _, ok := areaRangeRange[rangeValue]; ok { + resp.Diagnostics.AddAttributeError( + path.Root("nssa").AtName("area_range"), + tfdiag.DuplicateConfigErrSummary, + fmt.Sprintf("multiple area_range blocks with the same range %q"+ + " in nssa block", rangeValue), + ) + } + areaRangeRange[rangeValue] = struct{}{} + } + } + } + if config.Stub != nil { + if !config.Stub.Summaries.IsNull() && !config.Stub.Summaries.IsUnknown() && + !config.Stub.NoSummaries.IsNull() && !config.Stub.NoSummaries.IsUnknown() { + resp.Diagnostics.AddAttributeError( + path.Root("stub").AtName("summaries"), + tfdiag.ConflictConfigErrSummary, + "summaries and no_summaries cannot be configured together"+ + " in stub block", + ) + } + } + if !config.VirtualLink.IsNull() && !config.VirtualLink.IsUnknown() { + var configVirtualLink []ospfAreaBlockVirtualLink + asDiags := config.VirtualLink.ElementsAs(ctx, &configVirtualLink, false) + if asDiags.HasError() { + resp.Diagnostics.Append(asDiags...) + + return + } + + virtualLinkNeighborIDTransitArea := make(map[string]struct{}) + for _, block := range configVirtualLink { + if block.NeighborID.IsUnknown() { + continue + } + if block.TransitArea.IsUnknown() { + continue + } + neighborID := block.NeighborID.ValueString() + transitArea := block.TransitArea.ValueString() + if _, ok := virtualLinkNeighborIDTransitArea[neighborID+junos.IDSeparator+transitArea]; ok { + resp.Diagnostics.AddAttributeError( + path.Root("virtual_link"), + tfdiag.DuplicateConfigErrSummary, + fmt.Sprintf("multiple virtual_link blocks with the same neighbor_id %q and transit_area %q", + neighborID, transitArea), + ) + } + virtualLinkNeighborIDTransitArea[neighborID+junos.IDSeparator+transitArea] = struct{}{} + } + } +} + +func (rsc *ospfArea) Create( + ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse, +) { + var plan ospfAreaData + resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) + if resp.Diagnostics.HasError() { + return + } + if plan.AreaID.ValueString() == "" { + resp.Diagnostics.AddAttributeError( + path.Root("area_id"), + "Empty Area ID", + defaultResourceCouldNotCreateWithEmptyMessage(rsc, "area_id"), + ) + + return + } + if version := plan.Version.ValueString(); version == "" { + resp.Diagnostics.AddAttributeError( + path.Root("version"), + "Empty Version", + defaultResourceCouldNotCreateWithEmptyMessage(rsc, "version"), + ) + + return + } else if version == "v2" && plan.Realm.ValueString() != "" { + resp.Diagnostics.AddAttributeError( + path.Root("realm"), + tfdiag.ConflictConfigErrSummary, + "realm cannot be configured when version = v2", + ) + } + + defaultResourceCreate( + ctx, + rsc, + func(fnCtx context.Context, junSess *junos.Session) bool { + if v := plan.RoutingInstance.ValueString(); v != "" && v != junos.DefaultW { + instanceExists, err := checkRoutingInstanceExists(fnCtx, v, junSess) + if err != nil { + resp.Diagnostics.AddError(tfdiag.PreCheckErrSummary, err.Error()) + + return false + } + if !instanceExists { + resp.Diagnostics.AddAttributeError( + path.Root("routing_instance"), + tfdiag.MissingConfigErrSummary, + fmt.Sprintf("routing instance %q doesn't exist", v), + ) + + return false + } + } + areaExists, err := checkOspfAreaExists( + fnCtx, + plan.AreaID.ValueString(), + plan.Version.ValueString(), + plan.Realm.ValueString(), + plan.RoutingInstance.ValueString(), + junSess, + ) + if err != nil { + resp.Diagnostics.AddError(tfdiag.PreCheckErrSummary, err.Error()) + + return false + } + if areaExists { + var inRoutingInstanceMessage string + if v := plan.RoutingInstance.ValueString(); v != "" { + inRoutingInstanceMessage = fmt.Sprintf(" in routing-instance %q", v) + } + switch plan.Version.ValueString() { + case "v2": + resp.Diagnostics.AddError( + tfdiag.DuplicateConfigErrSummary, + fmt.Sprintf("ospf area %q already exists"+inRoutingInstanceMessage, plan.AreaID.ValueString()), + ) + case "v3": + if realm := plan.Realm.ValueString(); realm != "" { + resp.Diagnostics.AddError( + tfdiag.DuplicateConfigErrSummary, + fmt.Sprintf("ospf3 realm %q area %q already exists"+inRoutingInstanceMessage, realm, plan.AreaID.ValueString()), + ) + } else { + resp.Diagnostics.AddError( + tfdiag.DuplicateConfigErrSummary, + fmt.Sprintf("ospf3 area %q already exists"+inRoutingInstanceMessage, realm, plan.AreaID.ValueString()), + ) + } + } + + return false + } + + return true + }, + func(fnCtx context.Context, junSess *junos.Session) bool { + areaExists, err := checkOspfAreaExists( + fnCtx, + plan.AreaID.ValueString(), + plan.Version.ValueString(), + plan.Realm.ValueString(), + plan.RoutingInstance.ValueString(), + junSess, + ) + if err != nil { + resp.Diagnostics.AddError(tfdiag.PostCheckErrSummary, err.Error()) + + return false + } + if !areaExists { + var inRoutingInstanceMessage string + if v := plan.RoutingInstance.ValueString(); v != "" { + inRoutingInstanceMessage = fmt.Sprintf("in routing-instance %q", v) + } + switch plan.Version.ValueString() { + case "v2": + resp.Diagnostics.AddError( + tfdiag.NotFoundErrSummary, + fmt.Sprintf("ospf area %q does not exists after commit "+inRoutingInstanceMessage+ + "=> check your config", plan.AreaID.ValueString()), + ) + case "v3": + if realm := plan.Realm.ValueString(); realm != "" { + resp.Diagnostics.AddError( + tfdiag.NotFoundErrSummary, + fmt.Sprintf("ospf3 realm %q area %q does not exists after commit "+inRoutingInstanceMessage+ + "=> check your config", realm, plan.AreaID.ValueString()), + ) + } else { + resp.Diagnostics.AddError( + tfdiag.NotFoundErrSummary, + fmt.Sprintf("ospf3 area %q does not exists after commit "+inRoutingInstanceMessage+ + "=> check your config", realm, plan.AreaID.ValueString()), + ) + } + } + + return false + } + + return true + }, + &plan, + resp, + ) +} + +func (rsc *ospfArea) Read( + ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse, +) { + var state, data ospfAreaData + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + + var _ resourceDataReadFrom4String = &data + defaultResourceRead( + ctx, + rsc, + []string{ + state.AreaID.ValueString(), + state.Version.ValueString(), + state.Realm.ValueString(), + state.RoutingInstance.ValueString(), + }, + &data, + nil, + resp, + ) +} + +func (rsc *ospfArea) Update( + ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse, +) { + var plan, state ospfAreaData + resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + + defaultResourceUpdate( + ctx, + rsc, + &state, + &plan, + resp, + ) +} + +func (rsc *ospfArea) Delete( + ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse, +) { + var state ospfAreaData + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + + defaultResourceDelete( + ctx, + rsc, + &state, + resp, + ) +} + +func (rsc *ospfArea) ImportState( + ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse, +) { + junSess, err := rsc.client.StartNewSession(ctx) + if err != nil { + resp.Diagnostics.AddError(tfdiag.StartSessErrSummary, err.Error()) + + return + } + defer junSess.Close() + + var data ospfAreaData + idSplit := strings.Split(req.ID, junos.IDSeparator) + switch { + case len(idSplit) < 3: + resp.Diagnostics.AddError( + "Bad ID Format", + fmt.Sprintf("missing element(s) in id with separator %q", junos.IDSeparator), + ) + + return + case len(idSplit) == 4: + if err := data.read(ctx, idSplit[0], idSplit[1], idSplit[2], idSplit[3], junSess); err != nil { + resp.Diagnostics.AddError(tfdiag.ConfigReadErrSummary, err.Error()) + + return + } + default: + if err := data.read(ctx, idSplit[0], idSplit[1], "", idSplit[2], junSess); err != nil { + resp.Diagnostics.AddError(tfdiag.ConfigReadErrSummary, err.Error()) + + return + } + } + + if data.ID.IsNull() { + resp.Diagnostics.AddError( + tfdiag.NotFoundErrSummary, + defaultResourceImportDontFindMessage(rsc, req.ID)+ + " (id must be "+ + ""+junos.IDSeparator+""+junos.IDSeparator+" or "+ + ""+junos.IDSeparator+""+junos.IDSeparator+""+junos.IDSeparator+")", + ) + + return + } + resp.Diagnostics.Append(resp.State.Set(ctx, data)...) +} + +func checkOspfAreaExists( + _ context.Context, areaID, version, realm, routingInstance string, junSess *junos.Session, +) ( + _ bool, err error, +) { + var showConfig string + ospfVersion := junos.OspfV2 + if version == "v3" { + ospfVersion = junos.OspfV3 + } else if realm != "" { + return false, errors.New("realm can't set if version != v3") + } + switch { + case (routingInstance == junos.DefaultW || routingInstance == "") && realm == "": + showConfig, err = junSess.Command(junos.CmdShowConfig + + "protocols " + ospfVersion + " area " + areaID + junos.PipeDisplaySet) + if err != nil { + return false, err + } + case (routingInstance == junos.DefaultW || routingInstance == "") && realm != "": + showConfig, err = junSess.Command(junos.CmdShowConfig + + "protocols " + ospfVersion + " realm " + realm + " area " + areaID + junos.PipeDisplaySet) + if err != nil { + return false, err + } + case realm != "": + showConfig, err = junSess.Command(junos.CmdShowConfig + junos.RoutingInstancesWS + routingInstance + " " + + "protocols " + ospfVersion + " realm " + realm + " area " + areaID + junos.PipeDisplaySet) + if err != nil { + return false, err + } + default: + showConfig, err = junSess.Command(junos.CmdShowConfig + junos.RoutingInstancesWS + routingInstance + " " + + "protocols " + ospfVersion + " area " + areaID + junos.PipeDisplaySet) + if err != nil { + return false, err + } + } + if showConfig == junos.EmptyW { + return false, nil + } + + return true, nil +} + +func (rscData *ospfAreaData) fillID() { + routingInstance := junos.DefaultW + if v := rscData.RoutingInstance.ValueString(); v != "" { + routingInstance = v + } + if realm := rscData.Realm.ValueString(); realm != "" { + rscData.ID = types.StringValue( + rscData.AreaID.ValueString() + junos.IDSeparator + + rscData.Version.ValueString() + junos.IDSeparator + + realm + junos.IDSeparator + + routingInstance, + ) + } else { + rscData.ID = types.StringValue( + rscData.AreaID.ValueString() + junos.IDSeparator + + rscData.Version.ValueString() + junos.IDSeparator + + routingInstance, + ) + } +} + +func (rscData *ospfAreaData) nullID() bool { + return rscData.ID.IsNull() +} + +func (rscData *ospfAreaData) set( + _ context.Context, junSess *junos.Session, +) ( + path.Path, error, +) { + configSet := make([]string, 0) + setPrefix := junos.SetLS + if v := rscData.RoutingInstance.ValueString(); v != "" && v != junos.DefaultW { + setPrefix = junos.SetRoutingInstances + v + " " + } + ospfVersion := junos.OspfV2 + if rscData.Version.ValueString() == "v3" { + ospfVersion = junos.OspfV3 + } else if rscData.Realm.ValueString() != "" { + return path.Root("realm"), errors.New("realm can't set if version != v3") + } + setPrefix += "protocols " + ospfVersion + " " + if v := rscData.Realm.ValueString(); v != "" { + setPrefix += "realm " + v + " " + } + setPrefix += "area " + rscData.AreaID.ValueString() + " " + + for _, v := range rscData.ContextIdentifier { + configSet = append(configSet, setPrefix+"context-identifier "+v.ValueString()) + } + for _, v := range rscData.InterAreaPrefixExport { + configSet = append(configSet, setPrefix+"inter-area-prefix-export \""+v.ValueString()+"\"") + } + for _, v := range rscData.InterAreaPrefixImport { + configSet = append(configSet, setPrefix+"inter-area-prefix-import \""+v.ValueString()+"\"") + } + for _, v := range rscData.NetworkSummaryExport { + configSet = append(configSet, setPrefix+"network-summary-export \""+v.ValueString()+"\"") + } + for _, v := range rscData.NetworkSummaryImport { + configSet = append(configSet, setPrefix+"network-summary-import \""+v.ValueString()+"\"") + } + if rscData.NoContextIdentifierAdvertisement.ValueBool() { + configSet = append(configSet, setPrefix+"no-context-identifier-advertisement") + } + + interfaceName := make(map[string]struct{}) + for i, block := range rscData.Interface { + name := block.Name.ValueString() + if _, ok := interfaceName[name]; ok { + return path.Root("interface").AtListIndex(i).AtName("name"), + fmt.Errorf("multiple interface blocks with the same name %q", name) + } + interfaceName[name] = struct{}{} + + blockSet, pathErr, err := block.configSet(setPrefix, path.Root("interface").AtListIndex(i)) + if err != nil { + return pathErr, err + } + configSet = append(configSet, blockSet...) + } + areaRangeRange := make(map[string]struct{}) + for _, block := range rscData.AreaRange { + rangeValue := block.Range.ValueString() + if _, ok := areaRangeRange[rangeValue]; ok { + return path.Root("area_range"), + fmt.Errorf("multiple area_range blocks with the same range %q", rangeValue) + } + areaRangeRange[rangeValue] = struct{}{} + + configSet = append(configSet, block.configSet(setPrefix)...) + } + if rscData.Nssa != nil { + blockSet, pathErr, err := rscData.Nssa.configSet(setPrefix, path.Root("nssa")) + if err != nil { + return pathErr, err + } + configSet = append(configSet, blockSet...) + } + if rscData.Stub != nil { + configSet = append(configSet, setPrefix+"stub") + + if !rscData.Stub.DefaultMetric.IsNull() { + configSet = append(configSet, setPrefix+"stub default-metric "+ + utils.ConvI64toa(rscData.Stub.DefaultMetric.ValueInt64())) + } + if rscData.Stub.Summaries.ValueBool() { + configSet = append(configSet, setPrefix+"stub summaries") + } + if rscData.Stub.NoSummaries.ValueBool() { + configSet = append(configSet, setPrefix+"stub no-summaries") + } + } + virtualLinkNeighborIDTransitArea := make(map[string]struct{}) + for _, block := range rscData.VirtualLink { + neighborID := block.NeighborID.ValueString() + transitArea := block.TransitArea.ValueString() + if _, ok := virtualLinkNeighborIDTransitArea[neighborID+junos.IDSeparator+transitArea]; ok { + return path.Root("virtual_link"), + fmt.Errorf("multiple virtual_link blocks with the same neighbor_id %q and transit_area %q", neighborID, transitArea) + } + virtualLinkNeighborIDTransitArea[neighborID+junos.IDSeparator+transitArea] = struct{}{} + + configSet = append(configSet, block.configSet(setPrefix)...) + } + + return path.Empty(), junSess.ConfigSet(configSet) +} + +func (block *ospfAreaBlockInterface) configSet( + setPrefix string, pathRoot path.Path, +) ( + []string, // configSet + path.Path, // pathErr + error, // error +) { + setPrefix += "interface " + block.Name.ValueString() + " " + configSet := []string{ + setPrefix, + } + + if v := block.AuthenticationSimplePassword.ValueString(); v != "" { + if len(block.AuthenticationMD5) > 0 { + return configSet, + pathRoot.AtName("authentication_md5"), + fmt.Errorf("authentication_simple_password and authentication_md5 cannot be configured together"+ + " in interface block %q", block.Name.ValueString()) + } + configSet = append(configSet, setPrefix+"authentication simple-password \""+v+"\"") + } + if !block.DeadInterval.IsNull() { + configSet = append(configSet, setPrefix+"dead-interval "+ + utils.ConvI64toa(block.DeadInterval.ValueInt64())) + } + if block.DemandCircuit.ValueBool() { + configSet = append(configSet, setPrefix+"demand-circuit") + } + if block.Disable.ValueBool() { + configSet = append(configSet, setPrefix+"disable") + } + if block.DynamicNeighbors.ValueBool() { + configSet = append(configSet, setPrefix+"dynamic-neighbors") + } + if block.FloodReduction.ValueBool() { + configSet = append(configSet, setPrefix+"flood-reduction") + } + if !block.HelloInterval.IsNull() { + configSet = append(configSet, setPrefix+"hello-interval "+ + utils.ConvI64toa(block.HelloInterval.ValueInt64())) + } + if v := block.InterfaceType.ValueString(); v != "" { + configSet = append(configSet, setPrefix+"interface-type "+v) + } + if v := block.IpsecSA.ValueString(); v != "" { + configSet = append(configSet, setPrefix+"ipsec-sa \""+v+"\"") + } + if t := block.IPv4AdjacencySegmentProtectedType.ValueString(); t != "" { + if v := block.IPv4AdjacencySegmentProtectedValue.ValueString(); v != "" { + configSet = append(configSet, setPrefix+"ipv4-adjacency-segment protected "+t+" \""+v+"\"") + } else { + configSet = append(configSet, setPrefix+"ipv4-adjacency-segment protected "+t) + } + } else if block.IPv4AdjacencySegmentProtectedValue.ValueString() != "" { + return configSet, + pathRoot.AtName("ipv4_adjacency_segment_protected_value"), + fmt.Errorf("ipv4_adjacency_segment_protected_type must be specified with ipv4_adjacency_segment_protected_value"+ + " in interface block %q", block.Name.ValueString()) + } + if t := block.IPv4AdjacencySegmentUnprotectedType.ValueString(); t != "" { + if v := block.IPv4AdjacencySegmentUnprotectedValue.ValueString(); v != "" { + configSet = append(configSet, setPrefix+"ipv4-adjacency-segment unprotected "+t+" \""+v+"\"") + } else { + configSet = append(configSet, setPrefix+"ipv4-adjacency-segment unprotected "+t) + } + } else if block.IPv4AdjacencySegmentUnprotectedValue.ValueString() != "" { + return configSet, + pathRoot.AtName("ipv4_adjacency_segment_unprotected_value"), + fmt.Errorf("ipv4_adjacency_segment_unprotected_type must be specified with ipv4_adjacency_segment_unprotected_value"+ + " in interface block %q", block.Name.ValueString()) + } + if block.LinkProtection.ValueBool() { + configSet = append(configSet, setPrefix+"link-protection") + } + if !block.Metric.IsNull() { + configSet = append(configSet, setPrefix+"metric "+ + utils.ConvI64toa(block.Metric.ValueInt64())) + } + if !block.Mtu.IsNull() { + configSet = append(configSet, setPrefix+"mtu "+ + utils.ConvI64toa(block.Mtu.ValueInt64())) + } + if block.NoAdvertiseAdjacencySegment.ValueBool() { + configSet = append(configSet, setPrefix+"no-advertise-adjacency-segment") + } + if block.NoEligibleBackup.ValueBool() { + configSet = append(configSet, setPrefix+"no-eligible-backup") + } + if block.NoEligibleRemoteBackup.ValueBool() { + configSet = append(configSet, setPrefix+"no-eligible-remote-backup") + } + if block.NoInterfaceStateTraps.ValueBool() { + configSet = append(configSet, setPrefix+"no-interface-state-traps") + } + if block.NoNeighborDownNotification.ValueBool() { + configSet = append(configSet, setPrefix+"no-neighbor-down-notification") + } + if block.NodeLinkProtection.ValueBool() { + configSet = append(configSet, setPrefix+"node-link-protection") + } + if block.Passive.ValueBool() { + configSet = append(configSet, setPrefix+"passive") + if v := block.PassiveTrafficEngineeringRemoteNodeID.ValueString(); v != "" { + configSet = append(configSet, setPrefix+"passive traffic-engineering remote-node-id "+v) + } + if v := block.PassiveTrafficEngineeringRemoteNodeRouterID.ValueString(); v != "" { + configSet = append(configSet, setPrefix+"passive traffic-engineering remote-node-router-id "+v) + } + } else { + if block.PassiveTrafficEngineeringRemoteNodeID.ValueString() != "" { + return configSet, + pathRoot.AtName("passive_traffic_engineering_remote_node_id"), + fmt.Errorf("passive must be specified with passive_traffic_engineering_remote_node_id"+ + " in interface block %q", block.Name.ValueString()) + } + if block.PassiveTrafficEngineeringRemoteNodeRouterID.ValueString() != "" { + return configSet, + pathRoot.AtName("passive_traffic_engineering_remote_node_router_id"), + fmt.Errorf("passive must be specified with passive_traffic_engineering_remote_node_router_id"+ + " in interface block %q", block.Name.ValueString()) + } + } + if !block.PollInterval.IsNull() { + configSet = append(configSet, setPrefix+"poll-interval "+ + utils.ConvI64toa(block.PollInterval.ValueInt64())) + } + if !block.Priority.IsNull() { + configSet = append(configSet, setPrefix+"priority "+ + utils.ConvI64toa(block.Priority.ValueInt64())) + } + if !block.RetransmitInterval.IsNull() { + configSet = append(configSet, setPrefix+"retransmit-interval "+ + utils.ConvI64toa(block.RetransmitInterval.ValueInt64())) + } + if block.Secondary.ValueBool() { + configSet = append(configSet, setPrefix+"secondary") + } + if block.StrictBfd.ValueBool() { + configSet = append(configSet, setPrefix+"strict-bfd") + } + if !block.TeMetric.IsNull() { + configSet = append(configSet, setPrefix+"te-metric "+ + utils.ConvI64toa(block.TeMetric.ValueInt64())) + } + if !block.TransitDelay.IsNull() { + configSet = append(configSet, setPrefix+"transit-delay "+ + utils.ConvI64toa(block.TransitDelay.ValueInt64())) + } + + authenticationMD5KeyID := make(map[int64]struct{}) + for i, blockAuthenticationMD5 := range block.AuthenticationMD5 { + keyID := blockAuthenticationMD5.KeyID.ValueInt64() + if _, ok := authenticationMD5KeyID[keyID]; ok { + return configSet, + pathRoot.AtName("authentication_md5").AtListIndex(i).AtName("key_id"), + fmt.Errorf("multiple authentication_md5 blocks with the same key_id %d"+ + " in interface block %q", keyID, block.Name.ValueString()) + } + authenticationMD5KeyID[keyID] = struct{}{} + + configSet = append(configSet, setPrefix+"authentication md5 "+ + utils.ConvI64toa(keyID)+" key \""+blockAuthenticationMD5.Key.ValueString()+"\"") + if v := blockAuthenticationMD5.StartTime.ValueString(); v != "" { + configSet = append(configSet, setPrefix+"authentication md5 "+ + utils.ConvI64toa(keyID)+" start-time "+v) + } + } + bandwidthBasedMetricsBandwidth := make(map[string]struct{}) + for _, blockBandwidthBasedMetrics := range block.BandwidthBasedMetrics { + bandwidth := blockBandwidthBasedMetrics.Bandwidth.ValueString() + if _, ok := bandwidthBasedMetricsBandwidth[bandwidth]; ok { + return configSet, + pathRoot.AtName("bandwidth_based_metrics"), + fmt.Errorf("multiple bandwidth_based_metrics blocks with the same bandwidth %q"+ + " in interface block %q", bandwidth, block.Name.ValueString()) + } + bandwidthBasedMetricsBandwidth[bandwidth] = struct{}{} + + configSet = append(configSet, setPrefix+"bandwidth-based-metrics bandwidth "+bandwidth+ + " metric "+utils.ConvI64toa(blockBandwidthBasedMetrics.Metric.ValueInt64())) + } + if block.BfdLivenessDetection != nil { + if block.BfdLivenessDetection.isEmpty() { + return configSet, + path.Root("bfd_liveness_detection").AtName("*"), + fmt.Errorf("bfd_liveness_detection block is empty"+ + " in interface block %q", block.Name.ValueString()) + } + + configSet = append(configSet, block.BfdLivenessDetection.configSet(setPrefix)...) + } + neighborAddress := make(map[string]struct{}) + for _, blockNeighbor := range block.Neighbor { + address := blockNeighbor.Address.ValueString() + if _, ok := neighborAddress[address]; ok { + return configSet, + pathRoot.AtName("neighbor"), + fmt.Errorf("multiple neighbor blocks with the same address %q"+ + " in interface block %q", address, block.Name.ValueString()) + } + neighborAddress[address] = struct{}{} + + configSet = append(configSet, setPrefix+"neighbor "+address) + if blockNeighbor.Eligbile.ValueBool() { + configSet = append(configSet, setPrefix+"neighbor "+address+" eligible") + } + } + + return configSet, path.Empty(), nil +} + +func (block *ospfAreaBlockInterfaceBlockBfdLivenessDetection) configSet(setPrefix string) []string { + configSet := make([]string, 0, 1) + setPrefix += "bfd-liveness-detection " + + if v := block.AuthenticationAlgorithm.ValueString(); v != "" { + configSet = append(configSet, setPrefix+"authentication algorithm "+v) + } + if v := block.AuthenticationKeyChain.ValueString(); v != "" { + configSet = append(configSet, setPrefix+"authentication key-chain \""+v+"\"") + } + if block.AuthenticationLooseCheck.ValueBool() { + configSet = append(configSet, setPrefix+"authentication loose-check") + } + if !block.DetectionTimeThreshold.IsNull() { + configSet = append(configSet, setPrefix+"detection-time threshold "+ + utils.ConvI64toa(block.DetectionTimeThreshold.ValueInt64())) + } + if block.FullNeighborsOnly.ValueBool() { + configSet = append(configSet, setPrefix+"full-neighbors-only") + } + if !block.HolddownInterval.IsNull() { + configSet = append(configSet, setPrefix+"holddown-interval "+ + utils.ConvI64toa(block.HolddownInterval.ValueInt64())) + } + if !block.MinimumInterval.IsNull() { + configSet = append(configSet, setPrefix+"minimum-interval "+ + utils.ConvI64toa(block.MinimumInterval.ValueInt64())) + } + if !block.MinimumReceiveInterval.IsNull() { + configSet = append(configSet, setPrefix+"minimum-receive-interval "+ + utils.ConvI64toa(block.MinimumReceiveInterval.ValueInt64())) + } + if !block.Multiplier.IsNull() { + configSet = append(configSet, setPrefix+"multiplier "+ + utils.ConvI64toa(block.Multiplier.ValueInt64())) + } + if block.NoAdaptation.ValueBool() { + configSet = append(configSet, setPrefix+"no-adaptation") + } + if !block.TransmitIntervalMinimumInterval.IsNull() { + configSet = append(configSet, setPrefix+"transmit-interval minimum-interval "+ + utils.ConvI64toa(block.TransmitIntervalMinimumInterval.ValueInt64())) + } + if !block.TransmitIntervalThreshold.IsNull() { + configSet = append(configSet, setPrefix+"transmit-interval threshold "+ + utils.ConvI64toa(block.TransmitIntervalThreshold.ValueInt64())) + } + if v := block.Version.ValueString(); v != "" { + configSet = append(configSet, setPrefix+"version "+v) + } + + return configSet +} + +func (block *ospfAreaBlockAreaRange) configSet(setPrefix string) []string { + setPrefix += "area-range " + block.Range.ValueString() + " " + configSet := []string{ + setPrefix, + } + + if block.Exact.ValueBool() { + configSet = append(configSet, setPrefix+"exact") + } + if !block.OverrideMetric.IsNull() { + configSet = append(configSet, setPrefix+"override-metric "+ + utils.ConvI64toa(block.OverrideMetric.ValueInt64())) + } + if block.Restrict.ValueBool() { + configSet = append(configSet, setPrefix+"restrict") + } + + return configSet +} + +func (block *ospfAreaBlockNssa) configSet( + setPrefix string, pathRoot path.Path, +) ( + []string, // configSet + path.Path, // pathErr + error, // error +) { + setPrefix += "nssa " + configSet := []string{ + setPrefix, + } + + if block.Summaries.ValueBool() { + configSet = append(configSet, setPrefix+"summaries") + } + if block.NoSummaries.ValueBool() { + configSet = append(configSet, setPrefix+"no-summaries") + } + areaRangeRange := make(map[string]struct{}) + for _, blockAreaRange := range block.AreaRange { + rangeValue := blockAreaRange.Range.ValueString() + if _, ok := areaRangeRange[rangeValue]; ok { + return configSet, + pathRoot.AtName("area_range"), + fmt.Errorf("multiple area_range blocks with the same range %q"+ + " in nssa block", rangeValue) + } + areaRangeRange[rangeValue] = struct{}{} + + configSet = append(configSet, blockAreaRange.configSet(setPrefix)...) + } + if block.DefaultLsa != nil { + configSet = append(configSet, setPrefix+"default-lsa") + + if !block.DefaultLsa.DefaultMetric.IsNull() { + configSet = append(configSet, setPrefix+"default-lsa default-metric "+ + utils.ConvI64toa(block.DefaultLsa.DefaultMetric.ValueInt64())) + } + if !block.DefaultLsa.MetricType.IsNull() { + configSet = append(configSet, setPrefix+"default-lsa metric-type "+ + utils.ConvI64toa(block.DefaultLsa.MetricType.ValueInt64())) + } + if block.DefaultLsa.Type7.ValueBool() { + configSet = append(configSet, setPrefix+"default-lsa type-7") + } + } + + return configSet, path.Empty(), nil +} + +func (block *ospfAreaBlockVirtualLink) configSet(setPrefix string) []string { + setPrefix += "virtual-link" + + " neighbor-id " + block.NeighborID.ValueString() + + " transit-area " + block.TransitArea.ValueString() + + " " + configSet := []string{ + setPrefix, + } + + if !block.DeadInterval.IsNull() { + configSet = append(configSet, setPrefix+"dead-interval "+ + utils.ConvI64toa(block.DeadInterval.ValueInt64())) + } + if block.DemandCircuit.ValueBool() { + configSet = append(configSet, setPrefix+"demand-circuit") + } + if block.Disable.ValueBool() { + configSet = append(configSet, setPrefix+"disable") + } + if block.FloodReduction.ValueBool() { + configSet = append(configSet, setPrefix+"flood-reduction") + } + if !block.HelloInterval.IsNull() { + configSet = append(configSet, setPrefix+"hello-interval "+ + utils.ConvI64toa(block.HelloInterval.ValueInt64())) + } + if v := block.IpsecSA.ValueString(); v != "" { + configSet = append(configSet, setPrefix+"ipsec-sa \""+v+"\"") + } + if !block.Mtu.IsNull() { + configSet = append(configSet, setPrefix+"mtu "+ + utils.ConvI64toa(block.Mtu.ValueInt64())) + } + if !block.RetransmitInterval.IsNull() { + configSet = append(configSet, setPrefix+"retransmit-interval "+ + utils.ConvI64toa(block.RetransmitInterval.ValueInt64())) + } + if !block.TransitDelay.IsNull() { + configSet = append(configSet, setPrefix+"transit-delay "+ + utils.ConvI64toa(block.TransitDelay.ValueInt64())) + } + + return configSet +} + +func (rscData *ospfAreaData) read( + _ context.Context, areaID, version, realm, routingInstance string, junSess *junos.Session, +) ( + err error, +) { + var showConfig string + ospfVersion := junos.OspfV2 + if version == "v3" { + ospfVersion = junos.OspfV3 + } else if realm != "" { + return errors.New("realm can't set if version != v3") + } + switch { + case (routingInstance == junos.DefaultW || routingInstance == "") && realm == "": + showConfig, err = junSess.Command(junos.CmdShowConfig + + "protocols " + ospfVersion + " area " + areaID + junos.PipeDisplaySetRelative) + if err != nil { + return err + } + case (routingInstance == junos.DefaultW || routingInstance == "") && realm != "": + showConfig, err = junSess.Command(junos.CmdShowConfig + + "protocols " + ospfVersion + " realm " + realm + " area " + areaID + junos.PipeDisplaySetRelative) + if err != nil { + return err + } + case realm != "": + showConfig, err = junSess.Command(junos.CmdShowConfig + junos.RoutingInstancesWS + routingInstance + " " + + "protocols " + ospfVersion + " realm " + realm + " area " + areaID + junos.PipeDisplaySetRelative) + if err != nil { + return err + } + default: + showConfig, err = junSess.Command(junos.CmdShowConfig + junos.RoutingInstancesWS + routingInstance + " " + + "protocols " + ospfVersion + " area " + areaID + junos.PipeDisplaySetRelative) + if err != nil { + return err + } + } + + if showConfig != junos.EmptyW { + rscData.AreaID = types.StringValue(areaID) + if version == "v3" { + rscData.Version = types.StringValue(version) + } else { + rscData.Version = types.StringValue("v2") + } + if realm != "" { + rscData.Realm = types.StringValue(realm) + } + if routingInstance != "" { + rscData.RoutingInstance = types.StringValue(routingInstance) + } else { + rscData.RoutingInstance = types.StringValue(junos.DefaultW) + } + rscData.fillID() + for _, item := range strings.Split(showConfig, "\n") { + if strings.Contains(item, junos.XMLStartTagConfigOut) { + continue + } + if strings.Contains(item, junos.XMLEndTagConfigOut) { + break + } + itemTrim := strings.TrimPrefix(item, junos.SetLS) + switch { + case balt.CutPrefixInString(&itemTrim, "context-identifier "): + rscData.ContextIdentifier = append(rscData.ContextIdentifier, + types.StringValue(itemTrim)) + case balt.CutPrefixInString(&itemTrim, "inter-area-prefix-export "): + rscData.InterAreaPrefixExport = append(rscData.InterAreaPrefixExport, + types.StringValue(strings.Trim(itemTrim, "\""))) + case balt.CutPrefixInString(&itemTrim, "inter-area-prefix-import "): + rscData.InterAreaPrefixImport = append(rscData.InterAreaPrefixImport, + types.StringValue(strings.Trim(itemTrim, "\""))) + case balt.CutPrefixInString(&itemTrim, "network-summary-export "): + rscData.NetworkSummaryExport = append(rscData.NetworkSummaryExport, + types.StringValue(strings.Trim(itemTrim, "\""))) + case balt.CutPrefixInString(&itemTrim, "network-summary-import "): + rscData.NetworkSummaryImport = append(rscData.NetworkSummaryImport, + types.StringValue(strings.Trim(itemTrim, "\""))) + case itemTrim == "no-context-identifier-advertisement": + rscData.NoContextIdentifierAdvertisement = types.BoolValue(true) + + case balt.CutPrefixInString(&itemTrim, "interface "): + itemTrimFields := strings.Split(itemTrim, " ") + var interFace ospfAreaBlockInterface + rscData.Interface, interFace = tfdata.ExtractBlockWithTFTypesString( + rscData.Interface, "Name", itemTrimFields[0], + ) + interFace.Name = types.StringValue(itemTrimFields[0]) + balt.CutPrefixInString(&itemTrim, itemTrimFields[0]+" ") + + if err := interFace.read(itemTrim); err != nil { + return err + } + rscData.Interface = append(rscData.Interface, interFace) + case balt.CutPrefixInString(&itemTrim, "area-range "): + itemTrimFields := strings.Split(itemTrim, " ") + var areaRange ospfAreaBlockAreaRange + rscData.AreaRange, areaRange = tfdata.ExtractBlockWithTFTypesString( + rscData.AreaRange, "Range", itemTrimFields[0], + ) + areaRange.Range = types.StringValue(itemTrimFields[0]) + balt.CutPrefixInString(&itemTrim, itemTrimFields[0]+" ") + + if err := areaRange.read(itemTrim); err != nil { + return err + } + rscData.AreaRange = append(rscData.AreaRange, areaRange) + case balt.CutPrefixInString(&itemTrim, "nssa"): + if rscData.Nssa == nil { + rscData.Nssa = &ospfAreaBlockNssa{} + } + + if balt.CutPrefixInString(&itemTrim, " ") { + if err := rscData.Nssa.read(itemTrim); err != nil { + return err + } + } + case balt.CutPrefixInString(&itemTrim, "stub"): + if rscData.Stub == nil { + rscData.Stub = &ospfAreaBlockStub{} + } + + switch { + case balt.CutPrefixInString(&itemTrim, " default-metric "): + rscData.Stub.DefaultMetric, err = tfdata.ConvAtoi64Value(itemTrim) + if err != nil { + return err + } + case itemTrim == " summaries": + rscData.Stub.Summaries = types.BoolValue(true) + case itemTrim == " no-summaries": + rscData.Stub.NoSummaries = types.BoolValue(true) + } + case balt.CutPrefixInString(&itemTrim, "virtual-link "): + itemTrimFields := strings.Split(itemTrim, " ") + if len(itemTrimFields) < 4 { // neighbor-id transit-area + return fmt.Errorf(junos.CantReadValuesNotEnoughFields, "virtual-link", itemTrim) + } + var virtualLink ospfAreaBlockVirtualLink + rscData.VirtualLink, virtualLink = tfdata.ExtractBlockWith2TFTypesString( + rscData.VirtualLink, "NeighborID", itemTrimFields[1], "TransitArea", itemTrimFields[3], + ) + virtualLink.NeighborID = types.StringValue(itemTrimFields[1]) + virtualLink.TransitArea = types.StringValue(itemTrimFields[3]) + balt.CutPrefixInString(&itemTrim, "neighbor-id "+itemTrimFields[1]+" transit-area "+itemTrimFields[3]+" ") + + switch { + case balt.CutPrefixInString(&itemTrim, "dead-interval "): + virtualLink.DeadInterval, err = tfdata.ConvAtoi64Value(itemTrim) + case itemTrim == "demand-circuit": + virtualLink.DemandCircuit = types.BoolValue(true) + case itemTrim == "disable": + virtualLink.Disable = types.BoolValue(true) + case itemTrim == "flood-reduction": + virtualLink.FloodReduction = types.BoolValue(true) + case balt.CutPrefixInString(&itemTrim, "hello-interval "): + virtualLink.HelloInterval, err = tfdata.ConvAtoi64Value(itemTrim) + case balt.CutPrefixInString(&itemTrim, "ipsec-sa "): + virtualLink.IpsecSA = types.StringValue(strings.Trim(itemTrim, "\"")) + case balt.CutPrefixInString(&itemTrim, "mtu "): + virtualLink.Mtu, err = tfdata.ConvAtoi64Value(itemTrim) + case balt.CutPrefixInString(&itemTrim, "retransmit-interval "): + virtualLink.RetransmitInterval, err = tfdata.ConvAtoi64Value(itemTrim) + case balt.CutPrefixInString(&itemTrim, "transit-delay "): + virtualLink.TransitDelay, err = tfdata.ConvAtoi64Value(itemTrim) + } + if err != nil { + return err + } + rscData.VirtualLink = append(rscData.VirtualLink, virtualLink) + } + } + } + + return nil +} + +func (block *ospfAreaBlockInterface) read(itemTrim string) (err error) { + switch { + case balt.CutPrefixInString(&itemTrim, "authentication simple-password "): + block.AuthenticationSimplePassword, err = tfdata.JunosDecode( + strings.Trim(itemTrim, "\""), + "authentication simple-password", + ) + if err != nil { + return err + } + case balt.CutPrefixInString(&itemTrim, "dead-interval "): + block.DeadInterval, err = tfdata.ConvAtoi64Value(itemTrim) + if err != nil { + return err + } + case itemTrim == "demand-circuit": + block.DemandCircuit = types.BoolValue(true) + case itemTrim == junos.DisableW: + block.Disable = types.BoolValue(true) + case itemTrim == "dynamic-neighbors": + block.DynamicNeighbors = types.BoolValue(true) + case itemTrim == "flood-reduction": + block.FloodReduction = types.BoolValue(true) + case balt.CutPrefixInString(&itemTrim, "hello-interval "): + block.HelloInterval, err = tfdata.ConvAtoi64Value(itemTrim) + if err != nil { + return err + } + case balt.CutPrefixInString(&itemTrim, "interface-type "): + block.InterfaceType = types.StringValue(itemTrim) + case balt.CutPrefixInString(&itemTrim, "ipsec-sa "): + block.IpsecSA = types.StringValue(strings.Trim(itemTrim, "\"")) + case balt.CutPrefixInString(&itemTrim, "ipv4-adjacency-segment protected "): + itemTrimFields := strings.Split(itemTrim, " ") + block.IPv4AdjacencySegmentProtectedType = types.StringValue(itemTrimFields[0]) + if len(itemTrimFields) > 1 { // + block.IPv4AdjacencySegmentProtectedValue = types.StringValue(itemTrimFields[1]) + } + case balt.CutPrefixInString(&itemTrim, "ipv4-adjacency-segment unprotected "): + itemTrimFields := strings.Split(itemTrim, " ") + block.IPv4AdjacencySegmentUnprotectedType = types.StringValue(itemTrimFields[0]) + if len(itemTrimFields) > 1 { // + block.IPv4AdjacencySegmentUnprotectedValue = types.StringValue(itemTrimFields[1]) + } + case itemTrim == "link-protection": + block.LinkProtection = types.BoolValue(true) + case balt.CutPrefixInString(&itemTrim, "metric "): + block.Metric, err = tfdata.ConvAtoi64Value(itemTrim) + if err != nil { + return err + } + case balt.CutPrefixInString(&itemTrim, "mtu "): + block.Mtu, err = tfdata.ConvAtoi64Value(itemTrim) + if err != nil { + return err + } + case itemTrim == "no-advertise-adjacency-segment": + block.NoAdvertiseAdjacencySegment = types.BoolValue(true) + case itemTrim == "no-eligible-backup": + block.NoEligibleBackup = types.BoolValue(true) + case itemTrim == "no-eligible-remote-backup": + block.NoEligibleRemoteBackup = types.BoolValue(true) + case itemTrim == "no-interface-state-traps": + block.NoInterfaceStateTraps = types.BoolValue(true) + case itemTrim == "no-neighbor-down-notification": + block.NoNeighborDownNotification = types.BoolValue(true) + case itemTrim == "node-link-protection": + block.NodeLinkProtection = types.BoolValue(true) + case balt.CutPrefixInString(&itemTrim, "passive"): + block.Passive = types.BoolValue(true) + switch { + case balt.CutPrefixInString(&itemTrim, " traffic-engineering remote-node-id "): + block.PassiveTrafficEngineeringRemoteNodeID = types.StringValue(itemTrim) + case balt.CutPrefixInString(&itemTrim, " traffic-engineering remote-node-router-id "): + block.PassiveTrafficEngineeringRemoteNodeRouterID = types.StringValue(itemTrim) + } + case balt.CutPrefixInString(&itemTrim, "poll-interval "): + block.PollInterval, err = tfdata.ConvAtoi64Value(itemTrim) + if err != nil { + return err + } + case balt.CutPrefixInString(&itemTrim, "priority "): + block.Priority, err = tfdata.ConvAtoi64Value(itemTrim) + if err != nil { + return err + } + case balt.CutPrefixInString(&itemTrim, "retransmit-interval "): + block.RetransmitInterval, err = tfdata.ConvAtoi64Value(itemTrim) + if err != nil { + return err + } + case itemTrim == "secondary": + block.Secondary = types.BoolValue(true) + case itemTrim == "strict-bfd": + block.StrictBfd = types.BoolValue(true) + case balt.CutPrefixInString(&itemTrim, "te-metric "): + block.TeMetric, err = tfdata.ConvAtoi64Value(itemTrim) + if err != nil { + return err + } + case balt.CutPrefixInString(&itemTrim, "transit-delay "): + block.TransitDelay, err = tfdata.ConvAtoi64Value(itemTrim) + if err != nil { + return err + } + + case balt.CutPrefixInString(&itemTrim, "authentication md5 "): + itemTrimFields := strings.Split(itemTrim, " ") + keyID, err := tfdata.ConvAtoi64Value(itemTrimFields[0]) + if err != nil { + return err + } + var authenticationMD5 ospfAreaBlockInterfaceBlockAuthenticationMD5 + block.AuthenticationMD5, authenticationMD5 = tfdata.ExtractBlockWithTFTypesInt64( + block.AuthenticationMD5, "KeyID", keyID.ValueInt64(), + ) + authenticationMD5.KeyID = keyID + balt.CutPrefixInString(&itemTrim, itemTrimFields[0]+" ") + + switch { + case balt.CutPrefixInString(&itemTrim, "key "): + authenticationMD5.Key, err = tfdata.JunosDecode(strings.Trim(itemTrim, "\""), "authentication md5 key") + if err != nil { + return err + } + case balt.CutPrefixInString(&itemTrim, "start-time "): + authenticationMD5.StartTime = types.StringValue(strings.Split(strings.Trim(itemTrim, "\""), " ")[0]) + } + block.AuthenticationMD5 = append(block.AuthenticationMD5, authenticationMD5) + case balt.CutPrefixInString(&itemTrim, "bandwidth-based-metrics bandwidth "): + itemTrimFields := strings.Split(itemTrim, " ") + if len(itemTrimFields) < 3 { // metric + return fmt.Errorf(junos.CantReadValuesNotEnoughFields, "bandwidth-based-metrics bandwidth", itemTrim) + } + metric, err := tfdata.ConvAtoi64Value(itemTrimFields[2]) + if err != nil { + return err + } + + block.BandwidthBasedMetrics = append(block.BandwidthBasedMetrics, ospfAreaBlockInterfaceBlockBandwidthBasedMetrics{ + Bandwidth: types.StringValue(itemTrimFields[0]), + Metric: metric, + }) + case balt.CutPrefixInString(&itemTrim, "bfd-liveness-detection "): + if block.BfdLivenessDetection == nil { + block.BfdLivenessDetection = &ospfAreaBlockInterfaceBlockBfdLivenessDetection{} + } + + if err := block.BfdLivenessDetection.read(itemTrim); err != nil { + return err + } + case balt.CutPrefixInString(&itemTrim, "neighbor "): + itemTrimFields := strings.Split(itemTrim, " ") //
(eligible)? + block.Neighbor = append(block.Neighbor, ospfAreaBlockInterfaceBlockNeighbor{ + Address: types.StringValue(itemTrimFields[0]), + }) + if len(itemTrimFields) > 1 && itemTrimFields[1] == "eligible" { + block.Neighbor[len(block.Neighbor)-1].Eligbile = types.BoolValue(true) + } + } + + return nil +} + +func (block *ospfAreaBlockInterfaceBlockBfdLivenessDetection) read(itemTrim string) (err error) { + switch { + case balt.CutPrefixInString(&itemTrim, "authentication algorithm "): + block.AuthenticationAlgorithm = types.StringValue(itemTrim) + case balt.CutPrefixInString(&itemTrim, "authentication key-chain "): + block.AuthenticationKeyChain = types.StringValue(strings.Trim(itemTrim, "\"")) + case itemTrim == "authentication loose-check": + block.AuthenticationLooseCheck = types.BoolValue(true) + case balt.CutPrefixInString(&itemTrim, "detection-time threshold "): + block.DetectionTimeThreshold, err = tfdata.ConvAtoi64Value(itemTrim) + if err != nil { + return err + } + case itemTrim == "full-neighbors-only": + block.FullNeighborsOnly = types.BoolValue(true) + case balt.CutPrefixInString(&itemTrim, "holddown-interval "): + block.HolddownInterval, err = tfdata.ConvAtoi64Value(itemTrim) + if err != nil { + return err + } + case balt.CutPrefixInString(&itemTrim, "minimum-interval "): + block.MinimumInterval, err = tfdata.ConvAtoi64Value(itemTrim) + if err != nil { + return err + } + case balt.CutPrefixInString(&itemTrim, "minimum-receive-interval "): + block.MinimumReceiveInterval, err = tfdata.ConvAtoi64Value(itemTrim) + if err != nil { + return err + } + case balt.CutPrefixInString(&itemTrim, "multiplier "): + block.Multiplier, err = tfdata.ConvAtoi64Value(itemTrim) + if err != nil { + return err + } + case itemTrim == "no-adaptation": + block.NoAdaptation = types.BoolValue(true) + case balt.CutPrefixInString(&itemTrim, "transmit-interval minimum-interval "): + block.TransmitIntervalMinimumInterval, err = tfdata.ConvAtoi64Value(itemTrim) + if err != nil { + return err + } + case balt.CutPrefixInString(&itemTrim, "transmit-interval threshold "): + block.TransmitIntervalThreshold, err = tfdata.ConvAtoi64Value(itemTrim) + if err != nil { + return err + } + case balt.CutPrefixInString(&itemTrim, "version "): + block.Version = types.StringValue(itemTrim) + } + + return nil +} + +func (block *ospfAreaBlockAreaRange) read(itemTrim string) (err error) { + switch { + case itemTrim == "exact": + block.Exact = types.BoolValue(true) + case balt.CutPrefixInString(&itemTrim, "override-metric "): + block.OverrideMetric, err = tfdata.ConvAtoi64Value(itemTrim) + if err != nil { + return err + } + case itemTrim == "restrict": + block.Restrict = types.BoolValue(true) + } + + return nil +} + +func (block *ospfAreaBlockNssa) read(itemTrim string) (err error) { + switch { + case itemTrim == "summaries": + block.Summaries = types.BoolValue(true) + case itemTrim == "no-summaries": + block.NoSummaries = types.BoolValue(true) + + case balt.CutPrefixInString(&itemTrim, "area-range "): + itemTrimFields := strings.Split(itemTrim, " ") + var areaRange ospfAreaBlockAreaRange + block.AreaRange, areaRange = tfdata.ExtractBlockWithTFTypesString( + block.AreaRange, "Range", itemTrimFields[0], + ) + areaRange.Range = types.StringValue(itemTrimFields[0]) + balt.CutPrefixInString(&itemTrim, itemTrimFields[0]+" ") + + if err := areaRange.read(itemTrim); err != nil { + return err + } + block.AreaRange = append(block.AreaRange, areaRange) + case balt.CutPrefixInString(&itemTrim, "default-lsa"): + if block.DefaultLsa == nil { + block.DefaultLsa = &ospfAreaBlockNssaBlockDefaultLsa{} + } + + switch { + case balt.CutPrefixInString(&itemTrim, " default-metric "): + block.DefaultLsa.DefaultMetric, err = tfdata.ConvAtoi64Value(itemTrim) + if err != nil { + return err + } + case balt.CutPrefixInString(&itemTrim, " metric-type "): + block.DefaultLsa.MetricType, err = tfdata.ConvAtoi64Value(itemTrim) + if err != nil { + return err + } + case itemTrim == " type-7": + block.DefaultLsa.Type7 = types.BoolValue(true) + } + } + + return nil +} + +func (rscData *ospfAreaData) del( + _ context.Context, junSess *junos.Session, +) error { + configSet := make([]string, 0, 1) + ospfVersion := junos.OspfV2 + if rscData.Version.ValueString() == "v3" { + ospfVersion = junos.OspfV3 + } else if rscData.Realm.ValueString() != "" { + return errors.New("realm can't set if version != v3") + } + routingInstance := junos.DefaultW + if v := rscData.RoutingInstance.ValueString(); v != "" { + routingInstance = v + } + realm := rscData.Realm.ValueString() + switch { + case (routingInstance == junos.DefaultW || routingInstance == "") && realm == "": + configSet = append(configSet, junos.DeleteW+ + " protocols "+ospfVersion+" area "+rscData.AreaID.ValueString()) + case (routingInstance == junos.DefaultW || routingInstance == "") && realm != "": + configSet = append(configSet, junos.DeleteW+ + " protocols "+ospfVersion+" realm "+realm+" area "+rscData.AreaID.ValueString()) + case realm != "": + configSet = append(configSet, junos.DelRoutingInstances+routingInstance+ + " protocols "+ospfVersion+" realm "+realm+" area "+rscData.AreaID.ValueString()) + default: + configSet = append(configSet, junos.DelRoutingInstances+routingInstance+ + " protocols "+ospfVersion+" area "+rscData.AreaID.ValueString()) + } + + return junSess.ConfigSet(configSet) +} diff --git a/internal/providerfwk/resource_ospf_area_test.go b/internal/providerfwk/resource_ospf_area_test.go new file mode 100644 index 00000000..ca240851 --- /dev/null +++ b/internal/providerfwk/resource_ospf_area_test.go @@ -0,0 +1,172 @@ +package providerfwk_test + +import ( + "os" + "testing" + + "github.com/jeremmfr/terraform-provider-junos/internal/junos" + + "github.com/hashicorp/terraform-plugin-testing/config" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" +) + +// export TESTACC_INTERFACE= for choose interface available else it's ge-0/0/3. +// export TESTACC_INTERFACE2= for choose 2nd interface available else it's ge-0/0/4. +func TestAccResourceOspfArea_basic(t *testing.T) { + testaccInterface := junos.DefaultInterfaceTestAcc + testaccInterface2 := junos.DefaultInterfaceTestAcc2 + if iface := os.Getenv("TESTACC_INTERFACE"); iface != "" { + testaccInterface = iface + } + if iface := os.Getenv("TESTACC_INTERFACE2"); iface != "" { + testaccInterface2 = iface + } + if os.Getenv("TESTACC_SWITCH") == "" { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProtoV5ProviderFactories: testAccProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + // 1 + ConfigDirectory: config.TestStepDirectory(), + ConfigVariables: map[string]config.Variable{ + "interface": config.StringVariable(testaccInterface), + }, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("junos_ospf_area.testacc_ospfarea", + "area_id", "0.0.0.0"), + resource.TestCheckResourceAttr("junos_ospf_area.testacc_ospfarea", + "version", "v2"), + resource.TestCheckResourceAttr("junos_ospf_area.testacc_ospfarea", + "routing_instance", "default"), + resource.TestCheckResourceAttr("junos_ospf_area.testacc_ospfarea", + "interface.#", "2"), + resource.TestCheckResourceAttr("junos_ospf_area.testacc_ospfarea", + "interface.0.name", "all"), + resource.TestCheckResourceAttr("junos_ospf_area.testacc_ospfarea", + "interface.0.disable", "true"), + resource.TestCheckResourceAttr("junos_ospf_area.testacc_ospfarea", + "interface.0.passive", "true"), + resource.TestCheckResourceAttr("junos_ospf_area.testacc_ospfarea", + "interface.0.metric", "100"), + resource.TestCheckResourceAttr("junos_ospf_area.testacc_ospfarea", + "interface.0.retransmit_interval", "12"), + resource.TestCheckResourceAttr("junos_ospf_area.testacc_ospfarea", + "interface.0.hello_interval", "11"), + resource.TestCheckResourceAttr("junos_ospf_area.testacc_ospfarea", + "interface.0.dead_interval", "10"), + ), + }, + { + // 2 + ConfigDirectory: config.TestStepDirectory(), + ConfigVariables: map[string]config.Variable{ + "interface": config.StringVariable(testaccInterface), + "interface2": config.StringVariable(testaccInterface2), + }, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("junos_ospf_area.testacc_ospfarea", + "interface.#", "2"), + resource.TestCheckResourceAttr("junos_ospf_area.testacc_ospfarea2", + "routing_instance", "testacc_ospfarea"), + resource.TestCheckResourceAttr("junos_ospf_area.testacc_ospfarea2", + "version", "v3"), + resource.TestCheckResourceAttr("junos_ospf_area.testacc_ospfarea2", + "interface.#", "2"), + resource.TestCheckResourceAttr("junos_ospf_area.testacc_ospfarea2", + "interface.1.name", testaccInterface2+".0"), + ), + }, + { + // 3 + ResourceName: "junos_ospf_area.testacc_ospfarea", + ImportState: true, + ImportStateVerify: true, + ConfigVariables: map[string]config.Variable{ + "interface": config.StringVariable(testaccInterface), + "interface2": config.StringVariable(testaccInterface2), + }, + }, + { + // 4 + ResourceName: "junos_ospf_area.testacc_ospfarea2", + ImportState: true, + ImportStateVerify: true, + ConfigVariables: map[string]config.Variable{ + "interface": config.StringVariable(testaccInterface), + "interface2": config.StringVariable(testaccInterface2), + }, + }, + { + // 5 + ResourceName: "junos_ospf_area.testacc_ospfareav3ipv4", + ImportState: true, + ImportStateVerify: true, + ConfigVariables: map[string]config.Variable{ + "interface": config.StringVariable(testaccInterface), + "interface2": config.StringVariable(testaccInterface2), + }, + }, + { + // 6 + ResourceName: "junos_ospf_area.testacc_ospfarea2v3realm", + ImportState: true, + ImportStateVerify: true, + ConfigVariables: map[string]config.Variable{ + "interface": config.StringVariable(testaccInterface), + "interface2": config.StringVariable(testaccInterface2), + }, + }, + { + // 7 + ConfigDirectory: config.TestStepDirectory(), + }, + { + // 8 + ConfigDirectory: config.TestStepDirectory(), + }, + { + // 9 + ConfigDirectory: config.TestStepDirectory(), + ConfigVariables: map[string]config.Variable{ + "interface": config.StringVariable(testaccInterface), + }, + }, + { + // 10 + ConfigDirectory: config.TestStepDirectory(), + ConfigVariables: map[string]config.Variable{ + "interface": config.StringVariable(testaccInterface), + }, + }, + { + // 11 + ResourceName: "junos_ospf_area.testacc_ospfarea", + ImportState: true, + ImportStateVerify: true, + ConfigVariables: map[string]config.Variable{ + "interface": config.StringVariable(testaccInterface), + }, + }, + { + // 12 + ResourceName: "junos_ospf_area.testacc_ospfarea2", + ImportState: true, + ImportStateVerify: true, + ConfigVariables: map[string]config.Variable{ + "interface": config.StringVariable(testaccInterface), + }, + }, + { + // 13 + ResourceName: "junos_ospf_area.testacc_ospfarea3", + ImportState: true, + ImportStateVerify: true, + ConfigVariables: map[string]config.Variable{ + "interface": config.StringVariable(testaccInterface), + }, + }, + }, + }) + } +} diff --git a/internal/providerfwk/testdata/TestAccResourceOspfArea_basic/1/main.tf b/internal/providerfwk/testdata/TestAccResourceOspfArea_basic/1/main.tf new file mode 100644 index 00000000..83ee0c4d --- /dev/null +++ b/internal/providerfwk/testdata/TestAccResourceOspfArea_basic/1/main.tf @@ -0,0 +1,34 @@ +resource "junos_ospf_area" "testacc_ospfarea" { + area_id = "0.0.0.0" + interface { + name = "all" + disable = true + passive = true + metric = 100 + retransmit_interval = 12 + hello_interval = 11 + dead_interval = 10 + } + interface { + name = junos_interface_logical.testacc_ospfarea.name + secondary = true + } +} +resource "junos_ospf_area" "testacc_ospfareav3ipv4" { + area_id = "0" + version = "v3" + realm = "ipv4-unicast" + interface { + name = "all" + disable = true + } + interface { + name = junos_interface_logical.testacc_ospfarea.name + secondary = true + } +} +resource "junos_interface_logical" "testacc_ospfarea" { + name = "${var.interface}.0" + description = "testacc_ospfarea" +} + diff --git a/internal/providerfwk/testdata/TestAccResourceOspfArea_basic/1/variables.tf b/internal/providerfwk/testdata/TestAccResourceOspfArea_basic/1/variables.tf new file mode 100644 index 00000000..d5ed041c --- /dev/null +++ b/internal/providerfwk/testdata/TestAccResourceOspfArea_basic/1/variables.tf @@ -0,0 +1,3 @@ +variable "interface" { + type = string +} diff --git a/internal/providerfwk/testdata/TestAccResourceOspfArea_basic/10/main.tf b/internal/providerfwk/testdata/TestAccResourceOspfArea_basic/10/main.tf new file mode 100644 index 00000000..e2aa7ec2 --- /dev/null +++ b/internal/providerfwk/testdata/TestAccResourceOspfArea_basic/10/main.tf @@ -0,0 +1,86 @@ +resource "junos_ospf_area" "testacc_ospfarea" { + area_id = "1" + version = "v3" + interface { + name = "all" + } + area_range { + range = "fe80:f::/64" + exact = true + } + area_range { + range = "fe80:e::/64" + exact = true + override_metric = 106 + } + area_range { + range = "fe80::/64" + restrict = true + } + context_identifier = ["127.0.0.2", "127.0.0.1"] + inter_area_prefix_export = [ + junos_policyoptions_policy_statement.testacc_ospfarea.name, + junos_policyoptions_policy_statement.testacc_ospfarea2.name, + ] + inter_area_prefix_import = [ + junos_policyoptions_policy_statement.testacc_ospfarea2.name, + junos_policyoptions_policy_statement.testacc_ospfarea.name, + ] + nssa { + area_range { + range = "fe80::/64" + exact = true + } + area_range { + range = "fe80:b::/64" + override_metric = 107 + } + area_range { + range = "fe80:a::/64" + restrict = true + } + default_lsa { + default_metric = 109 + metric_type = 2 + type_7 = true + } + summaries = true + } +} +resource "junos_policyoptions_policy_statement" "testacc_ospfarea" { + name = "testacc_ospfarea" + then { + action = "accept" + } +} +resource "junos_policyoptions_policy_statement" "testacc_ospfarea2" { + name = "testacc_ospfarea2" + then { + action = "reject" + } +} +resource "junos_ospf_area" "testacc_ospfarea2" { + area_id = "2" + version = "v3" + interface { + name = "${var.interface}.0" + passive = true + } + stub { + default_metric = 150 + no_summaries = true + } +} +resource "junos_ospf_area" "testacc_ospfarea3" { + area_id = "3" + version = "v3" + realm = "ipv4-unicast" + interface { + name = "${var.interface}.0" + passive = true + } + nssa { + no_summaries = true + default_lsa {} + } +} diff --git a/internal/providerfwk/testdata/TestAccResourceOspfArea_basic/10/variables.tf b/internal/providerfwk/testdata/TestAccResourceOspfArea_basic/10/variables.tf new file mode 100644 index 00000000..d5ed041c --- /dev/null +++ b/internal/providerfwk/testdata/TestAccResourceOspfArea_basic/10/variables.tf @@ -0,0 +1,3 @@ +variable "interface" { + type = string +} diff --git a/internal/providerfwk/testdata/TestAccResourceOspfArea_basic/2/main.tf b/internal/providerfwk/testdata/TestAccResourceOspfArea_basic/2/main.tf new file mode 100644 index 00000000..787cf86f --- /dev/null +++ b/internal/providerfwk/testdata/TestAccResourceOspfArea_basic/2/main.tf @@ -0,0 +1,150 @@ +resource "junos_ospf_area" "testacc_ospfarea" { + area_id = "0.0.0.0" + interface { + name = "all" + passive = true + authentication_simple_password = "testPass" + link_protection = true + no_advertise_adjacency_segment = true + no_interface_state_traps = true + no_neighbor_down_notification = true + poll_interval = 19 + te_metric = 221 + } + interface { + name = junos_interface_logical.testacc_ospfarea.name + disable = true + authentication_md5 { + key_id = 3 + key = "testK3y" + } + authentication_md5 { + key_id = 2 + key = "testK3y2" + start_time = "2022-3-9.12:50:00" + } + strict_bfd = true + bfd_liveness_detection { + minimum_receive_interval = 29 + transmit_interval_minimum_interval = 48 + transmit_interval_threshold = 49 + version = "automatic" + } + neighbor { + address = "192.0.2.6" + } + neighbor { + address = "192.0.2.5" + eligible = "true" + } + } + network_summary_export = [junos_policyoptions_policy_statement.testacc_ospfarea.name] + network_summary_import = [junos_policyoptions_policy_statement.testacc_ospfarea2.name] +} +resource "junos_policyoptions_policy_statement" "testacc_ospfarea" { + name = "testacc_ospfarea" + then { + action = "accept" + } +} +resource "junos_policyoptions_policy_statement" "testacc_ospfarea2" { + name = "testacc_ospfarea2" + then { + action = "reject" + } +} +resource "junos_ospf_area" "testacc_ospfareav3ipv4" { + area_id = "0" + version = "v3" + realm = "ipv4-unicast" + interface { + name = junos_interface_logical.testacc_ospfarea.name + priority = 0 + bfd_liveness_detection { + full_neighbors_only = true + minimum_receive_interval = 27 + transmit_interval_minimum_interval = 50 + transmit_interval_threshold = 51 + } + } +} +resource "junos_interface_logical" "testacc_ospfarea" { + name = "${var.interface}.0" + description = "testacc_ospfarea" +} +resource "junos_interface_logical" "testacc_ospfarea2" { + name = "${var.interface2}.0" + description = "testacc_ospfarea2" + routing_instance = junos_routing_instance.testacc_ospfarea.name +} +resource "junos_routing_instance" "testacc_ospfarea" { + name = "testacc_ospfarea" +} +resource "junos_ospf_area" "testacc_ospfarea2" { + area_id = "0.0.0.0" + version = "v3" + routing_instance = junos_routing_instance.testacc_ospfarea.name + interface { + name = "all" + passive = true + metric = 100 + retransmit_interval = 32 + hello_interval = 31 + dead_interval = 30 + bandwidth_based_metrics { + bandwidth = "100k" + metric = 13 + } + bandwidth_based_metrics { + bandwidth = "1m" + metric = 14 + } + demand_circuit = true + dynamic_neighbors = true + flood_reduction = true + interface_type = "p2mp" + mtu = 900 + no_eligible_backup = true + no_eligible_remote_backup = true + node_link_protection = true + passive_traffic_engineering_remote_node_id = "192.0.2.7" + passive_traffic_engineering_remote_node_router_id = "192.0.2.8" + priority = 21 + transit_delay = 23 + } + interface { + name = junos_interface_logical.testacc_ospfarea2.name + bfd_liveness_detection { + authentication_loose_check = true + detection_time_threshold = 60 + full_neighbors_only = true + holddown_interval = 15 + minimum_interval = 16 + minimum_receive_interval = 17 + multiplier = 2 + no_adaptation = true + transmit_interval_minimum_interval = 18 + transmit_interval_threshold = 19 + version = "automatic" + } + } +} +resource "junos_ospf_area" "testacc_ospfarea2v3realm" { + area_id = "0.0.0.0" + version = "v3" + realm = "ipv4-multicast" + routing_instance = junos_routing_instance.testacc_ospfarea.name + interface { + name = "all" + passive = true + } + interface { + name = junos_interface_logical.testacc_ospfarea2.name + bfd_liveness_detection { + version = "automatic" + minimum_receive_interval = 270 + transmit_interval_minimum_interval = 500 + transmit_interval_threshold = 510 + } + } +} diff --git a/internal/providerfwk/testdata/TestAccResourceOspfArea_basic/2/variables.tf b/internal/providerfwk/testdata/TestAccResourceOspfArea_basic/2/variables.tf new file mode 100644 index 00000000..8ea1ebce --- /dev/null +++ b/internal/providerfwk/testdata/TestAccResourceOspfArea_basic/2/variables.tf @@ -0,0 +1,7 @@ +variable "interface" { + type = string +} + +variable "interface2" { + type = string +} diff --git a/internal/providerfwk/testdata/TestAccResourceOspfArea_basic/7/main.tf b/internal/providerfwk/testdata/TestAccResourceOspfArea_basic/7/main.tf new file mode 100644 index 00000000..5849c297 --- /dev/null +++ b/internal/providerfwk/testdata/TestAccResourceOspfArea_basic/7/main.tf @@ -0,0 +1,12 @@ +resource "junos_ospf_area" "testacc_ospfarea" { + area_id = "0.0.0.0" + version = "v3" + interface { + name = "all" + disable = true + } + virtual_link { + neighbor_id = "192.0.2.0" + transit_area = "192.0.2.1" + } +} diff --git a/internal/providerfwk/testdata/TestAccResourceOspfArea_basic/8/main.tf b/internal/providerfwk/testdata/TestAccResourceOspfArea_basic/8/main.tf new file mode 100644 index 00000000..40203b3e --- /dev/null +++ b/internal/providerfwk/testdata/TestAccResourceOspfArea_basic/8/main.tf @@ -0,0 +1,25 @@ +resource "junos_ospf_area" "testacc_ospfarea" { + area_id = "0.0.0.0" + version = "v3" + interface { + name = "all" + disable = true + } + virtual_link { + neighbor_id = "192.0.2.100" + transit_area = "192.0.2.101" + dead_interval = 102 + demand_circuit = true + disable = true + flood_reduction = true + hello_interval = 103 + mtu = 1040 + retransmit_interval = 105 + transit_delay = 106 + + } + virtual_link { + neighbor_id = "192.0.2.0" + transit_area = "192.0.2.1" + } +} diff --git a/internal/providerfwk/testdata/TestAccResourceOspfArea_basic/9/main.tf b/internal/providerfwk/testdata/TestAccResourceOspfArea_basic/9/main.tf new file mode 100644 index 00000000..7d7c6bd7 --- /dev/null +++ b/internal/providerfwk/testdata/TestAccResourceOspfArea_basic/9/main.tf @@ -0,0 +1,39 @@ +resource "junos_ospf_area" "testacc_ospfarea" { + area_id = "1" + version = "v3" + interface { + name = "all" + } + area_range { + range = "fe80::/64" + } + no_context_identifier_advertisement = true + inter_area_prefix_export = [ + junos_policyoptions_policy_statement.testacc_ospfarea2.name, + ] + inter_area_prefix_import = [ + junos_policyoptions_policy_statement.testacc_ospfarea.name, + ] + nssa {} +} +resource "junos_policyoptions_policy_statement" "testacc_ospfarea" { + name = "testacc_ospfarea" + then { + action = "accept" + } +} +resource "junos_policyoptions_policy_statement" "testacc_ospfarea2" { + name = "testacc_ospfarea2" + then { + action = "reject" + } +} +resource "junos_ospf_area" "testacc_ospfarea2" { + area_id = "2" + version = "v3" + interface { + name = "${var.interface}.0" + passive = true + } + stub {} +} diff --git a/internal/providerfwk/testdata/TestAccResourceOspfArea_basic/9/variables.tf b/internal/providerfwk/testdata/TestAccResourceOspfArea_basic/9/variables.tf new file mode 100644 index 00000000..d5ed041c --- /dev/null +++ b/internal/providerfwk/testdata/TestAccResourceOspfArea_basic/9/variables.tf @@ -0,0 +1,3 @@ +variable "interface" { + type = string +} diff --git a/internal/providerfwk/testdata/TestAccUpgradeStateResourceOspfArea_V0toV1_basic/1/main.tf b/internal/providerfwk/testdata/TestAccUpgradeStateResourceOspfArea_V0toV1_basic/1/main.tf new file mode 100644 index 00000000..bab213b1 --- /dev/null +++ b/internal/providerfwk/testdata/TestAccUpgradeStateResourceOspfArea_V0toV1_basic/1/main.tf @@ -0,0 +1,150 @@ +resource "junos_ospf_area" "testacc_ospfarea" { + area_id = "0.0.0.0" + interface { + name = "all" + passive = true + authentication_simple_password = "testPass" + link_protection = true + no_advertise_adjacency_segment = true + no_interface_state_traps = true + no_neighbor_down_notification = true + poll_interval = 19 + te_metric = 221 + } + interface { + name = junos_interface_logical.testacc_ospfarea.name + disable = true + authentication_md5 { + key_id = 3 + key = "testK3y" + } + authentication_md5 { + key_id = 2 + key = "testK3y2" + start_time = "2022-3-9.12:50:00" + } + strict_bfd = true + bfd_liveness_detection { + minimum_receive_interval = 29 + transmit_interval_minimum_interval = 48 + transmit_interval_threshold = 49 + version = "automatic" + } + neighbor { + address = "192.0.2.6" + } + neighbor { + address = "192.0.2.5" + eligible = "true" + } + } + network_summary_export = [junos_policyoptions_policy_statement.testacc_ospfarea.name] + network_summary_import = [junos_policyoptions_policy_statement.testacc_ospfarea2.name] +} +resource "junos_policyoptions_policy_statement" "testacc_ospfarea" { + name = "testacc_ospfarea" + then { + action = "accept" + } +} +resource "junos_policyoptions_policy_statement" "testacc_ospfarea2" { + name = "testacc_ospfarea2" + then { + action = "reject" + } +} +resource "junos_ospf_area" "testacc_ospfareav3ipv4" { + area_id = "0.0.0.0" + version = "v3" + realm = "ipv4-unicast" + interface { + name = junos_interface_logical.testacc_ospfarea.name + priority = 0 + bfd_liveness_detection { + full_neighbors_only = true + minimum_receive_interval = 27 + transmit_interval_minimum_interval = 50 + transmit_interval_threshold = 51 + } + } +} +resource "junos_interface_logical" "testacc_ospfarea" { + name = "${var.interface}.0" + description = "testacc_ospfarea" +} +resource "junos_interface_logical" "testacc_ospfarea2" { + name = "${var.interface2}.0" + description = "testacc_ospfarea2" + routing_instance = junos_routing_instance.testacc_ospfarea.name +} +resource "junos_routing_instance" "testacc_ospfarea" { + name = "testacc_ospfarea" +} +resource "junos_ospf_area" "testacc_ospfarea2" { + area_id = "0.0.0.0" + version = "v3" + routing_instance = junos_routing_instance.testacc_ospfarea.name + interface { + name = "all" + passive = true + metric = 100 + retransmit_interval = 32 + hello_interval = 31 + dead_interval = 30 + bandwidth_based_metrics { + bandwidth = "100k" + metric = 13 + } + bandwidth_based_metrics { + bandwidth = "1m" + metric = 14 + } + demand_circuit = true + dynamic_neighbors = true + flood_reduction = true + interface_type = "p2mp" + mtu = 900 + no_eligible_backup = true + no_eligible_remote_backup = true + node_link_protection = true + passive_traffic_engineering_remote_node_id = "192.0.2.7" + passive_traffic_engineering_remote_node_router_id = "192.0.2.8" + priority = 21 + transit_delay = 23 + } + interface { + name = junos_interface_logical.testacc_ospfarea2.name + bfd_liveness_detection { + authentication_loose_check = true + detection_time_threshold = 60 + full_neighbors_only = true + holddown_interval = 15 + minimum_interval = 16 + minimum_receive_interval = 17 + multiplier = 2 + no_adaptation = true + transmit_interval_minimum_interval = 18 + transmit_interval_threshold = 19 + version = "automatic" + } + } +} +resource "junos_ospf_area" "testacc_ospfarea2v3realm" { + area_id = "0.0.0.0" + version = "v3" + realm = "ipv4-multicast" + routing_instance = junos_routing_instance.testacc_ospfarea.name + interface { + name = "all" + passive = true + } + interface { + name = junos_interface_logical.testacc_ospfarea2.name + bfd_liveness_detection { + version = "automatic" + minimum_receive_interval = 270 + transmit_interval_minimum_interval = 500 + transmit_interval_threshold = 510 + } + } +} diff --git a/internal/providerfwk/testdata/TestAccUpgradeStateResourceOspfArea_V0toV1_basic/1/provider.tf b/internal/providerfwk/testdata/TestAccUpgradeStateResourceOspfArea_V0toV1_basic/1/provider.tf new file mode 100644 index 00000000..713fa309 --- /dev/null +++ b/internal/providerfwk/testdata/TestAccUpgradeStateResourceOspfArea_V0toV1_basic/1/provider.tf @@ -0,0 +1,10 @@ +terraform { + required_providers { + junos = { + source = "registry.terraform.io/jeremmfr/junos" + version = "1.33.0" + } + } +} + +provider "junos" {} diff --git a/internal/providerfwk/testdata/TestAccUpgradeStateResourceOspfArea_V0toV1_basic/1/variables.tf b/internal/providerfwk/testdata/TestAccUpgradeStateResourceOspfArea_V0toV1_basic/1/variables.tf new file mode 100644 index 00000000..8ea1ebce --- /dev/null +++ b/internal/providerfwk/testdata/TestAccUpgradeStateResourceOspfArea_V0toV1_basic/1/variables.tf @@ -0,0 +1,7 @@ +variable "interface" { + type = string +} + +variable "interface2" { + type = string +} diff --git a/internal/providerfwk/testdata/TestAccUpgradeStateResourceOspfArea_V0toV1_basic/2/main.tf b/internal/providerfwk/testdata/TestAccUpgradeStateResourceOspfArea_V0toV1_basic/2/main.tf new file mode 120000 index 00000000..7a6c4026 --- /dev/null +++ b/internal/providerfwk/testdata/TestAccUpgradeStateResourceOspfArea_V0toV1_basic/2/main.tf @@ -0,0 +1 @@ +../1/main.tf \ No newline at end of file diff --git a/internal/providerfwk/testdata/TestAccUpgradeStateResourceOspfArea_V0toV1_basic/2/variables.tf b/internal/providerfwk/testdata/TestAccUpgradeStateResourceOspfArea_V0toV1_basic/2/variables.tf new file mode 120000 index 00000000..c7b4d96c --- /dev/null +++ b/internal/providerfwk/testdata/TestAccUpgradeStateResourceOspfArea_V0toV1_basic/2/variables.tf @@ -0,0 +1 @@ +../1/variables.tf \ No newline at end of file diff --git a/internal/providerfwk/upgradestate_ospf_area.go b/internal/providerfwk/upgradestate_ospf_area.go new file mode 100644 index 00000000..8af7860e --- /dev/null +++ b/internal/providerfwk/upgradestate_ospf_area.go @@ -0,0 +1,647 @@ +package providerfwk + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/types" +) + +func (rsc *ospfArea) UpgradeState(_ context.Context) map[int64]resource.StateUpgrader { + return map[int64]resource.StateUpgrader{ + 0: { + PriorSchema: &schema.Schema{ + Attributes: map[string]schema.Attribute{ + "id": schema.StringAttribute{ + Computed: true, + }, + "area_id": schema.StringAttribute{ + Required: true, + }, + "version": schema.StringAttribute{ + Optional: true, + Computed: true, + }, + "realm": schema.StringAttribute{ + Optional: true, + }, + "routing_instance": schema.StringAttribute{ + Optional: true, + Computed: true, + }, + "context_identifier": schema.SetAttribute{ + ElementType: types.StringType, + Optional: true, + }, + "inter_area_prefix_export": schema.ListAttribute{ + ElementType: types.StringType, + Optional: true, + }, + "inter_area_prefix_import": schema.ListAttribute{ + ElementType: types.StringType, + Optional: true, + }, + "network_summary_export": schema.ListAttribute{ + ElementType: types.StringType, + Optional: true, + }, + "network_summary_import": schema.ListAttribute{ + ElementType: types.StringType, + Optional: true, + }, + "no_context_identifier_advertisement": schema.BoolAttribute{ + Optional: true, + }, + }, + Blocks: map[string]schema.Block{ + "interface": schema.ListNestedBlock{ + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "name": schema.StringAttribute{ + Required: true, + }, + "authentication_simple_password": schema.StringAttribute{ + Optional: true, + Sensitive: true, + }, + "dead_interval": schema.Int64Attribute{ + Optional: true, + }, + "demand_circuit": schema.BoolAttribute{ + Optional: true, + }, + "disable": schema.BoolAttribute{ + Optional: true, + }, + "dynamic_neighbors": schema.BoolAttribute{ + Optional: true, + }, + "flood_reduction": schema.BoolAttribute{ + Optional: true, + }, + "hello_interval": schema.Int64Attribute{ + Optional: true, + }, + "interface_type": schema.StringAttribute{ + Optional: true, + }, + "ipsec_sa": schema.StringAttribute{ + Optional: true, + }, + "ipv4_adjacency_segment_protected_type": schema.StringAttribute{ + Optional: true, + }, + "ipv4_adjacency_segment_protected_value": schema.StringAttribute{ + Optional: true, + }, + "ipv4_adjacency_segment_unprotected_type": schema.StringAttribute{ + Optional: true, + }, + "ipv4_adjacency_segment_unprotected_value": schema.StringAttribute{ + Optional: true, + }, + "link_protection": schema.BoolAttribute{ + Optional: true, + }, + "metric": schema.Int64Attribute{ + Optional: true, + }, + "mtu": schema.Int64Attribute{ + Optional: true, + }, + "no_advertise_adjacency_segment": schema.BoolAttribute{ + Optional: true, + }, + "no_eligible_backup": schema.BoolAttribute{ + Optional: true, + }, + "no_eligible_remote_backup": schema.BoolAttribute{ + Optional: true, + }, + "no_interface_state_traps": schema.BoolAttribute{ + Optional: true, + }, + "no_neighbor_down_notification": schema.BoolAttribute{ + Optional: true, + }, + "node_link_protection": schema.BoolAttribute{ + Optional: true, + }, + "passive": schema.BoolAttribute{ + Optional: true, + }, + "passive_traffic_engineering_remote_node_id": schema.StringAttribute{ + Optional: true, + }, + "passive_traffic_engineering_remote_node_router_id": schema.StringAttribute{ + Optional: true, + }, + "poll_interval": schema.Int64Attribute{ + Optional: true, + }, + "priority": schema.Int64Attribute{ + Optional: true, + }, + "retransmit_interval": schema.Int64Attribute{ + Optional: true, + }, + "secondary": schema.BoolAttribute{ + Optional: true, + }, + "strict_bfd": schema.BoolAttribute{ + Optional: true, + }, + "te_metric": schema.Int64Attribute{ + Optional: true, + }, + "transit_delay": schema.Int64Attribute{ + Optional: true, + }, + }, + Blocks: map[string]schema.Block{ + "authentication_md5": schema.ListNestedBlock{ + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "key_id": schema.Int64Attribute{ + Required: true, + }, + "key": schema.StringAttribute{ + Required: true, + Sensitive: true, + }, + "start_time": schema.StringAttribute{ + Optional: true, + }, + }, + }, + }, + "bandwidth_based_metrics": schema.SetNestedBlock{ + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "bandwidth": schema.StringAttribute{ + Required: true, + }, + "metric": schema.Int64Attribute{ + Required: true, + }, + }, + }, + }, + "bfd_liveness_detection": schema.ListNestedBlock{ + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "authentication_algorithm": schema.StringAttribute{ + Optional: true, + }, + "authentication_key_chain": schema.StringAttribute{ + Optional: true, + }, + "authentication_loose_check": schema.BoolAttribute{ + Optional: true, + }, + "detection_time_threshold": schema.Int64Attribute{ + Optional: true, + }, + "full_neighbors_only": schema.BoolAttribute{ + Optional: true, + }, + "holddown_interval": schema.Int64Attribute{ + Optional: true, + }, + "minimum_interval": schema.Int64Attribute{ + Optional: true, + }, + "minimum_receive_interval": schema.Int64Attribute{ + Optional: true, + }, + "multiplier": schema.Int64Attribute{ + Optional: true, + }, + "no_adaptation": schema.BoolAttribute{ + Optional: true, + }, + "transmit_interval_minimum_interval": schema.Int64Attribute{ + Optional: true, + }, + "transmit_interval_threshold": schema.Int64Attribute{ + Optional: true, + }, + "version": schema.StringAttribute{ + Optional: true, + }, + }, + }, + }, + "neighbor": schema.SetNestedBlock{ + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "address": schema.StringAttribute{ + Required: true, + }, + "eligible": schema.BoolAttribute{ + Optional: true, + }, + }, + }, + }, + }, + }, + }, + "area_range": schema.SetNestedBlock{ + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "range": schema.StringAttribute{ + Required: true, + }, + "exact": schema.BoolAttribute{ + Optional: true, + }, + "override_metric": schema.Int64Attribute{ + Optional: true, + }, + "restrict": schema.BoolAttribute{ + Optional: true, + }, + }, + }, + }, + "nssa": schema.ListNestedBlock{ + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "summaries": schema.BoolAttribute{ + Optional: true, + }, + "no_summaries": schema.BoolAttribute{ + Optional: true, + }, + }, + Blocks: map[string]schema.Block{ + "area_range": schema.SetNestedBlock{ + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "range": schema.StringAttribute{ + Required: true, + }, + "exact": schema.BoolAttribute{ + Optional: true, + }, + "override_metric": schema.Int64Attribute{ + Optional: true, + }, + "restrict": schema.BoolAttribute{ + Optional: true, + }, + }, + }, + }, + "default_lsa": schema.ListNestedBlock{ + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "default_metric": schema.Int64Attribute{ + Optional: true, + }, + "metric_type": schema.Int64Attribute{ + Optional: true, + }, + "type_7": schema.BoolAttribute{ + Optional: true, + }, + }, + }, + }, + }, + }, + }, + "stub": schema.ListNestedBlock{ + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "default_metric": schema.Int64Attribute{ + Optional: true, + }, + "summaries": schema.BoolAttribute{ + Optional: true, + }, + "no_summaries": schema.BoolAttribute{ + Optional: true, + }, + }, + }, + }, + "virtual_link": schema.SetNestedBlock{ + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "neighbor_id": schema.StringAttribute{ + Required: true, + }, + "transit_area": schema.StringAttribute{ + Required: true, + }, + "dead_interval": schema.Int64Attribute{ + Optional: true, + }, + "demand_circuit": schema.BoolAttribute{ + Optional: true, + }, + "disable": schema.BoolAttribute{ + Optional: true, + }, + "flood_reduction": schema.BoolAttribute{ + Optional: true, + }, + "hello_interval": schema.Int64Attribute{ + Optional: true, + }, + "ipsec_sa": schema.StringAttribute{ + Optional: true, + }, + "mtu": schema.Int64Attribute{ + Optional: true, + }, + "retransmit_interval": schema.Int64Attribute{ + Optional: true, + }, + "transit_delay": schema.Int64Attribute{ + Optional: true, + }, + }, + }, + }, + }, + }, + StateUpgrader: upgradeOspfAreaStateV0toV1, + }, + } +} + +func upgradeOspfAreaStateV0toV1( + ctx context.Context, req resource.UpgradeStateRequest, resp *resource.UpgradeStateResponse, +) { + type modelV0 struct { + ID types.String `tfsdk:"id"` + AreaID types.String `tfsdk:"area_id"` + Version types.String `tfsdk:"version"` + Realm types.String `tfsdk:"realm"` + RoutingInstance types.String `tfsdk:"routing_instance"` + ContextIdentifier []types.String `tfsdk:"context_identifier"` + InterAreaPrefixExport []types.String `tfsdk:"inter_area_prefix_export"` + InterAreaPrefixImport []types.String `tfsdk:"inter_area_prefix_import"` + NetworkSummaryExport []types.String `tfsdk:"network_summary_export"` + NetworkSummaryImport []types.String `tfsdk:"network_summary_import"` + NoContextIdentifierAdvertisement types.Bool `tfsdk:"no_context_identifier_advertisement"` + Interface []struct { + Name types.String `tfsdk:"name"` + AuthenticationSimplePassword types.String `tfsdk:"authentication_simple_password"` + DeadInterval types.Int64 `tfsdk:"dead_interval"` + DemandCircuit types.Bool `tfsdk:"demand_circuit"` + Disable types.Bool `tfsdk:"disable"` + DynamicNeighbors types.Bool `tfsdk:"dynamic_neighbors"` + FloodReduction types.Bool `tfsdk:"flood_reduction"` + HelloInterval types.Int64 `tfsdk:"hello_interval"` + InterfaceType types.String `tfsdk:"interface_type"` + IpsecSA types.String `tfsdk:"ipsec_sa"` + IPv4AdjacencySegmentProtectedType types.String `tfsdk:"ipv4_adjacency_segment_protected_type"` + IPv4AdjacencySegmentProtectedValue types.String `tfsdk:"ipv4_adjacency_segment_protected_value"` + IPv4AdjacencySegmentUnprotectedType types.String `tfsdk:"ipv4_adjacency_segment_unprotected_type"` + IPv4AdjacencySegmentUnprotectedValue types.String `tfsdk:"ipv4_adjacency_segment_unprotected_value"` + LinkProtection types.Bool `tfsdk:"link_protection"` + Metric types.Int64 `tfsdk:"metric"` + Mtu types.Int64 `tfsdk:"mtu"` + NoAdvertiseAdjacencySegment types.Bool `tfsdk:"no_advertise_adjacency_segment"` + NoEligibleBackup types.Bool `tfsdk:"no_eligible_backup"` + NoEligibleRemoteBackup types.Bool `tfsdk:"no_eligible_remote_backup"` + NoInterfaceStateTraps types.Bool `tfsdk:"no_interface_state_traps"` + NoNeighborDownNotification types.Bool `tfsdk:"no_neighbor_down_notification"` + NodeLinkProtection types.Bool `tfsdk:"node_link_protection"` + Passive types.Bool `tfsdk:"passive"` + PassiveTrafficEngineeringRemoteNodeID types.String `tfsdk:"passive_traffic_engineering_remote_node_id"` + PassiveTrafficEngineeringRemoteNodeRouterID types.String `tfsdk:"passive_traffic_engineering_remote_node_router_id"` + PollInterval types.Int64 `tfsdk:"poll_interval"` + Priority types.Int64 `tfsdk:"priority"` + RetransmitInterval types.Int64 `tfsdk:"retransmit_interval"` + Secondary types.Bool `tfsdk:"secondary"` + StrictBfd types.Bool `tfsdk:"strict_bfd"` + TeMetric types.Int64 `tfsdk:"te_metric"` + TransitDelay types.Int64 `tfsdk:"transit_delay"` + AuthenticationMD5 []struct { + KeyID types.Int64 `tfsdk:"key_id"` + Key types.String `tfsdk:"key"` + StartTime types.String `tfsdk:"start_time"` + } `tfsdk:"authentication_md5"` + BandwidthBasedMetrics []struct { + Bandwidth types.String `tfsdk:"bandwidth"` + Metric types.Int64 `tfsdk:"metric"` + } `tfsdk:"bandwidth_based_metrics"` + BfdLivenessDetection []struct { + AuthenticationAlgorithm types.String `tfsdk:"authentication_algorithm"` + AuthenticationKeyChain types.String `tfsdk:"authentication_key_chain"` + AuthenticationLooseCheck types.Bool `tfsdk:"authentication_loose_check"` + DetectionTimeThreshold types.Int64 `tfsdk:"detection_time_threshold"` + FullNeighborsOnly types.Bool `tfsdk:"full_neighbors_only"` + HolddownInterval types.Int64 `tfsdk:"holddown_interval"` + MinimumInterval types.Int64 `tfsdk:"minimum_interval"` + MinimumReceiveInterval types.Int64 `tfsdk:"minimum_receive_interval"` + Multiplier types.Int64 `tfsdk:"multiplier"` + NoAdaptation types.Bool `tfsdk:"no_adaptation"` + TransmitIntervalMinimumInterval types.Int64 `tfsdk:"transmit_interval_minimum_interval"` + TransmitIntervalThreshold types.Int64 `tfsdk:"transmit_interval_threshold"` + Version types.String `tfsdk:"version"` + } `tfsdk:"bfd_liveness_detection"` + Neighbor []struct { + Address types.String `tfsdk:"address"` + Eligbile types.Bool `tfsdk:"eligible"` + } `tfsdk:"neighbor"` + } `tfsdk:"interface"` + AreaRange []struct { + Range types.String `tfsdk:"range"` + Exact types.Bool `tfsdk:"exact"` + OverrideMetric types.Int64 `tfsdk:"override_metric"` + Restrict types.Bool `tfsdk:"restrict"` + } `tfsdk:"area_range"` + Nssa []struct { + Summaries types.Bool `tfsdk:"summaries"` + NoSummaries types.Bool `tfsdk:"no_summaries"` + AreaRange []struct { + Range types.String `tfsdk:"range"` + Exact types.Bool `tfsdk:"exact"` + OverrideMetric types.Int64 `tfsdk:"override_metric"` + Restrict types.Bool `tfsdk:"restrict"` + } `tfsdk:"area_range"` + DefaultLsa []struct { + DefaultMetric types.Int64 `tfsdk:"default_metric"` + MetricType types.Int64 `tfsdk:"metric_type"` + Type7 types.Bool `tfsdk:"type_7"` + } `tfsdk:"default_lsa"` + } `tfsdk:"nssa"` + Stub []struct { + DefaultMetric types.Int64 `tfsdk:"default_metric"` + Summaries types.Bool `tfsdk:"summaries"` + NoSummaries types.Bool `tfsdk:"no_summaries"` + } `tfsdk:"stub"` + VirtualLink []struct { + NeighborID types.String `tfsdk:"neighbor_id"` + TransitArea types.String `tfsdk:"transit_area"` + DeadInterval types.Int64 `tfsdk:"dead_interval"` + DemandCircuit types.Bool `tfsdk:"demand_circuit"` + Disable types.Bool `tfsdk:"disable"` + FloodReduction types.Bool `tfsdk:"flood_reduction"` + HelloInterval types.Int64 `tfsdk:"hello_interval"` + IpsecSA types.String `tfsdk:"ipsec_sa"` + Mtu types.Int64 `tfsdk:"mtu"` + RetransmitInterval types.Int64 `tfsdk:"retransmit_interval"` + TransitDelay types.Int64 `tfsdk:"transit_delay"` + } `tfsdk:"virtual_link"` + } + + var dataV0 modelV0 + resp.Diagnostics.Append(req.State.Get(ctx, &dataV0)...) + if resp.Diagnostics.HasError() { + return + } + + var dataV1 ospfAreaData + dataV1.ID = dataV0.ID + dataV1.AreaID = dataV0.AreaID + dataV1.Version = dataV0.Version + dataV1.Realm = dataV0.Realm + dataV1.RoutingInstance = dataV0.RoutingInstance + dataV1.ContextIdentifier = dataV0.ContextIdentifier + dataV1.InterAreaPrefixExport = dataV0.InterAreaPrefixExport + dataV1.InterAreaPrefixImport = dataV0.InterAreaPrefixImport + dataV1.NetworkSummaryExport = dataV0.NetworkSummaryExport + dataV1.NetworkSummaryImport = dataV0.NetworkSummaryImport + dataV1.NoContextIdentifierAdvertisement = dataV0.NoContextIdentifierAdvertisement + for _, blockV0 := range dataV0.Interface { + blockV1 := ospfAreaBlockInterface{ + Name: blockV0.Name, + AuthenticationSimplePassword: blockV0.AuthenticationSimplePassword, + DeadInterval: blockV0.DeadInterval, + DemandCircuit: blockV0.DemandCircuit, + Disable: blockV0.Disable, + DynamicNeighbors: blockV0.DynamicNeighbors, + FloodReduction: blockV0.FloodReduction, + HelloInterval: blockV0.HelloInterval, + InterfaceType: blockV0.InterfaceType, + IpsecSA: blockV0.IpsecSA, + IPv4AdjacencySegmentProtectedType: blockV0.IPv4AdjacencySegmentProtectedType, + IPv4AdjacencySegmentProtectedValue: blockV0.IPv4AdjacencySegmentProtectedValue, + IPv4AdjacencySegmentUnprotectedType: blockV0.IPv4AdjacencySegmentUnprotectedType, + IPv4AdjacencySegmentUnprotectedValue: blockV0.IPv4AdjacencySegmentUnprotectedValue, + LinkProtection: blockV0.LinkProtection, + Metric: blockV0.Metric, + Mtu: blockV0.Mtu, + NoAdvertiseAdjacencySegment: blockV0.NoAdvertiseAdjacencySegment, + NoEligibleBackup: blockV0.NoEligibleBackup, + NoEligibleRemoteBackup: blockV0.NoEligibleBackup, + NoInterfaceStateTraps: blockV0.NoInterfaceStateTraps, + NoNeighborDownNotification: blockV0.NoNeighborDownNotification, + NodeLinkProtection: blockV0.NodeLinkProtection, + Passive: blockV0.Passive, + PassiveTrafficEngineeringRemoteNodeID: blockV0.PassiveTrafficEngineeringRemoteNodeID, + PassiveTrafficEngineeringRemoteNodeRouterID: blockV0.PassiveTrafficEngineeringRemoteNodeRouterID, + PollInterval: blockV0.PollInterval, + Priority: blockV0.Priority, + RetransmitInterval: blockV0.RetransmitInterval, + Secondary: blockV0.Secondary, + StrictBfd: blockV0.StrictBfd, + TeMetric: blockV0.TeMetric, + TransitDelay: blockV0.TransitDelay, + } + for _, subBlockV0 := range blockV0.AuthenticationMD5 { + subBlockV1 := ospfAreaBlockInterfaceBlockAuthenticationMD5{ + KeyID: subBlockV0.KeyID, + Key: subBlockV0.Key, + StartTime: subBlockV0.StartTime, + } + blockV1.AuthenticationMD5 = append(blockV1.AuthenticationMD5, subBlockV1) + } + for _, subBlockV0 := range blockV0.BandwidthBasedMetrics { + subBlockV1 := ospfAreaBlockInterfaceBlockBandwidthBasedMetrics{ + Bandwidth: subBlockV0.Bandwidth, + Metric: subBlockV0.Metric, + } + blockV1.BandwidthBasedMetrics = append(blockV1.BandwidthBasedMetrics, subBlockV1) + } + if len(blockV0.BfdLivenessDetection) > 0 { + blockV1.BfdLivenessDetection = &ospfAreaBlockInterfaceBlockBfdLivenessDetection{ + AuthenticationAlgorithm: blockV0.BfdLivenessDetection[0].AuthenticationAlgorithm, + AuthenticationKeyChain: blockV0.BfdLivenessDetection[0].AuthenticationKeyChain, + AuthenticationLooseCheck: blockV0.BfdLivenessDetection[0].AuthenticationLooseCheck, + DetectionTimeThreshold: blockV0.BfdLivenessDetection[0].DetectionTimeThreshold, + FullNeighborsOnly: blockV0.BfdLivenessDetection[0].FullNeighborsOnly, + HolddownInterval: blockV0.BfdLivenessDetection[0].HolddownInterval, + MinimumInterval: blockV0.BfdLivenessDetection[0].MinimumInterval, + MinimumReceiveInterval: blockV0.BfdLivenessDetection[0].MinimumReceiveInterval, + Multiplier: blockV0.BfdLivenessDetection[0].Multiplier, + NoAdaptation: blockV0.BfdLivenessDetection[0].NoAdaptation, + TransmitIntervalMinimumInterval: blockV0.BfdLivenessDetection[0].TransmitIntervalMinimumInterval, + TransmitIntervalThreshold: blockV0.BfdLivenessDetection[0].TransmitIntervalThreshold, + Version: blockV0.BfdLivenessDetection[0].Version, + } + } + for _, subBlockV0 := range blockV0.Neighbor { + subBlockV1 := ospfAreaBlockInterfaceBlockNeighbor{ + Address: subBlockV0.Address, + Eligbile: subBlockV0.Eligbile, + } + blockV1.Neighbor = append(blockV1.Neighbor, subBlockV1) + } + dataV1.Interface = append(dataV1.Interface, blockV1) + } + for _, blockV0 := range dataV0.AreaRange { + blockV1 := ospfAreaBlockAreaRange{ + Range: blockV0.Range, + Exact: blockV0.Exact, + OverrideMetric: blockV0.OverrideMetric, + Restrict: blockV0.Restrict, + } + dataV1.AreaRange = append(dataV1.AreaRange, blockV1) + } + if len(dataV0.Nssa) > 0 { + dataV1.Nssa = &ospfAreaBlockNssa{ + Summaries: dataV0.Nssa[0].Summaries, + NoSummaries: dataV0.Nssa[0].NoSummaries, + } + for _, subBlockV0 := range dataV0.Nssa[0].AreaRange { + subBlockV1 := ospfAreaBlockAreaRange{ + Range: subBlockV0.Range, + Exact: subBlockV0.Exact, + OverrideMetric: subBlockV0.OverrideMetric, + Restrict: subBlockV0.Restrict, + } + dataV1.Nssa.AreaRange = append(dataV1.Nssa.AreaRange, subBlockV1) + } + if len(dataV0.Nssa[0].DefaultLsa) > 0 { + dataV1.Nssa.DefaultLsa = &ospfAreaBlockNssaBlockDefaultLsa{ + DefaultMetric: dataV0.Nssa[0].DefaultLsa[0].DefaultMetric, + MetricType: dataV0.Nssa[0].DefaultLsa[0].MetricType, + Type7: dataV0.Nssa[0].DefaultLsa[0].Type7, + } + } + } + if len(dataV0.Stub) > 0 { + dataV1.Stub = &ospfAreaBlockStub{ + DefaultMetric: dataV0.Stub[0].DefaultMetric, + Summaries: dataV0.Stub[0].Summaries, + NoSummaries: dataV0.Stub[0].NoSummaries, + } + } + for _, blockV0 := range dataV0.VirtualLink { + blockV1 := ospfAreaBlockVirtualLink{ + NeighborID: blockV0.NeighborID, + TransitArea: blockV0.TransitArea, + DeadInterval: blockV0.DeadInterval, + DemandCircuit: blockV0.DemandCircuit, + Disable: blockV0.Disable, + FloodReduction: blockV0.FloodReduction, + HelloInterval: blockV0.HelloInterval, + IpsecSA: blockV0.IpsecSA, + Mtu: blockV0.Mtu, + RetransmitInterval: blockV0.RetransmitInterval, + TransitDelay: blockV0.TransitDelay, + } + dataV1.VirtualLink = append(dataV1.VirtualLink, blockV1) + } + + resp.Diagnostics.Append(resp.State.Set(ctx, dataV1)...) +} diff --git a/internal/providerfwk/upgradestate_ospf_area_test.go b/internal/providerfwk/upgradestate_ospf_area_test.go new file mode 100644 index 00000000..430eadfb --- /dev/null +++ b/internal/providerfwk/upgradestate_ospf_area_test.go @@ -0,0 +1,49 @@ +package providerfwk_test + +import ( + "os" + "testing" + + "github.com/jeremmfr/terraform-provider-junos/internal/junos" + + "github.com/hashicorp/terraform-plugin-testing/config" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/plancheck" +) + +func TestAccUpgradeStateResourceOspfArea_V0toV1_basic(t *testing.T) { + testaccInterface := junos.DefaultInterfaceTestAcc + testaccInterface2 := junos.DefaultInterfaceTestAcc2 + if iface := os.Getenv("TESTACC_INTERFACE"); iface != "" { + testaccInterface = iface + } + if iface := os.Getenv("TESTACC_INTERFACE2"); iface != "" { + testaccInterface2 = iface + } + if os.Getenv("TESTACC_SWITCH") == "" { + resource.Test(t, resource.TestCase{ + Steps: []resource.TestStep{ + { + ConfigDirectory: config.TestStepDirectory(), + ConfigVariables: map[string]config.Variable{ + "interface": config.StringVariable(testaccInterface), + "interface2": config.StringVariable(testaccInterface2), + }, + }, + { + ProtoV5ProviderFactories: testAccProtoV5ProviderFactories, + ConfigDirectory: config.TestStepDirectory(), + ConfigVariables: map[string]config.Variable{ + "interface": config.StringVariable(testaccInterface), + "interface2": config.StringVariable(testaccInterface2), + }, + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectEmptyPlan(), + }, + }, + }, + }, + }) + } +} diff --git a/internal/providersdk/func_common.go b/internal/providersdk/func_common.go index 841e2a2f..45c9bc29 100644 --- a/internal/providersdk/func_common.go +++ b/internal/providersdk/func_common.go @@ -176,29 +176,6 @@ func copyAndRemoveItemMapList( return list } -func copyAndRemoveItemMapList2( - identifier, identifier2 string, m map[string]interface{}, list []map[string]interface{}, -) []map[string]interface{} { - if m[identifier] == nil { - panic(fmt.Errorf("internal error: can't find identifier %s in map", identifier)) - } - if m[identifier2] == nil { - panic(fmt.Errorf("internal error: can't find identifier %s in map", identifier2)) - } - for i, element := range list { - if element[identifier] == m[identifier] && element[identifier2] == m[identifier2] { - for key, value := range element { - m[key] = value - } - list = append(list[:i], list[i+1:]...) - - break - } - } - - return list -} - func validateIsIPv6Address(i interface{}, k string) (warnings []string, errors []error) { v, ok := i.(string) if !ok { diff --git a/internal/providersdk/provider.go b/internal/providersdk/provider.go index a6ac3af4..cdc52179 100644 --- a/internal/providersdk/provider.go +++ b/internal/providersdk/provider.go @@ -180,7 +180,6 @@ func Provider() *schema.Provider { "junos_lldpmed_interface": resourceLldpMedInterface(), "junos_null_commit_file": resourceNullCommitFile(), "junos_ospf": resourceOspf(), - "junos_ospf_area": resourceOspfArea(), "junos_rib_group": resourceRibGroup(), "junos_rip_group": resourceRipGroup(), "junos_rip_neighbor": resourceRipNeighbor(), @@ -215,11 +214,11 @@ func Provider() *schema.Provider { "junos_system_ntp_server": resourceSystemNtpServer(), "junos_system_root_authentication": resourceSystemRootAuthentication(), "junos_system_services_dhcp_localserver_group": resourceSystemServicesDhcpLocalServerGroup(), - "junos_vlan": resourceVlan(), - "junos_vstp": resourceVstp(), - "junos_vstp_interface": resourceVstpInterface(), - "junos_vstp_vlan": resourceVstpVlan(), - "junos_vstp_vlan_group": resourceVstpVlanGroup(), + "junos_vlan": resourceVlan(), + "junos_vstp": resourceVstp(), + "junos_vstp_interface": resourceVstpInterface(), + "junos_vstp_vlan": resourceVstpVlan(), + "junos_vstp_vlan_group": resourceVstpVlanGroup(), }, DataSourcesMap: map[string]*schema.Resource{ "junos_system_information": dataSourceSystemInformation(), diff --git a/internal/providersdk/resource_ospf_area.go b/internal/providersdk/resource_ospf_area.go deleted file mode 100644 index aa81de8e..00000000 --- a/internal/providersdk/resource_ospf_area.go +++ /dev/null @@ -1,1909 +0,0 @@ -package providersdk - -import ( - "context" - "errors" - "fmt" - "regexp" - "slices" - "strconv" - "strings" - - "github.com/jeremmfr/terraform-provider-junos/internal/junos" - - "github.com/hashicorp/terraform-plugin-sdk/v2/diag" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" - balt "github.com/jeremmfr/go-utils/basicalter" - jdecode "github.com/jeremmfr/junosdecode" -) - -type ospfAreaOptions struct { - noContextIdentifierAdvertisement bool - areaID string - routingInstance string - realm string - version string - contextIdentifier []string - interAreaPrefixExport []string - interAreaPrefixImport []string - networkSummaryExport []string - networkSummaryImport []string - areaRange []map[string]interface{} - interFace []map[string]interface{} - nssa []map[string]interface{} - stub []map[string]interface{} - virtualLink []map[string]interface{} -} - -func resourceOspfArea() *schema.Resource { - return &schema.Resource{ - CreateWithoutTimeout: resourceOspfAreaCreate, - ReadWithoutTimeout: resourceOspfAreaRead, - UpdateWithoutTimeout: resourceOspfAreaUpdate, - DeleteWithoutTimeout: resourceOspfAreaDelete, - Importer: &schema.ResourceImporter{ - StateContext: resourceOspfAreaImport, - }, - Schema: map[string]*schema.Schema{ - "area_id": { - Type: schema.TypeString, - ForceNew: true, - Required: true, - ValidateFunc: validation.StringMatch( - regexp.MustCompile(`^(\d|\.)+$`), "should be usually in the IP format"), - }, - "routing_instance": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - Default: junos.DefaultW, - ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, formatDefault), - }, - "realm": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - ValidateFunc: validation.StringInSlice([]string{"ipv4-unicast", "ipv4-multicast", "ipv6-multicast"}, false), - }, - "version": { - Type: schema.TypeString, - Optional: true, - Default: "v2", - ForceNew: true, - ValidateFunc: validation.StringInSlice([]string{"v2", "v3"}, false), - }, - "interface": { - Type: schema.TypeList, - Required: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Required: true, - }, - "authentication_simple_password": { - Type: schema.TypeString, - Optional: true, - Sensitive: true, - }, - "authentication_md5": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "key_id": { - Type: schema.TypeInt, - Required: true, - ValidateFunc: validation.IntBetween(0, 255), - }, - "key": { - Type: schema.TypeString, - Required: true, - Sensitive: true, - }, - "start_time": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: validation.StringMatch( - regexp.MustCompile(`^\d{4}\-\d\d?\-\d\d?\.\d{2}:\d{2}:\d{2}$`), - "must be in the format 'YYYY-MM-DD.HH:MM:SS'"), - }, - }, - }, - }, - "bandwidth_based_metrics": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "bandwidth": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringMatch(regexp.MustCompile(`^(\d)+(m|k|g)?$`), - `must be a bandwidth ^(\d)+(m|k|g)?$`), - }, - "metric": { - Type: schema.TypeInt, - Required: true, - ValidateFunc: validation.IntBetween(1, 65535), - }, - }, - }, - }, - "bfd_liveness_detection": { - Type: schema.TypeList, - Optional: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "authentication_algorithm": { - Type: schema.TypeString, - Optional: true, - }, - "authentication_key_chain": { - Type: schema.TypeString, - Optional: true, - }, - "authentication_loose_check": { - Type: schema.TypeBool, - Optional: true, - }, - "detection_time_threshold": { - Type: schema.TypeInt, - Optional: true, - ValidateFunc: validation.IntBetween(1, 4294967295), - }, - "full_neighbors_only": { - Type: schema.TypeBool, - Optional: true, - }, - "holddown_interval": { - Type: schema.TypeInt, - Optional: true, - ValidateFunc: validation.IntBetween(1, 255000), - }, - "minimum_interval": { - Type: schema.TypeInt, - Optional: true, - ValidateFunc: validation.IntBetween(1, 255000), - }, - "minimum_receive_interval": { - Type: schema.TypeInt, - Optional: true, - ValidateFunc: validation.IntBetween(1, 255000), - }, - "multiplier": { - Type: schema.TypeInt, - Optional: true, - ValidateFunc: validation.IntBetween(1, 255), - }, - "no_adaptation": { - Type: schema.TypeBool, - Optional: true, - }, - "transmit_interval_minimum_interval": { - Type: schema.TypeInt, - Optional: true, - ValidateFunc: validation.IntBetween(1, 255000), - }, - "transmit_interval_threshold": { - Type: schema.TypeInt, - Optional: true, - ValidateFunc: validation.IntBetween(1, 4294967295), - }, - "version": { - Type: schema.TypeString, - Optional: true, - }, - }, - }, - }, - "dead_interval": { - Type: schema.TypeInt, - Optional: true, - ValidateFunc: validation.IntBetween(1, 65535), - }, - "demand_circuit": { - Type: schema.TypeBool, - Optional: true, - }, - "disable": { - Type: schema.TypeBool, - Optional: true, - }, - "dynamic_neighbors": { - Type: schema.TypeBool, - Optional: true, - }, - "flood_reduction": { - Type: schema.TypeBool, - Optional: true, - }, - "hello_interval": { - Type: schema.TypeInt, - Optional: true, - ValidateFunc: validation.IntBetween(1, 255), - }, - "interface_type": { - Type: schema.TypeString, - Optional: true, - }, - "ipsec_sa": { - Type: schema.TypeString, - Optional: true, - }, - "ipv4_adjacency_segment_protected_type": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: validation.StringInSlice([]string{"dynamic", "index", "label"}, false), - }, - "ipv4_adjacency_segment_protected_value": { - Type: schema.TypeString, - Optional: true, - }, - "ipv4_adjacency_segment_unprotected_type": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: validation.StringInSlice([]string{"dynamic", "index", "label"}, false), - }, - "ipv4_adjacency_segment_unprotected_value": { - Type: schema.TypeString, - Optional: true, - }, - "link_protection": { - Type: schema.TypeBool, - Optional: true, - }, - "metric": { - Type: schema.TypeInt, - Optional: true, - ValidateFunc: validation.IntBetween(1, 65535), - }, - "mtu": { - Type: schema.TypeInt, - Optional: true, - ValidateFunc: validation.IntBetween(128, 65535), - }, - "neighbor": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "address": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.IsIPAddress, - }, - "eligible": { - Type: schema.TypeBool, - Optional: true, - Default: false, - }, - }, - }, - }, - "no_advertise_adjacency_segment": { - Type: schema.TypeBool, - Optional: true, - }, - "no_eligible_backup": { - Type: schema.TypeBool, - Optional: true, - }, - "no_eligible_remote_backup": { - Type: schema.TypeBool, - Optional: true, - }, - "no_interface_state_traps": { - Type: schema.TypeBool, - Optional: true, - }, - "no_neighbor_down_notification": { - Type: schema.TypeBool, - Optional: true, - }, - "node_link_protection": { - Type: schema.TypeBool, - Optional: true, - }, - "passive": { - Type: schema.TypeBool, - Optional: true, - }, - "passive_traffic_engineering_remote_node_id": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: validation.IsIPAddress, - }, - "passive_traffic_engineering_remote_node_router_id": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: validation.IsIPAddress, - }, - "poll_interval": { - Type: schema.TypeInt, - Optional: true, - ValidateFunc: validation.IntBetween(1, 65535), - }, - "priority": { - Type: schema.TypeInt, - Optional: true, - Default: -1, - ValidateFunc: validation.IntBetween(0, 255), - }, - "retransmit_interval": { - Type: schema.TypeInt, - Optional: true, - ValidateFunc: validation.IntBetween(1, 65535), - }, - "secondary": { - Type: schema.TypeBool, - Optional: true, - }, - "strict_bfd": { - Type: schema.TypeBool, - Optional: true, - }, - "te_metric": { - Type: schema.TypeInt, - Optional: true, - ValidateFunc: validation.IntBetween(1, 4294967295), - }, - "transit_delay": { - Type: schema.TypeInt, - Optional: true, - ValidateFunc: validation.IntBetween(1, 65535), - }, - }, - }, - }, - "area_range": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "range": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.IsCIDRNetwork(0, 128), - }, - "exact": { - Type: schema.TypeBool, - Optional: true, - Default: false, - }, - "override_metric": { - Type: schema.TypeInt, - Optional: true, - Default: 0, - ValidateFunc: validation.IntBetween(1, 16777215), - }, - "restrict": { - Type: schema.TypeBool, - Optional: true, - Default: false, - }, - }, - }, - }, - "context_identifier": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Schema{ - Type: schema.TypeString, - ValidateFunc: validation.StringMatch( - regexp.MustCompile(`^(\d{1,3}\.){3}\d{1,3}$`), "must be in the IP format"), - }, - ConflictsWith: []string{"no_context_identifier_advertisement"}, - }, - "inter_area_prefix_export": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{ - Type: schema.TypeString, - ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, formatDefault), - }, - }, - "inter_area_prefix_import": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{ - Type: schema.TypeString, - ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, formatDefault), - }, - }, - "network_summary_export": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{ - Type: schema.TypeString, - ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, formatDefault), - }, - }, - "network_summary_import": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{ - Type: schema.TypeString, - ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, formatDefault), - }, - }, - "no_context_identifier_advertisement": { - Type: schema.TypeBool, - Optional: true, - ConflictsWith: []string{"context_identifier"}, - }, - "nssa": { - Type: schema.TypeList, - Optional: true, - MaxItems: 1, - ConflictsWith: []string{"stub"}, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "area_range": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "range": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.IsCIDRNetwork(0, 128), - }, - "exact": { - Type: schema.TypeBool, - Optional: true, - Default: false, - }, - "override_metric": { - Type: schema.TypeInt, - Optional: true, - Default: 0, - ValidateFunc: validation.IntBetween(1, 16777215), - }, - "restrict": { - Type: schema.TypeBool, - Optional: true, - Default: false, - }, - }, - }, - }, - "default_lsa": { - Type: schema.TypeList, - Optional: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "default_metric": { - Type: schema.TypeInt, - Optional: true, - ValidateFunc: validation.IntBetween(1, 16777215), - }, - "metric_type": { - Type: schema.TypeInt, - Optional: true, - ValidateFunc: validation.IntBetween(1, 2), - }, - "type_7": { - Type: schema.TypeBool, - Optional: true, - }, - }, - }, - }, - "no_summaries": { - Type: schema.TypeBool, - Optional: true, - ConflictsWith: []string{"nssa.0.summaries"}, - }, - "summaries": { - Type: schema.TypeBool, - Optional: true, - ConflictsWith: []string{"nssa.0.no_summaries"}, - }, - }, - }, - }, - "stub": { - Type: schema.TypeList, - Optional: true, - MaxItems: 1, - ConflictsWith: []string{"nssa"}, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "default_metric": { - Type: schema.TypeInt, - Optional: true, - ValidateFunc: validation.IntBetween(1, 16777215), - }, - "no_summaries": { - Type: schema.TypeBool, - Optional: true, - ConflictsWith: []string{"stub.0.summaries"}, - }, - "summaries": { - Type: schema.TypeBool, - Optional: true, - ConflictsWith: []string{"stub.0.no_summaries"}, - }, - }, - }, - }, - "virtual_link": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "neighbor_id": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.IsIPv4Address, - }, - "transit_area": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringMatch( - regexp.MustCompile(`^(\d{1,3}\.){3}\d{1,3}$`), "must be in the IP format"), - }, - "dead_interval": { - Type: schema.TypeInt, - Optional: true, - Default: 0, - ValidateFunc: validation.IntBetween(1, 65535), - }, - "demand_circuit": { - Type: schema.TypeBool, - Optional: true, - Default: false, - }, - "disable": { - Type: schema.TypeBool, - Optional: true, - Default: false, - }, - "flood_reduction": { - Type: schema.TypeBool, - Optional: true, - Default: false, - }, - "hello_interval": { - Type: schema.TypeInt, - Optional: true, - Default: 0, - ValidateFunc: validation.IntBetween(1, 255), - }, - "ipsec_sa": { - Type: schema.TypeString, - Optional: true, - Default: "", - }, - "mtu": { - Type: schema.TypeInt, - Optional: true, - Default: 0, - ValidateFunc: validation.IntBetween(128, 65535), - }, - "retransmit_interval": { - Type: schema.TypeInt, - Optional: true, - Default: 0, - ValidateFunc: validation.IntBetween(1, 65535), - }, - "transit_delay": { - Type: schema.TypeInt, - Optional: true, - Default: 0, - ValidateFunc: validation.IntBetween(1, 65535), - }, - }, - }, - }, - }, - } -} - -func resourceOspfAreaCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { - clt := m.(*junos.Client) - if clt.FakeCreateSetFile() { - junSess := clt.NewSessionWithoutNetconf(ctx) - if err := setOspfArea(d, junSess); err != nil { - return diag.FromErr(err) - } - if realm := d.Get("realm").(string); realm != "" { - d.SetId(d.Get("area_id").(string) + junos.IDSeparator + d.Get("version").(string) + - junos.IDSeparator + realm + junos.IDSeparator + d.Get("routing_instance").(string)) - } else { - d.SetId(d.Get("area_id").(string) + junos.IDSeparator + d.Get("version").(string) + - junos.IDSeparator + d.Get("routing_instance").(string)) - } - - return nil - } - junSess, err := clt.StartNewSession(ctx) - if err != nil { - return diag.FromErr(err) - } - defer junSess.Close() - if err := junSess.ConfigLock(ctx); err != nil { - return diag.FromErr(err) - } - var diagWarns diag.Diagnostics - ospfAreaExists, err := checkOspfAreaExists( - d.Get("area_id").(string), - d.Get("version").(string), - d.Get("realm").(string), - d.Get("routing_instance").(string), - junSess, - ) - if err != nil { - appendDiagWarns(&diagWarns, junSess.ConfigClear()) - - return append(diagWarns, diag.FromErr(err)...) - } - if ospfAreaExists { - appendDiagWarns(&diagWarns, junSess.ConfigClear()) - - if realm := d.Get("realm").(string); realm != "" { - return append(diagWarns, diag.FromErr(fmt.Errorf("ospf %v realm %v area %v already exists in routing instance %v", - d.Get("version").(string), realm, d.Get("area_id").(string), d.Get("routing_instance").(string)))...) - } - - return append(diagWarns, diag.FromErr(fmt.Errorf("ospf %v area %v already exists in routing instance %v", - d.Get("version").(string), d.Get("area_id").(string), d.Get("routing_instance").(string)))...) - } - if err := setOspfArea(d, junSess); err != nil { - appendDiagWarns(&diagWarns, junSess.ConfigClear()) - - return append(diagWarns, diag.FromErr(err)...) - } - warns, err := junSess.CommitConf(ctx, "create resource junos_ospf_area") - appendDiagWarns(&diagWarns, warns) - if err != nil { - appendDiagWarns(&diagWarns, junSess.ConfigClear()) - - return append(diagWarns, diag.FromErr(err)...) - } - ospfAreaExists, err = checkOspfAreaExists( - d.Get("area_id").(string), - d.Get("version").(string), - d.Get("realm").(string), - d.Get("routing_instance").(string), - junSess, - ) - if err != nil { - return append(diagWarns, diag.FromErr(err)...) - } - if ospfAreaExists { - if realm := d.Get("realm").(string); realm != "" { - d.SetId(d.Get("area_id").(string) + junos.IDSeparator + d.Get("version").(string) + - junos.IDSeparator + realm + junos.IDSeparator + d.Get("routing_instance").(string)) - } else { - d.SetId(d.Get("area_id").(string) + junos.IDSeparator + d.Get("version").(string) + - junos.IDSeparator + d.Get("routing_instance").(string)) - } - } else { - if realm := d.Get("realm").(string); realm != "" { - return append(diagWarns, - diag.FromErr(fmt.Errorf("ospf %v realm %v area %v in routing instance %v "+ - "not exists after commit => check your config", - d.Get("version").(string), realm, d.Get("area_id").(string), d.Get("routing_instance").(string)))...) - } - - return append(diagWarns, - diag.FromErr(fmt.Errorf("ospf %v area %v in routing instance %v not exists after commit => check your config", - d.Get("version").(string), d.Get("area_id").(string), d.Get("routing_instance").(string)))...) - } - - return append(diagWarns, resourceOspfAreaReadWJunSess(d, junSess)...) -} - -func resourceOspfAreaRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { - clt := m.(*junos.Client) - junSess, err := clt.StartNewSession(ctx) - if err != nil { - return diag.FromErr(err) - } - defer junSess.Close() - - return resourceOspfAreaReadWJunSess(d, junSess) -} - -func resourceOspfAreaReadWJunSess(d *schema.ResourceData, junSess *junos.Session) diag.Diagnostics { - junos.MutexLock() - ospfAreaOptions, err := readOspfArea( - d.Get("area_id").(string), - d.Get("version").(string), - d.Get("realm").(string), - d.Get("routing_instance").(string), - junSess, - ) - junos.MutexUnlock() - if err != nil { - return diag.FromErr(err) - } - if ospfAreaOptions.areaID == "" { - d.SetId("") - } else { - fillOspfAreaData(d, ospfAreaOptions) - } - - return nil -} - -func resourceOspfAreaUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { - d.Partial(true) - clt := m.(*junos.Client) - if clt.FakeUpdateAlso() { - junSess := clt.NewSessionWithoutNetconf(ctx) - if err := delOspfArea(d, junSess); err != nil { - return diag.FromErr(err) - } - if err := setOspfArea(d, junSess); err != nil { - return diag.FromErr(err) - } - d.Partial(false) - - return nil - } - junSess, err := clt.StartNewSession(ctx) - if err != nil { - return diag.FromErr(err) - } - defer junSess.Close() - if err := junSess.ConfigLock(ctx); err != nil { - return diag.FromErr(err) - } - var diagWarns diag.Diagnostics - if err := delOspfArea(d, junSess); err != nil { - appendDiagWarns(&diagWarns, junSess.ConfigClear()) - - return append(diagWarns, diag.FromErr(err)...) - } - if err := setOspfArea(d, junSess); err != nil { - appendDiagWarns(&diagWarns, junSess.ConfigClear()) - - return append(diagWarns, diag.FromErr(err)...) - } - warns, err := junSess.CommitConf(ctx, "update resource junos_ospf_area") - appendDiagWarns(&diagWarns, warns) - if err != nil { - appendDiagWarns(&diagWarns, junSess.ConfigClear()) - - return append(diagWarns, diag.FromErr(err)...) - } - d.Partial(false) - - return append(diagWarns, resourceOspfAreaReadWJunSess(d, junSess)...) -} - -func resourceOspfAreaDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { - clt := m.(*junos.Client) - if clt.FakeDeleteAlso() { - junSess := clt.NewSessionWithoutNetconf(ctx) - if err := delOspfArea(d, junSess); err != nil { - return diag.FromErr(err) - } - - return nil - } - junSess, err := clt.StartNewSession(ctx) - if err != nil { - return diag.FromErr(err) - } - defer junSess.Close() - if err := junSess.ConfigLock(ctx); err != nil { - return diag.FromErr(err) - } - var diagWarns diag.Diagnostics - if err := delOspfArea(d, junSess); err != nil { - appendDiagWarns(&diagWarns, junSess.ConfigClear()) - - return append(diagWarns, diag.FromErr(err)...) - } - warns, err := junSess.CommitConf(ctx, "delete resource junos_ospf_area") - appendDiagWarns(&diagWarns, warns) - if err != nil { - appendDiagWarns(&diagWarns, junSess.ConfigClear()) - - return append(diagWarns, diag.FromErr(err)...) - } - - return diagWarns -} - -func resourceOspfAreaImport(ctx context.Context, d *schema.ResourceData, m interface{}, -) ([]*schema.ResourceData, error) { - clt := m.(*junos.Client) - junSess, err := clt.StartNewSession(ctx) - if err != nil { - return nil, err - } - defer junSess.Close() - result := make([]*schema.ResourceData, 1) - idSplit := strings.Split(d.Id(), junos.IDSeparator) - if len(idSplit) < 3 { - return nil, fmt.Errorf("missing element(s) in id with separator %v", junos.IDSeparator) - } - if len(idSplit) == 3 { - ospfAreaExists, err := checkOspfAreaExists(idSplit[0], idSplit[1], "", idSplit[2], junSess) - if err != nil { - return nil, err - } - if !ospfAreaExists { - return nil, - fmt.Errorf( - "don't find ospf area with id '%v' (id must be "+ - ""+junos.IDSeparator+""+junos.IDSeparator+" or "+ - ""+junos.IDSeparator+""+junos.IDSeparator+""+junos.IDSeparator+")", - d.Id(), - ) - } - ospfAreaOptions, err := readOspfArea(idSplit[0], idSplit[1], "", idSplit[2], junSess) - if err != nil { - return nil, err - } - fillOspfAreaData(d, ospfAreaOptions) - result[0] = d - - return result, nil - } - ospfAreaExists, err := checkOspfAreaExists(idSplit[0], idSplit[1], idSplit[2], idSplit[3], junSess) - if err != nil { - return nil, err - } - if !ospfAreaExists { - return nil, - fmt.Errorf( - "don't find ospf area with id '%v' (id must be "+ - ""+junos.IDSeparator+""+junos.IDSeparator+" or "+ - ""+junos.IDSeparator+""+junos.IDSeparator+""+junos.IDSeparator+")", - d.Id(), - ) - } - ospfAreaOptions, err := readOspfArea(idSplit[0], idSplit[1], idSplit[2], idSplit[3], junSess) - if err != nil { - return nil, err - } - fillOspfAreaData(d, ospfAreaOptions) - if ospfAreaOptions.realm == "" { - d.SetId(idSplit[0] + junos.IDSeparator + idSplit[1] + junos.IDSeparator + idSplit[3]) - } - result[0] = d - - return result, nil -} - -func checkOspfAreaExists(idArea, version, realm, routingInstance string, junSess *junos.Session, -) (_ bool, err error) { - var showConfig string - ospfVersion := junos.OspfV2 - if version == "v3" { - ospfVersion = junos.OspfV3 - } else if realm != "" { - return false, errors.New("realm can't set if version != v3") - } - switch { - case routingInstance == junos.DefaultW && realm == "": - showConfig, err = junSess.Command(junos.CmdShowConfig + - "protocols " + ospfVersion + " area " + idArea + junos.PipeDisplaySet) - if err != nil { - return false, err - } - case routingInstance == junos.DefaultW && realm != "": - showConfig, err = junSess.Command(junos.CmdShowConfig + - "protocols " + ospfVersion + " realm " + realm + " area " + idArea + junos.PipeDisplaySet) - if err != nil { - return false, err - } - case realm != "": - showConfig, err = junSess.Command(junos.CmdShowConfig + junos.RoutingInstancesWS + routingInstance + " " + - "protocols " + ospfVersion + " realm " + realm + " area " + idArea + junos.PipeDisplaySet) - if err != nil { - return false, err - } - default: - showConfig, err = junSess.Command(junos.CmdShowConfig + junos.RoutingInstancesWS + routingInstance + " " + - "protocols " + ospfVersion + " area " + idArea + junos.PipeDisplaySet) - if err != nil { - return false, err - } - } - if showConfig == junos.EmptyW { - return false, nil - } - - return true, nil -} - -func setOspfArea(d *schema.ResourceData, junSess *junos.Session) error { - configSet := make([]string, 0) - setPrefix := junos.SetLS - if d.Get("routing_instance").(string) != junos.DefaultW { - setPrefix = junos.SetRoutingInstances + d.Get("routing_instance").(string) + " " - } - ospfVersion := junos.OspfV2 - if d.Get("version").(string) == "v3" { - ospfVersion = junos.OspfV3 - } else if d.Get("realm").(string) != "" { - return errors.New("realm can't set if version != v3") - } - setPrefix += "protocols " + ospfVersion + " " - if realm := d.Get("realm").(string); realm != "" { - setPrefix += "realm " + realm + " " - } - setPrefix += "area " + d.Get("area_id").(string) + " " - - interfaceNameList := make([]string, 0) - for _, v := range d.Get("interface").([]interface{}) { - ospfInterface := v.(map[string]interface{}) - if slices.Contains(interfaceNameList, ospfInterface["name"].(string)) { - return fmt.Errorf("multiple blocks interface with the same name %s", ospfInterface["name"].(string)) - } - interfaceNameList = append(interfaceNameList, ospfInterface["name"].(string)) - setPrefixInterface := setPrefix + "interface " + ospfInterface["name"].(string) + " " - configSetInterface, err := setOspfAreaInterface(setPrefixInterface, ospfInterface) - if err != nil { - return err - } - configSet = append(configSet, configSetInterface...) - } - areaRangeList := make([]string, 0) - for _, areaRangeBlock := range d.Get("area_range").(*schema.Set).List() { - areaRange := areaRangeBlock.(map[string]interface{}) - if slices.Contains(areaRangeList, areaRange["range"].(string)) { - return fmt.Errorf("multiple blocks area_range with the same range %s", areaRange["range"].(string)) - } - areaRangeList = append(areaRangeList, areaRange["range"].(string)) - configSet = append(configSet, setPrefix+"area-range "+areaRange["range"].(string)) - if areaRange["exact"].(bool) { - configSet = append(configSet, - setPrefix+"area-range "+areaRange["range"].(string)+" exact", - ) - } - if v := areaRange["override_metric"].(int); v != 0 { - configSet = append(configSet, - setPrefix+"area-range "+areaRange["range"].(string)+" override-metric "+strconv.Itoa(v), - ) - } - if areaRange["restrict"].(bool) { - configSet = append(configSet, - setPrefix+"area-range "+areaRange["range"].(string)+" restrict", - ) - } - } - for _, contextIdentifier := range sortSetOfString(d.Get("context_identifier").(*schema.Set).List()) { - configSet = append(configSet, setPrefix+"context-identifier "+contextIdentifier) - } - for _, interAreaPrefExport := range d.Get("inter_area_prefix_export").([]interface{}) { - configSet = append(configSet, setPrefix+"inter-area-prefix-export "+interAreaPrefExport.(string)) - } - for _, interAreaPrefImport := range d.Get("inter_area_prefix_import").([]interface{}) { - configSet = append(configSet, setPrefix+"inter-area-prefix-import "+interAreaPrefImport.(string)) - } - for _, networkSummaryExport := range d.Get("network_summary_export").([]interface{}) { - configSet = append(configSet, setPrefix+"network-summary-export "+networkSummaryExport.(string)) - } - for _, networkSummaryImport := range d.Get("network_summary_import").([]interface{}) { - configSet = append(configSet, setPrefix+"network-summary-import "+networkSummaryImport.(string)) - } - if d.Get("no_context_identifier_advertisement").(bool) { - configSet = append(configSet, setPrefix+"no-context-identifier-advertisement") - } - for _, nssaBlock := range d.Get("nssa").([]interface{}) { - setPrefixNssa := setPrefix + "nssa " - configSet = append(configSet, setPrefixNssa) - if nssaBlock != nil { - nssa := nssaBlock.(map[string]interface{}) - nssaAreaRangeList := make([]string, 0) - for _, areaRangeBlock := range nssa["area_range"].(*schema.Set).List() { - areaRange := areaRangeBlock.(map[string]interface{}) - if slices.Contains(nssaAreaRangeList, areaRange["range"].(string)) { - return fmt.Errorf("multiple blocks area_range with the same range %s in nssa block", areaRange["range"].(string)) - } - nssaAreaRangeList = append(nssaAreaRangeList, areaRange["range"].(string)) - configSet = append(configSet, setPrefixNssa+"area-range "+areaRange["range"].(string)) - if areaRange["exact"].(bool) { - configSet = append(configSet, - setPrefixNssa+"area-range "+areaRange["range"].(string)+" exact", - ) - } - if v := areaRange["override_metric"].(int); v != 0 { - configSet = append(configSet, - setPrefixNssa+"area-range "+areaRange["range"].(string)+" override-metric "+strconv.Itoa(v), - ) - } - if areaRange["restrict"].(bool) { - configSet = append(configSet, - setPrefixNssa+"area-range "+areaRange["range"].(string)+" restrict", - ) - } - } - for _, defaultLsaBlock := range nssa["default_lsa"].([]interface{}) { - configSet = append(configSet, setPrefixNssa+"default-lsa") - if defaultLsaBlock != nil { - defaultLsa := defaultLsaBlock.(map[string]interface{}) - if v := defaultLsa["default_metric"].(int); v != 0 { - configSet = append(configSet, setPrefixNssa+"default-lsa default-metric "+strconv.Itoa(v)) - } - if v := defaultLsa["metric_type"].(int); v != 0 { - configSet = append(configSet, setPrefixNssa+"default-lsa metric-type "+strconv.Itoa(v)) - } - if defaultLsa["type_7"].(bool) { - configSet = append(configSet, setPrefixNssa+"default-lsa type-7") - } - } - } - if nssa["no_summaries"].(bool) { - configSet = append(configSet, setPrefixNssa+"no-summaries") - } - if nssa["summaries"].(bool) { - configSet = append(configSet, setPrefixNssa+"summaries") - } - } - } - for _, stubBlock := range d.Get("stub").([]interface{}) { - configSet = append(configSet, setPrefix+"stub") - if stubBlock != nil { - stub := stubBlock.(map[string]interface{}) - if v := stub["default_metric"].(int); v != 0 { - configSet = append(configSet, setPrefix+"stub default-metric "+strconv.Itoa(v)) - } - if stub["no_summaries"].(bool) { - configSet = append(configSet, setPrefix+"stub no-summaries") - } - if stub["summaries"].(bool) { - configSet = append(configSet, setPrefix+"stub summaries") - } - } - } - virtualLinkList := make([]string, 0) - for _, virtualLinkBlock := range d.Get("virtual_link").(*schema.Set).List() { - virtualLink := virtualLinkBlock.(map[string]interface{}) - if slices.Contains( - virtualLinkList, - virtualLink["neighbor_id"].(string)+junos.IDSeparator+virtualLink["transit_area"].(string), - ) { - return fmt.Errorf( - "multiple blocks virtual_link with the same neighbor_id '%s' and transit_area '%s'", - virtualLink["neighbor_id"].(string), virtualLink["transit_area"].(string)) - } - virtualLinkList = append( - virtualLinkList, virtualLink["neighbor_id"].(string)+junos.IDSeparator+virtualLink["transit_area"].(string), - ) - setPrefixVirtualLink := setPrefix + "virtual-link " + - "neighbor-id " + virtualLink["neighbor_id"].(string) + - " transit-area " + virtualLink["transit_area"].(string) + " " - configSet = append(configSet, setPrefixVirtualLink) - if v := virtualLink["dead_interval"].(int); v != 0 { - configSet = append(configSet, setPrefixVirtualLink+"dead-interval "+strconv.Itoa(v)) - } - if virtualLink["demand_circuit"].(bool) { - configSet = append(configSet, setPrefixVirtualLink+"demand-circuit") - } - if virtualLink["disable"].(bool) { - configSet = append(configSet, setPrefixVirtualLink+"disable") - } - if virtualLink["flood_reduction"].(bool) { - configSet = append(configSet, setPrefixVirtualLink+"flood-reduction") - } - if v := virtualLink["hello_interval"].(int); v != 0 { - configSet = append(configSet, setPrefixVirtualLink+"hello-interval "+strconv.Itoa(v)) - } - if v := virtualLink["ipsec_sa"].(string); v != "" { - configSet = append(configSet, setPrefixVirtualLink+"ipsec-sa \""+v+"\"") - } - if v := virtualLink["mtu"].(int); v != 0 { - configSet = append(configSet, setPrefixVirtualLink+"mtu "+strconv.Itoa(v)) - } - if v := virtualLink["retransmit_interval"].(int); v != 0 { - configSet = append(configSet, setPrefixVirtualLink+"retransmit-interval "+strconv.Itoa(v)) - } - if v := virtualLink["transit_delay"].(int); v != 0 { - configSet = append(configSet, setPrefixVirtualLink+"transit-delay "+strconv.Itoa(v)) - } - } - - return junSess.ConfigSet(configSet) -} - -func setOspfAreaInterface(setPrefix string, ospfInterface map[string]interface{}) ([]string, error) { - configSet := make([]string, 0) - - configSet = append(configSet, setPrefix) - if v := ospfInterface["authentication_simple_password"].(string); v != "" { - if len(ospfInterface["authentication_md5"].([]interface{})) != 0 { - return configSet, fmt.Errorf("conflict between 'authentication_simple_password' and 'authentication_md5'"+ - " in interface '%s'", ospfInterface["name"].(string)) - } - configSet = append(configSet, setPrefix+"authentication simple-password \""+v+"\"") - } - authenticationMD5List := make([]int, 0) - for _, mAuthMD5 := range ospfInterface["authentication_md5"].([]interface{}) { - authMD5 := mAuthMD5.(map[string]interface{}) - if slices.Contains(authenticationMD5List, authMD5["key_id"].(int)) { - return configSet, fmt.Errorf("multiple blocks authentication_md5 with the same key_id %d in interface with name %s", - authMD5["key_id"].(int), ospfInterface["name"].(string)) - } - authenticationMD5List = append(authenticationMD5List, authMD5["key_id"].(int)) - configSet = append(configSet, setPrefix+"authentication md5 "+ - strconv.Itoa(authMD5["key_id"].(int))+" key \""+authMD5["key"].(string)+"\"") - if v := authMD5["start_time"].(string); v != "" { - configSet = append(configSet, setPrefix+"authentication md5 "+ - strconv.Itoa(authMD5["key_id"].(int))+" start-time "+v) - } - } - bandwidthBasedMetricsList := make([]string, 0) - for _, mBandBaseMet := range ospfInterface["bandwidth_based_metrics"].(*schema.Set).List() { - bandwidthBaseMetrics := mBandBaseMet.(map[string]interface{}) - if slices.Contains(bandwidthBasedMetricsList, bandwidthBaseMetrics["bandwidth"].(string)) { - return configSet, fmt.Errorf("multiple blocks bandwidth_based_metrics "+ - "with the same bandwidth %s in interface with name %s", - bandwidthBaseMetrics["bandwidth"].(string), ospfInterface["name"].(string)) - } - bandwidthBasedMetricsList = append(bandwidthBasedMetricsList, bandwidthBaseMetrics["bandwidth"].(string)) - configSet = append(configSet, setPrefix+"bandwidth-based-metrics bandwidth "+ - bandwidthBaseMetrics["bandwidth"].(string)+" metric "+strconv.Itoa(bandwidthBaseMetrics["metric"].(int))) - } - for _, mBFDLivDet := range ospfInterface["bfd_liveness_detection"].([]interface{}) { - if mBFDLivDet == nil { - return configSet, fmt.Errorf("bfd_liveness_detection block is empty in interface %s", ospfInterface["name"].(string)) - } - setPrefixBfd := setPrefix + "bfd-liveness-detection " - bfdLiveDetect := mBFDLivDet.(map[string]interface{}) - if v := bfdLiveDetect["authentication_algorithm"].(string); v != "" { - configSet = append(configSet, setPrefixBfd+"authentication algorithm "+v) - } - if v := bfdLiveDetect["authentication_key_chain"].(string); v != "" { - configSet = append(configSet, setPrefixBfd+"authentication key-chain \""+v+"\"") - } - if bfdLiveDetect["authentication_loose_check"].(bool) { - configSet = append(configSet, setPrefixBfd+"authentication loose-check") - } - if v := bfdLiveDetect["detection_time_threshold"].(int); v != 0 { - configSet = append(configSet, setPrefixBfd+"detection-time threshold "+strconv.Itoa(v)) - } - if bfdLiveDetect["full_neighbors_only"].(bool) { - configSet = append(configSet, setPrefixBfd+"full-neighbors-only") - } - if v := bfdLiveDetect["holddown_interval"].(int); v != 0 { - configSet = append(configSet, setPrefixBfd+"holddown-interval "+strconv.Itoa(v)) - } - if v := bfdLiveDetect["minimum_interval"].(int); v != 0 { - configSet = append(configSet, setPrefixBfd+"minimum-interval "+strconv.Itoa(v)) - } - if v := bfdLiveDetect["minimum_receive_interval"].(int); v != 0 { - configSet = append(configSet, setPrefixBfd+"minimum-receive-interval "+strconv.Itoa(v)) - } - if v := bfdLiveDetect["multiplier"].(int); v != 0 { - configSet = append(configSet, setPrefixBfd+"multiplier "+strconv.Itoa(v)) - } - if bfdLiveDetect["no_adaptation"].(bool) { - configSet = append(configSet, setPrefixBfd+"no-adaptation") - } - if v := bfdLiveDetect["transmit_interval_minimum_interval"].(int); v != 0 { - configSet = append(configSet, setPrefixBfd+ - "transmit-interval minimum-interval "+strconv.Itoa(v)) - } - if v := bfdLiveDetect["transmit_interval_threshold"].(int); v != 0 { - configSet = append(configSet, setPrefixBfd+ - "transmit-interval threshold "+strconv.Itoa(v)) - } - if v := bfdLiveDetect["version"].(string); v != "" { - configSet = append(configSet, setPrefixBfd+"version "+v) - } - if len(configSet) == 0 || !strings.HasPrefix(configSet[len(configSet)-1], setPrefixBfd) { - return configSet, fmt.Errorf("bfd_liveness_detection block is empty in interface %s", ospfInterface["name"].(string)) - } - } - if v := ospfInterface["dead_interval"].(int); v != 0 { - configSet = append(configSet, setPrefix+"dead-interval "+strconv.Itoa(v)) - } - if ospfInterface["demand_circuit"].(bool) { - configSet = append(configSet, setPrefix+"demand-circuit") - } - if ospfInterface["disable"].(bool) { - configSet = append(configSet, setPrefix+"disable") - } - if ospfInterface["dynamic_neighbors"].(bool) { - configSet = append(configSet, setPrefix+"dynamic-neighbors") - } - if ospfInterface["flood_reduction"].(bool) { - configSet = append(configSet, setPrefix+"flood-reduction") - } - if v := ospfInterface["hello_interval"].(int); v != 0 { - configSet = append(configSet, setPrefix+"hello-interval "+strconv.Itoa(v)) - } - if v := ospfInterface["interface_type"].(string); v != "" { - configSet = append(configSet, setPrefix+"interface-type "+v) - } - if v := ospfInterface["ipsec_sa"].(string); v != "" { - configSet = append(configSet, setPrefix+"ipsec-sa \""+v+"\"") - } - if t := ospfInterface["ipv4_adjacency_segment_protected_type"].(string); t != "" { - if v := ospfInterface["ipv4_adjacency_segment_protected_value"].(string); v != "" { - configSet = append(configSet, setPrefix+"ipv4-adjacency-segment protected "+t+" "+v) - } else { - configSet = append(configSet, setPrefix+"ipv4-adjacency-segment protected "+t) - } - } else if ospfInterface["ipv4_adjacency_segment_protected_value"].(string) != "" { - return configSet, errors.New("ipv4_adjacency_segment_protected_type need to be set with " + - "ipv4_adjacency_segment_protected_value") - } - if t := ospfInterface["ipv4_adjacency_segment_unprotected_type"].(string); t != "" { - if v := ospfInterface["ipv4_adjacency_segment_unprotected_value"].(string); v != "" { - configSet = append(configSet, setPrefix+"ipv4-adjacency-segment unprotected "+t+" "+v) - } else { - configSet = append(configSet, setPrefix+"ipv4-adjacency-segment unprotected "+t) - } - } else if ospfInterface["ipv4_adjacency_segment_unprotected_value"].(string) != "" { - return configSet, errors.New("ipv4_adjacency_segment_unprotected_type need to be set with " + - "ipv4_adjacency_segment_unprotected_value") - } - if ospfInterface["link_protection"].(bool) { - configSet = append(configSet, setPrefix+"link-protection") - } - if v := ospfInterface["metric"].(int); v != 0 { - configSet = append(configSet, setPrefix+"metric "+strconv.Itoa(v)) - } - if v := ospfInterface["mtu"].(int); v != 0 { - configSet = append(configSet, setPrefix+"mtu "+strconv.Itoa(v)) - } - neighborList := make([]string, 0) - for _, mNeighbor := range ospfInterface["neighbor"].(*schema.Set).List() { - neighbor := mNeighbor.(map[string]interface{}) - if slices.Contains(neighborList, neighbor["address"].(string)) { - return configSet, fmt.Errorf("multiple blocks neighbor with the same address %s in interface with name %s", - neighbor["address"].(string), ospfInterface["name"].(string)) - } - neighborList = append(neighborList, neighbor["address"].(string)) - configSet = append(configSet, setPrefix+"neighbor "+neighbor["address"].(string)) - if neighbor["eligible"].(bool) { - configSet = append(configSet, setPrefix+"neighbor "+neighbor["address"].(string)+" eligible") - } - } - if ospfInterface["no_advertise_adjacency_segment"].(bool) { - configSet = append(configSet, setPrefix+"no-advertise-adjacency-segment") - } - if ospfInterface["no_eligible_backup"].(bool) { - configSet = append(configSet, setPrefix+"no-eligible-backup") - } - if ospfInterface["no_eligible_remote_backup"].(bool) { - configSet = append(configSet, setPrefix+"no-eligible-remote-backup") - } - if ospfInterface["no_interface_state_traps"].(bool) { - configSet = append(configSet, setPrefix+"no-interface-state-traps") - } - if ospfInterface["no_neighbor_down_notification"].(bool) { - configSet = append(configSet, setPrefix+"no-neighbor-down-notification") - } - if ospfInterface["node_link_protection"].(bool) { - configSet = append(configSet, setPrefix+"node-link-protection") - } - if ospfInterface["passive"].(bool) { - configSet = append(configSet, setPrefix+"passive") - if v := ospfInterface["passive_traffic_engineering_remote_node_id"].(string); v != "" { - configSet = append(configSet, setPrefix+"passive traffic-engineering remote-node-id "+v) - } - if v := ospfInterface["passive_traffic_engineering_remote_node_router_id"].(string); v != "" { - configSet = append(configSet, setPrefix+"passive traffic-engineering remote-node-router-id "+v) - } - } else if ospfInterface["passive_traffic_engineering_remote_node_id"].(string) != "" || - ospfInterface["passive_traffic_engineering_remote_node_router_id"].(string) != "" { - return configSet, errors.New("passive need to be true with " + - "passive_traffic_engineering_remote_node_id and passive_traffic_engineering_remote_node_router_id") - } - if v := ospfInterface["poll_interval"].(int); v != 0 { - configSet = append(configSet, setPrefix+"poll-interval "+strconv.Itoa(v)) - } - if v := ospfInterface["priority"].(int); v != -1 { - configSet = append(configSet, setPrefix+"priority "+strconv.Itoa(v)) - } - if v := ospfInterface["retransmit_interval"].(int); v != 0 { - configSet = append(configSet, setPrefix+"retransmit-interval "+strconv.Itoa(v)) - } - if ospfInterface["secondary"].(bool) { - configSet = append(configSet, setPrefix+"secondary") - } - if ospfInterface["strict_bfd"].(bool) { - configSet = append(configSet, setPrefix+"strict-bfd") - } - if v := ospfInterface["te_metric"].(int); v != 0 { - configSet = append(configSet, setPrefix+"te-metric "+strconv.Itoa(v)) - } - if v := ospfInterface["transit_delay"].(int); v != 0 { - configSet = append(configSet, setPrefix+"transit-delay "+strconv.Itoa(v)) - } - - return configSet, nil -} - -func readOspfArea(idArea, version, realm, routingInstance string, junSess *junos.Session, -) (confRead ospfAreaOptions, err error) { - var showConfig string - ospfVersion := junos.OspfV2 - if version == "v3" { - ospfVersion = junos.OspfV3 - } else if realm != "" { - return confRead, errors.New("realm can't set if version != v3") - } - switch { - case routingInstance == junos.DefaultW && realm == "": - showConfig, err = junSess.Command(junos.CmdShowConfig + - "protocols " + ospfVersion + " area " + idArea + junos.PipeDisplaySetRelative) - if err != nil { - return confRead, err - } - case routingInstance == junos.DefaultW && realm != "": - showConfig, err = junSess.Command(junos.CmdShowConfig + - "protocols " + ospfVersion + " realm " + realm + " area " + idArea + junos.PipeDisplaySetRelative) - if err != nil { - return confRead, err - } - case realm != "": - showConfig, err = junSess.Command(junos.CmdShowConfig + junos.RoutingInstancesWS + routingInstance + " " + - "protocols " + ospfVersion + " realm " + realm + " area " + idArea + junos.PipeDisplaySetRelative) - if err != nil { - return confRead, err - } - default: - showConfig, err = junSess.Command(junos.CmdShowConfig + junos.RoutingInstancesWS + routingInstance + " " + - "protocols " + ospfVersion + " area " + idArea + junos.PipeDisplaySetRelative) - if err != nil { - return confRead, err - } - } - - if showConfig != junos.EmptyW { - confRead.areaID = idArea - confRead.realm = realm - confRead.version = version - confRead.routingInstance = routingInstance - for _, item := range strings.Split(showConfig, "\n") { - if strings.Contains(item, junos.XMLStartTagConfigOut) { - continue - } - if strings.Contains(item, junos.XMLEndTagConfigOut) { - break - } - itemTrim := strings.TrimPrefix(item, junos.SetLS) - switch { - case balt.CutPrefixInString(&itemTrim, "interface "): - itemTrimFields := strings.Split(itemTrim, " ") - interfaceOptions := map[string]interface{}{ - "name": itemTrimFields[0], - "authentication_simple_password": "", - "authentication_md5": make([]map[string]interface{}, 0), - "bandwidth_based_metrics": make([]map[string]interface{}, 0), - "bfd_liveness_detection": make([]map[string]interface{}, 0), - "dead_interval": 0, - "demand_circuit": false, - "disable": false, - "dynamic_neighbors": false, - "flood_reduction": false, - "hello_interval": 0, - "interface_type": "", - "ipsec_sa": "", - "ipv4_adjacency_segment_protected_type": "", - "ipv4_adjacency_segment_protected_value": "", - "ipv4_adjacency_segment_unprotected_type": "", - "ipv4_adjacency_segment_unprotected_value": "", - "link_protection": false, - "metric": 0, - "mtu": 0, - "neighbor": make([]map[string]interface{}, 0), - "no_advertise_adjacency_segment": false, - "no_eligible_backup": false, - "no_eligible_remote_backup": false, - "no_interface_state_traps": false, - "no_neighbor_down_notification": false, - "node_link_protection": false, - "passive": false, - "passive_traffic_engineering_remote_node_id": "", - "passive_traffic_engineering_remote_node_router_id": "", - "poll_interval": 0, - "priority": -1, - "retransmit_interval": 0, - "secondary": false, - "strict_bfd": false, - "te_metric": 0, - "transit_delay": 0, - } - balt.CutPrefixInString(&itemTrim, itemTrimFields[0]+" ") - confRead.interFace = copyAndRemoveItemMapList("name", interfaceOptions, confRead.interFace) - if err := readOspfAreaInterface(itemTrim, interfaceOptions); err != nil { - return confRead, err - } - confRead.interFace = append(confRead.interFace, interfaceOptions) - case balt.CutPrefixInString(&itemTrim, "area-range "): - itemTrimFields := strings.Split(itemTrim, " ") - areaRange := map[string]interface{}{ - "range": itemTrimFields[0], - "exact": false, - "override_metric": 0, - "restrict": false, - } - confRead.areaRange = copyAndRemoveItemMapList("range", areaRange, confRead.areaRange) - balt.CutPrefixInString(&itemTrim, itemTrimFields[0]+" ") - switch { - case itemTrim == "exact": - areaRange["exact"] = true - case balt.CutPrefixInString(&itemTrim, "override-metric "): - areaRange["override_metric"], err = strconv.Atoi(itemTrim) - if err != nil { - return confRead, fmt.Errorf(failedConvAtoiError, itemTrim, err) - } - case itemTrim == "restrict": - areaRange["restrict"] = true - } - confRead.areaRange = append(confRead.areaRange, areaRange) - case balt.CutPrefixInString(&itemTrim, "context-identifier "): - confRead.contextIdentifier = append(confRead.contextIdentifier, itemTrim) - case balt.CutPrefixInString(&itemTrim, "inter-area-prefix-export "): - confRead.interAreaPrefixExport = append(confRead.interAreaPrefixExport, itemTrim) - case balt.CutPrefixInString(&itemTrim, "inter-area-prefix-import "): - confRead.interAreaPrefixImport = append(confRead.interAreaPrefixImport, itemTrim) - case balt.CutPrefixInString(&itemTrim, "network-summary-export "): - confRead.networkSummaryExport = append(confRead.networkSummaryExport, itemTrim) - case balt.CutPrefixInString(&itemTrim, "network-summary-import "): - confRead.networkSummaryImport = append(confRead.networkSummaryImport, itemTrim) - case itemTrim == "no-context-identifier-advertisement": - confRead.noContextIdentifierAdvertisement = true - case balt.CutPrefixInString(&itemTrim, "nssa"): - if len(confRead.nssa) == 0 { - confRead.nssa = append(confRead.nssa, map[string]interface{}{ - "area_range": make([]map[string]interface{}, 0), - "default_lsa": make([]map[string]interface{}, 0), - "no_summaries": false, - "summaries": false, - }) - } - switch { - case balt.CutPrefixInString(&itemTrim, " area-range "): - itemTrimFields := strings.Split(itemTrim, " ") - areaRange := map[string]interface{}{ - "range": itemTrimFields[0], - "exact": false, - "override_metric": 0, - "restrict": false, - } - confRead.nssa[0]["area_range"] = copyAndRemoveItemMapList( - "range", - areaRange, - confRead.nssa[0]["area_range"].([]map[string]interface{}), - ) - balt.CutPrefixInString(&itemTrim, itemTrimFields[0]+" ") - switch { - case itemTrim == "exact": - areaRange["exact"] = true - case balt.CutPrefixInString(&itemTrim, "override-metric "): - areaRange["override_metric"], err = strconv.Atoi(itemTrim) - if err != nil { - return confRead, fmt.Errorf(failedConvAtoiError, itemTrim, err) - } - case itemTrim == "restrict": - areaRange["restrict"] = true - } - confRead.nssa[0]["area_range"] = append(confRead.nssa[0]["area_range"].([]map[string]interface{}), areaRange) - case balt.CutPrefixInString(&itemTrim, " default-lsa"): - if len(confRead.nssa[0]["default_lsa"].([]map[string]interface{})) == 0 { - confRead.nssa[0]["default_lsa"] = append( - confRead.nssa[0]["default_lsa"].([]map[string]interface{}), - map[string]interface{}{ - "default_metric": 0, - "metric_type": 0, - "type_7": false, - }) - } - defaultLsa := confRead.nssa[0]["default_lsa"].([]map[string]interface{})[0] - switch { - case balt.CutPrefixInString(&itemTrim, " default-metric "): - defaultLsa["default_metric"], err = strconv.Atoi(itemTrim) - if err != nil { - return confRead, fmt.Errorf(failedConvAtoiError, itemTrim, err) - } - case balt.CutPrefixInString(&itemTrim, " metric-type "): - defaultLsa["metric_type"], err = strconv.Atoi(itemTrim) - if err != nil { - return confRead, fmt.Errorf(failedConvAtoiError, itemTrim, err) - } - case itemTrim == " type-7": - defaultLsa["type_7"] = true - } - case itemTrim == " no-summaries": - confRead.nssa[0]["no_summaries"] = true - case itemTrim == " summaries": - confRead.nssa[0]["summaries"] = true - } - case balt.CutPrefixInString(&itemTrim, "stub"): - if len(confRead.stub) == 0 { - confRead.stub = append(confRead.stub, map[string]interface{}{ - "default_metric": 0, - "no_summaries": false, - "summaries": false, - }) - } - switch { - case balt.CutPrefixInString(&itemTrim, " default-metric "): - confRead.stub[0]["default_metric"], err = strconv.Atoi(itemTrim) - if err != nil { - return confRead, fmt.Errorf(failedConvAtoiError, itemTrim, err) - } - case itemTrim == " no-summaries": - confRead.stub[0]["no_summaries"] = true - case itemTrim == " summaries": - confRead.stub[0]["summaries"] = true - } - case balt.CutPrefixInString(&itemTrim, "virtual-link "): - itemTrimFields := strings.Split(itemTrim, " ") - if len(itemTrimFields) < 4 { // neighbor-id transit-area - return confRead, fmt.Errorf(junos.CantReadValuesNotEnoughFields, "virtual-link", itemTrim) - } - virtualLink := map[string]interface{}{ - "neighbor_id": itemTrimFields[1], - "transit_area": itemTrimFields[3], - "dead_interval": 0, - "demand_circuit": false, - "disable": false, - "flood_reduction": false, - "hello_interval": 0, - "ipsec_sa": "", - "mtu": 0, - "retransmit_interval": 0, - "transit_delay": 0, - } - confRead.virtualLink = copyAndRemoveItemMapList2("neighbor_id", "transit_area", virtualLink, confRead.virtualLink) - balt.CutPrefixInString(&itemTrim, "neighbor-id "+itemTrimFields[1]+" transit-area "+itemTrimFields[3]+" ") - switch { - case balt.CutPrefixInString(&itemTrim, "dead-interval "): - virtualLink["dead_interval"], err = strconv.Atoi(itemTrim) - case itemTrim == "demand-circuit": - virtualLink["demand_circuit"] = true - case itemTrim == "disable": - virtualLink["disable"] = true - case itemTrim == "flood-reduction": - virtualLink["flood_reduction"] = true - case balt.CutPrefixInString(&itemTrim, "hello-interval "): - virtualLink["hello_interval"], err = strconv.Atoi(itemTrim) - case balt.CutPrefixInString(&itemTrim, "ipsec-sa "): - virtualLink["ipsec_sa"] = strings.Trim(itemTrim, "\"") - case balt.CutPrefixInString(&itemTrim, "mtu "): - virtualLink["mtu"], err = strconv.Atoi(itemTrim) - case balt.CutPrefixInString(&itemTrim, "retransmit-interval "): - virtualLink["retransmit_interval"], err = strconv.Atoi(itemTrim) - case balt.CutPrefixInString(&itemTrim, "transit-delay "): - virtualLink["transit_delay"], err = strconv.Atoi(itemTrim) - } - if err != nil { - return confRead, fmt.Errorf(failedConvAtoiError, itemTrim, err) - } - confRead.virtualLink = append(confRead.virtualLink, virtualLink) - } - } - } - - return confRead, nil -} - -func readOspfAreaInterface(itemTrim string, interfaceOptions map[string]interface{}) (err error) { - switch { - case balt.CutPrefixInString(&itemTrim, "authentication simple-password "): - interfaceOptions["authentication_simple_password"], err = jdecode.Decode(strings.Trim(itemTrim, "\"")) - if err != nil { - return fmt.Errorf("decoding authentication simple-password: %w", err) - } - case balt.CutPrefixInString(&itemTrim, "authentication md5 "): - itemTrimFields := strings.Split(itemTrim, " ") - keyID, err := strconv.Atoi(itemTrimFields[0]) - if err != nil { - return fmt.Errorf(failedConvAtoiError, itemTrimFields[0], err) - } - authMD5 := map[string]interface{}{ - "key_id": keyID, - "key": "", - "start_time": "", - } - interfaceOptions["authentication_md5"] = copyAndRemoveItemMapList("key_id", authMD5, - interfaceOptions["authentication_md5"].([]map[string]interface{})) - balt.CutPrefixInString(&itemTrim, itemTrimFields[0]+" ") - switch { - case balt.CutPrefixInString(&itemTrim, "key "): - authMD5["key"], err = jdecode.Decode(strings.Trim(itemTrim, "\"")) - if err != nil { - return fmt.Errorf("decoding authentication md5 key: %w", err) - } - case balt.CutPrefixInString(&itemTrim, "start-time "): - authMD5["start_time"] = strings.Split(strings.Trim(itemTrim, "\""), " ")[0] - } - interfaceOptions["authentication_md5"] = append( - interfaceOptions["authentication_md5"].([]map[string]interface{}), authMD5) - case balt.CutPrefixInString(&itemTrim, "bandwidth-based-metrics bandwidth "): - itemTrimFields := strings.Split(itemTrim, " ") - if len(itemTrimFields) < 3 { // metric - return fmt.Errorf(junos.CantReadValuesNotEnoughFields, "bandwidth-based-metrics bandwidth", itemTrim) - } - metric, err := strconv.Atoi(itemTrimFields[2]) - if err != nil { - return fmt.Errorf(failedConvAtoiError, itemTrimFields[2], err) - } - interfaceOptions["bandwidth_based_metrics"] = append( - interfaceOptions["bandwidth_based_metrics"].([]map[string]interface{}), map[string]interface{}{ - "bandwidth": itemTrimFields[0], - "metric": metric, - }) - case balt.CutPrefixInString(&itemTrim, "bfd-liveness-detection "): - if len(interfaceOptions["bfd_liveness_detection"].([]map[string]interface{})) == 0 { - interfaceOptions["bfd_liveness_detection"] = append( - interfaceOptions["bfd_liveness_detection"].([]map[string]interface{}), map[string]interface{}{ - "authentication_algorithm": "", - "authentication_key_chain": "", - "authentication_loose_check": false, - "detection_time_threshold": 0, - "full_neighbors_only": false, - "holddown_interval": 0, - "minimum_interval": 0, - "minimum_receive_interval": 0, - "multiplier": 0, - "no_adaptation": false, - "transmit_interval_minimum_interval": 0, - "transmit_interval_threshold": 0, - "version": "", - }) - } - if err := readOspfAreaInterfaceBfd(itemTrim, - interfaceOptions["bfd_liveness_detection"].([]map[string]interface{})[0]); err != nil { - return err - } - case balt.CutPrefixInString(&itemTrim, "dead-interval "): - interfaceOptions["dead_interval"], err = strconv.Atoi(itemTrim) - if err != nil { - return fmt.Errorf(failedConvAtoiError, itemTrim, err) - } - case itemTrim == "demand-circuit": - interfaceOptions["demand_circuit"] = true - case itemTrim == junos.DisableW: - interfaceOptions["disable"] = true - case itemTrim == "dynamic-neighbors": - interfaceOptions["dynamic_neighbors"] = true - case itemTrim == "flood-reduction": - interfaceOptions["flood_reduction"] = true - case balt.CutPrefixInString(&itemTrim, "hello-interval "): - interfaceOptions["hello_interval"], err = strconv.Atoi(itemTrim) - if err != nil { - return fmt.Errorf(failedConvAtoiError, itemTrim, err) - } - case balt.CutPrefixInString(&itemTrim, "interface-type "): - interfaceOptions["interface_type"] = itemTrim - case balt.CutPrefixInString(&itemTrim, "ipsec-sa "): - interfaceOptions["ipsec_sa"] = strings.Trim(itemTrim, "\"") - case balt.CutPrefixInString(&itemTrim, "ipv4-adjacency-segment protected "): - itemTrimFields := strings.Split(itemTrim, " ") - interfaceOptions["ipv4_adjacency_segment_protected_type"] = itemTrimFields[0] - if len(itemTrimFields) > 1 { // - interfaceOptions["ipv4_adjacency_segment_protected_value"] = itemTrimFields[1] - } - case balt.CutPrefixInString(&itemTrim, "ipv4-adjacency-segment unprotected "): - itemTrimFields := strings.Split(itemTrim, " ") - interfaceOptions["ipv4_adjacency_segment_unprotected_type"] = itemTrimFields[0] - if len(itemTrimFields) > 1 { // - interfaceOptions["ipv4_adjacency_segment_unprotected_value"] = itemTrimFields[1] - } - case itemTrim == "link-protection": - interfaceOptions["link_protection"] = true - case balt.CutPrefixInString(&itemTrim, "metric "): - interfaceOptions["metric"], err = strconv.Atoi(itemTrim) - if err != nil { - return fmt.Errorf(failedConvAtoiError, itemTrim, err) - } - case balt.CutPrefixInString(&itemTrim, "mtu "): - interfaceOptions["mtu"], err = strconv.Atoi(itemTrim) - if err != nil { - return fmt.Errorf(failedConvAtoiError, itemTrim, err) - } - case balt.CutPrefixInString(&itemTrim, "neighbor "): - itemTrimFields := strings.Split(itemTrim, " ") //
(eligible)? - address := itemTrimFields[0] - if len(itemTrimFields) > 1 && itemTrimFields[1] == "eligible" { - interfaceOptions["neighbor"] = append( - interfaceOptions["neighbor"].([]map[string]interface{}), map[string]interface{}{ - "address": address, - "eligible": true, - }) - } else { - interfaceOptions["neighbor"] = append( - interfaceOptions["neighbor"].([]map[string]interface{}), map[string]interface{}{ - "address": address, - "eligible": false, - }) - } - case itemTrim == "no-advertise-adjacency-segment": - interfaceOptions["no_advertise_adjacency_segment"] = true - case itemTrim == "no-eligible-backup": - interfaceOptions["no_eligible_backup"] = true - case itemTrim == "no-eligible-remote-backup": - interfaceOptions["no_eligible_remote_backup"] = true - case itemTrim == "no-interface-state-traps": - interfaceOptions["no_interface_state_traps"] = true - case itemTrim == "no-neighbor-down-notification": - interfaceOptions["no_neighbor_down_notification"] = true - case itemTrim == "node-link-protection": - interfaceOptions["node_link_protection"] = true - case balt.CutPrefixInString(&itemTrim, "passive"): - interfaceOptions["passive"] = true - switch { - case balt.CutPrefixInString(&itemTrim, " traffic-engineering remote-node-id "): - interfaceOptions["passive_traffic_engineering_remote_node_id"] = itemTrim - case balt.CutPrefixInString(&itemTrim, " traffic-engineering remote-node-router-id "): - interfaceOptions["passive_traffic_engineering_remote_node_router_id"] = itemTrim - } - case balt.CutPrefixInString(&itemTrim, "poll-interval "): - interfaceOptions["poll_interval"], err = strconv.Atoi(itemTrim) - if err != nil { - return fmt.Errorf(failedConvAtoiError, itemTrim, err) - } - case balt.CutPrefixInString(&itemTrim, "priority "): - interfaceOptions["priority"], err = strconv.Atoi(itemTrim) - if err != nil { - return fmt.Errorf(failedConvAtoiError, itemTrim, err) - } - case balt.CutPrefixInString(&itemTrim, "retransmit-interval "): - interfaceOptions["retransmit_interval"], err = strconv.Atoi(itemTrim) - if err != nil { - return fmt.Errorf(failedConvAtoiError, itemTrim, err) - } - case itemTrim == "secondary": - interfaceOptions["secondary"] = true - case itemTrim == "strict-bfd": - interfaceOptions["strict_bfd"] = true - case balt.CutPrefixInString(&itemTrim, "te-metric "): - interfaceOptions["te_metric"], err = strconv.Atoi(itemTrim) - if err != nil { - return fmt.Errorf(failedConvAtoiError, itemTrim, err) - } - case balt.CutPrefixInString(&itemTrim, "transit-delay "): - interfaceOptions["transit_delay"], err = strconv.Atoi(itemTrim) - if err != nil { - return fmt.Errorf(failedConvAtoiError, itemTrim, err) - } - } - - return nil -} - -func readOspfAreaInterfaceBfd(itemTrim string, bfd map[string]interface{}) (err error) { - switch { - case balt.CutPrefixInString(&itemTrim, "authentication algorithm "): - bfd["authentication_algorithm"] = itemTrim - case balt.CutPrefixInString(&itemTrim, "authentication key-chain "): - bfd["authentication_key_chain"] = strings.Trim(itemTrim, "\"") - case itemTrim == "authentication loose-check": - bfd["authentication_loose_check"] = true - case balt.CutPrefixInString(&itemTrim, "detection-time threshold "): - bfd["detection_time_threshold"], err = strconv.Atoi(itemTrim) - if err != nil { - return fmt.Errorf(failedConvAtoiError, itemTrim, err) - } - case itemTrim == "full-neighbors-only": - bfd["full_neighbors_only"] = true - case balt.CutPrefixInString(&itemTrim, "holddown-interval "): - bfd["holddown_interval"], err = strconv.Atoi(itemTrim) - if err != nil { - return fmt.Errorf(failedConvAtoiError, itemTrim, err) - } - case balt.CutPrefixInString(&itemTrim, "minimum-interval "): - bfd["minimum_interval"], err = strconv.Atoi(itemTrim) - if err != nil { - return fmt.Errorf(failedConvAtoiError, itemTrim, err) - } - case balt.CutPrefixInString(&itemTrim, "minimum-receive-interval "): - bfd["minimum_receive_interval"], err = strconv.Atoi(itemTrim) - if err != nil { - return fmt.Errorf(failedConvAtoiError, itemTrim, err) - } - case balt.CutPrefixInString(&itemTrim, "multiplier "): - bfd["multiplier"], err = strconv.Atoi(itemTrim) - if err != nil { - return fmt.Errorf(failedConvAtoiError, itemTrim, err) - } - case itemTrim == "no-adaptation": - bfd["no_adaptation"] = true - case balt.CutPrefixInString(&itemTrim, "transmit-interval minimum-interval "): - bfd["transmit_interval_minimum_interval"], err = strconv.Atoi(itemTrim) - if err != nil { - return fmt.Errorf(failedConvAtoiError, itemTrim, err) - } - case balt.CutPrefixInString(&itemTrim, "transmit-interval threshold "): - bfd["transmit_interval_threshold"], err = strconv.Atoi(itemTrim) - if err != nil { - return fmt.Errorf(failedConvAtoiError, itemTrim, err) - } - case balt.CutPrefixInString(&itemTrim, "version "): - bfd["version"] = itemTrim - } - - return nil -} - -func delOspfArea(d *schema.ResourceData, junSess *junos.Session) error { - configSet := make([]string, 0, 1) - ospfVersion := junos.OspfV2 - if d.Get("version").(string) == "v3" { - ospfVersion = junos.OspfV3 - } else if d.Get("realm").(string) != "" { - return errors.New("realm can't set if version != v3") - } - switch { - case d.Get("routing_instance").(string) == junos.DefaultW && d.Get("realm").(string) == "": - configSet = append(configSet, junos.DeleteW+ - " protocols "+ospfVersion+ - " area "+d.Get("area_id").(string)) - case d.Get("routing_instance").(string) == junos.DefaultW && d.Get("realm").(string) != "": - configSet = append(configSet, junos.DeleteW+ - " protocols "+ospfVersion+ - " realm "+d.Get("realm").(string)+ - " area "+d.Get("area_id").(string)) - case d.Get("realm").(string) != "": - configSet = append(configSet, junos.DelRoutingInstances+d.Get("routing_instance").(string)+ - " protocols "+ospfVersion+ - " realm "+d.Get("realm").(string)+ - " area "+d.Get("area_id").(string)) - default: - configSet = append(configSet, junos.DelRoutingInstances+d.Get("routing_instance").(string)+ - " protocols "+ospfVersion+ - " area "+d.Get("area_id").(string)) - } - - return junSess.ConfigSet(configSet) -} - -func fillOspfAreaData(d *schema.ResourceData, ospfAreaOptions ospfAreaOptions) { - if tfErr := d.Set("area_id", ospfAreaOptions.areaID); tfErr != nil { - panic(tfErr) - } - if tfErr := d.Set("routing_instance", ospfAreaOptions.routingInstance); tfErr != nil { - panic(tfErr) - } - if tfErr := d.Set("realm", ospfAreaOptions.realm); tfErr != nil { - panic(tfErr) - } - if tfErr := d.Set("version", ospfAreaOptions.version); tfErr != nil { - panic(tfErr) - } - if tfErr := d.Set("interface", ospfAreaOptions.interFace); tfErr != nil { - panic(tfErr) - } - if tfErr := d.Set("area_range", ospfAreaOptions.areaRange); tfErr != nil { - panic(tfErr) - } - if tfErr := d.Set("context_identifier", ospfAreaOptions.contextIdentifier); tfErr != nil { - panic(tfErr) - } - if tfErr := d.Set("inter_area_prefix_export", ospfAreaOptions.interAreaPrefixExport); tfErr != nil { - panic(tfErr) - } - if tfErr := d.Set("inter_area_prefix_import", ospfAreaOptions.interAreaPrefixImport); tfErr != nil { - panic(tfErr) - } - if tfErr := d.Set("network_summary_export", ospfAreaOptions.networkSummaryExport); tfErr != nil { - panic(tfErr) - } - if tfErr := d.Set("network_summary_import", ospfAreaOptions.networkSummaryImport); tfErr != nil { - panic(tfErr) - } - if tfErr := d.Set( - "no_context_identifier_advertisement", - ospfAreaOptions.noContextIdentifierAdvertisement, - ); tfErr != nil { - panic(tfErr) - } - if tfErr := d.Set("nssa", ospfAreaOptions.nssa); tfErr != nil { - panic(tfErr) - } - if tfErr := d.Set("stub", ospfAreaOptions.stub); tfErr != nil { - panic(tfErr) - } - if tfErr := d.Set("virtual_link", ospfAreaOptions.virtualLink); tfErr != nil { - panic(tfErr) - } -} diff --git a/internal/providersdk/resource_ospf_area_test.go b/internal/providersdk/resource_ospf_area_test.go deleted file mode 100644 index 0824492a..00000000 --- a/internal/providersdk/resource_ospf_area_test.go +++ /dev/null @@ -1,498 +0,0 @@ -package providersdk_test - -import ( - "fmt" - "os" - "testing" - - "github.com/jeremmfr/terraform-provider-junos/internal/junos" - - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" -) - -// export TESTACC_INTERFACE= for choose interface available else it's ge-0/0/3. -// export TESTACC_INTERFACE2= for choose 2nd interface available else it's ge-0/0/4. -func TestAccResourceOspfArea_basic(t *testing.T) { - testaccOspfArea := junos.DefaultInterfaceTestAcc - testaccOspfArea2 := junos.DefaultInterfaceTestAcc2 - if iface := os.Getenv("TESTACC_INTERFACE"); iface != "" { - testaccOspfArea = iface - } - if iface := os.Getenv("TESTACC_INTERFACE2"); iface != "" { - testaccOspfArea2 = iface - } - if os.Getenv("TESTACC_SWITCH") == "" { - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - ProtoV5ProviderFactories: testAccProtoV5ProviderFactories, - Steps: []resource.TestStep{ - { - Config: testAccResourceOspfAreaConfigCreate(testaccOspfArea), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("junos_ospf_area.testacc_ospfarea", - "area_id", "0.0.0.0"), - resource.TestCheckResourceAttr("junos_ospf_area.testacc_ospfarea", - "version", "v2"), - resource.TestCheckResourceAttr("junos_ospf_area.testacc_ospfarea", - "routing_instance", "default"), - resource.TestCheckResourceAttr("junos_ospf_area.testacc_ospfarea", - "interface.#", "2"), - resource.TestCheckResourceAttr("junos_ospf_area.testacc_ospfarea", - "interface.0.name", "all"), - resource.TestCheckResourceAttr("junos_ospf_area.testacc_ospfarea", - "interface.0.disable", "true"), - resource.TestCheckResourceAttr("junos_ospf_area.testacc_ospfarea", - "interface.0.passive", "true"), - resource.TestCheckResourceAttr("junos_ospf_area.testacc_ospfarea", - "interface.0.metric", "100"), - resource.TestCheckResourceAttr("junos_ospf_area.testacc_ospfarea", - "interface.0.retransmit_interval", "12"), - resource.TestCheckResourceAttr("junos_ospf_area.testacc_ospfarea", - "interface.0.hello_interval", "11"), - resource.TestCheckResourceAttr("junos_ospf_area.testacc_ospfarea", - "interface.0.dead_interval", "10"), - ), - }, - { - Config: testAccResourceOspfAreaConfigUpdate(testaccOspfArea, testaccOspfArea2), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("junos_ospf_area.testacc_ospfarea", - "interface.#", "2"), - resource.TestCheckResourceAttr("junos_ospf_area.testacc_ospfarea2", - "routing_instance", "testacc_ospfarea"), - resource.TestCheckResourceAttr("junos_ospf_area.testacc_ospfarea2", - "version", "v3"), - resource.TestCheckResourceAttr("junos_ospf_area.testacc_ospfarea2", - "interface.#", "2"), - resource.TestCheckResourceAttr("junos_ospf_area.testacc_ospfarea2", - "interface.1.name", testaccOspfArea2+".0"), - resource.TestCheckResourceAttr("junos_ospf_area.testacc_ospfarea2", - "interface.1.bfd_liveness_detection.#", "1"), - ), - }, - { - ResourceName: "junos_ospf_area.testacc_ospfarea", - ImportState: true, - ImportStateVerify: true, - }, - { - ResourceName: "junos_ospf_area.testacc_ospfarea2", - ImportState: true, - ImportStateVerify: true, - }, - { - ResourceName: "junos_ospf_area.testacc_ospfareav3ipv4", - ImportState: true, - ImportStateVerify: true, - }, - { - ResourceName: "junos_ospf_area.testacc_ospfarea2v3realm", - ImportState: true, - ImportStateVerify: true, - }, - { - Config: testAccResourceOspfAreaConfigUpdate2(), - }, - { - Config: testAccResourceOspfAreaConfigUpdate3(), - }, - { - Config: testAccResourceOspfAreaConfigUpdate4(testaccOspfArea), - }, - { - Config: testAccResourceOspfAreaConfigUpdate5(testaccOspfArea), - }, - { - ResourceName: "junos_ospf_area.testacc_ospfarea", - ImportState: true, - ImportStateVerify: true, - }, - { - ResourceName: "junos_ospf_area.testacc_ospfarea2", - ImportState: true, - ImportStateVerify: true, - }, - { - ResourceName: "junos_ospf_area.testacc_ospfarea3", - ImportState: true, - ImportStateVerify: true, - }, - }, - }) - } -} - -func testAccResourceOspfAreaConfigCreate(interFace string) string { - return fmt.Sprintf(` -resource "junos_ospf_area" "testacc_ospfarea" { - area_id = "0.0.0.0" - interface { - name = "all" - disable = true - passive = true - metric = 100 - retransmit_interval = 12 - hello_interval = 11 - dead_interval = 10 - } - interface { - name = junos_interface_logical.testacc_ospfarea.name - secondary = true - } -} -resource "junos_ospf_area" "testacc_ospfareav3ipv4" { - area_id = "0.0.0.0" - version = "v3" - realm = "ipv4-unicast" - interface { - name = "all" - disable = true - } - interface { - name = junos_interface_logical.testacc_ospfarea.name - secondary = true - } -} -resource "junos_interface_logical" "testacc_ospfarea" { - name = "%s.0" - description = "testacc_ospfarea" -} -`, interFace) -} - -func testAccResourceOspfAreaConfigUpdate(interFace, interFace2 string) string { - return fmt.Sprintf(` -resource "junos_ospf_area" "testacc_ospfarea" { - area_id = "0.0.0.0" - interface { - name = "all" - passive = true - authentication_simple_password = "testPass" - link_protection = true - no_advertise_adjacency_segment = true - no_interface_state_traps = true - no_neighbor_down_notification = true - poll_interval = 19 - te_metric = 221 - } - interface { - name = junos_interface_logical.testacc_ospfarea.name - disable = true - authentication_md5 { - key_id = 3 - key = "testK3y" - } - authentication_md5 { - key_id = 2 - key = "testK3y2" - start_time = "2022-3-9.12:50:00" - } - strict_bfd = true - bfd_liveness_detection { - minimum_receive_interval = 29 - transmit_interval_minimum_interval = 48 - transmit_interval_threshold = 49 - version = "automatic" - } - neighbor { - address = "192.0.2.6" - } - neighbor { - address = "192.0.2.5" - eligible = "true" - } - } - network_summary_export = [junos_policyoptions_policy_statement.testacc_ospfarea.name] - network_summary_import = [junos_policyoptions_policy_statement.testacc_ospfarea2.name] -} -resource "junos_policyoptions_policy_statement" "testacc_ospfarea" { - name = "testacc_ospfarea" - then { - action = "accept" - } -} -resource "junos_policyoptions_policy_statement" "testacc_ospfarea2" { - name = "testacc_ospfarea2" - then { - action = "reject" - } -} -resource "junos_ospf_area" "testacc_ospfareav3ipv4" { - area_id = "0.0.0.0" - version = "v3" - realm = "ipv4-unicast" - interface { - name = junos_interface_logical.testacc_ospfarea.name - priority = 0 - bfd_liveness_detection { - full_neighbors_only = true - minimum_receive_interval = 27 - transmit_interval_minimum_interval = 50 - transmit_interval_threshold = 51 - } - } -} -resource "junos_interface_logical" "testacc_ospfarea" { - name = "%s.0" - description = "testacc_ospfarea" -} -resource "junos_interface_logical" "testacc_ospfarea2" { - name = "%s.0" - description = "testacc_ospfarea2" - routing_instance = junos_routing_instance.testacc_ospfarea.name -} -resource "junos_routing_instance" "testacc_ospfarea" { - name = "testacc_ospfarea" -} -resource "junos_ospf_area" "testacc_ospfarea2" { - area_id = "0.0.0.0" - version = "v3" - routing_instance = junos_routing_instance.testacc_ospfarea.name - interface { - name = "all" - passive = true - metric = 100 - retransmit_interval = 32 - hello_interval = 31 - dead_interval = 30 - bandwidth_based_metrics { - bandwidth = "100k" - metric = 13 - } - bandwidth_based_metrics { - bandwidth = "1m" - metric = 14 - } - demand_circuit = true - dynamic_neighbors = true - flood_reduction = true - interface_type = "p2mp" - mtu = 900 - no_eligible_backup = true - no_eligible_remote_backup = true - node_link_protection = true - passive_traffic_engineering_remote_node_id = "192.0.2.7" - passive_traffic_engineering_remote_node_router_id = "192.0.2.8" - priority = 21 - transit_delay = 23 - } - interface { - name = junos_interface_logical.testacc_ospfarea2.name - bfd_liveness_detection { - authentication_loose_check = true - detection_time_threshold = 60 - full_neighbors_only = true - holddown_interval = 15 - minimum_interval = 16 - minimum_receive_interval = 17 - multiplier = 2 - no_adaptation = true - transmit_interval_minimum_interval = 18 - transmit_interval_threshold = 19 - version = "automatic" - } - } -} -resource "junos_ospf_area" "testacc_ospfarea2v3realm" { - area_id = "0.0.0.0" - version = "v3" - realm = "ipv4-multicast" - routing_instance = junos_routing_instance.testacc_ospfarea.name - interface { - name = "all" - passive = true - } - interface { - name = junos_interface_logical.testacc_ospfarea2.name - bfd_liveness_detection { - version = "automatic" - minimum_receive_interval = 270 - transmit_interval_minimum_interval = 500 - transmit_interval_threshold = 510 - } - } -} -`, interFace, interFace2) -} - -func testAccResourceOspfAreaConfigUpdate2() string { - return ` -resource "junos_ospf_area" "testacc_ospfarea" { - area_id = "0.0.0.0" - version = "v3" - interface { - name = "all" - disable = true - } - virtual_link { - neighbor_id = "192.0.2.0" - transit_area = "192.0.2.1" - } -} -` -} - -func testAccResourceOspfAreaConfigUpdate3() string { - return ` -resource "junos_ospf_area" "testacc_ospfarea" { - area_id = "0.0.0.0" - version = "v3" - interface { - name = "all" - disable = true - } - virtual_link { - neighbor_id = "192.0.2.100" - transit_area = "192.0.2.101" - dead_interval = 102 - demand_circuit = true - disable = true - flood_reduction = true - hello_interval = 103 - mtu = 1040 - retransmit_interval = 105 - transit_delay = 106 - - } - virtual_link { - neighbor_id = "192.0.2.0" - transit_area = "192.0.2.1" - } -} -` -} - -func testAccResourceOspfAreaConfigUpdate4(interFace string) string { - return fmt.Sprintf(` -resource "junos_ospf_area" "testacc_ospfarea" { - area_id = "1" - version = "v3" - interface { - name = "all" - } - area_range { - range = "fe80::/64" - } - no_context_identifier_advertisement = true - inter_area_prefix_export = [ - junos_policyoptions_policy_statement.testacc_ospfarea2.name, - ] - inter_area_prefix_import = [ - junos_policyoptions_policy_statement.testacc_ospfarea.name, - ] - nssa {} -} -resource "junos_policyoptions_policy_statement" "testacc_ospfarea" { - name = "testacc_ospfarea" - then { - action = "accept" - } -} -resource "junos_policyoptions_policy_statement" "testacc_ospfarea2" { - name = "testacc_ospfarea2" - then { - action = "reject" - } -} -resource "junos_ospf_area" "testacc_ospfarea2" { - area_id = "2" - version = "v3" - interface { - name = "%s.0" - passive = true - } - stub {} -} -`, interFace) -} - -func testAccResourceOspfAreaConfigUpdate5(interFace string) string { - return fmt.Sprintf(` -resource "junos_ospf_area" "testacc_ospfarea" { - area_id = "1" - version = "v3" - interface { - name = "all" - } - area_range { - range = "fe80:f::/64" - exact = true - } - area_range { - range = "fe80:e::/64" - exact = true - override_metric = 106 - } - area_range { - range = "fe80::/64" - restrict = true - } - context_identifier = ["127.0.0.2", "127.0.0.1"] - inter_area_prefix_export = [ - junos_policyoptions_policy_statement.testacc_ospfarea.name, - junos_policyoptions_policy_statement.testacc_ospfarea2.name, - ] - inter_area_prefix_import = [ - junos_policyoptions_policy_statement.testacc_ospfarea2.name, - junos_policyoptions_policy_statement.testacc_ospfarea.name, - ] - nssa { - area_range { - range = "fe80::/64" - exact = true - } - area_range { - range = "fe80:b::/64" - override_metric = 107 - } - area_range { - range = "fe80:a::/64" - restrict = true - } - default_lsa { - default_metric = 109 - metric_type = 2 - type_7 = true - } - summaries = true - } -} -resource "junos_policyoptions_policy_statement" "testacc_ospfarea" { - name = "testacc_ospfarea" - then { - action = "accept" - } -} -resource "junos_policyoptions_policy_statement" "testacc_ospfarea2" { - name = "testacc_ospfarea2" - then { - action = "reject" - } -} -resource "junos_ospf_area" "testacc_ospfarea2" { - area_id = "2" - version = "v3" - interface { - name = "%s.0" - passive = true - } - stub { - default_metric = 150 - no_summaries = true - } -} -resource "junos_ospf_area" "testacc_ospfarea3" { - area_id = "3" - version = "v3" - realm = "ipv4-unicast" - interface { - name = "%s.0" - passive = true - } - nssa { - no_summaries = true - default_lsa {} - } -} -`, interFace, interFace) -} From d7d1dbb2ac8ccb7f51d444fb750ebf1589c84105 Mon Sep 17 00:00:00 2001 From: Jeremy Muriel Date: Mon, 1 Apr 2024 19:22:59 +0200 Subject: [PATCH 08/25] r/ospf: use new provider via framework --- .changes/ospf-with-fwk.md | 5 + docs/resources/ospf.md | 10 +- internal/providerfwk/provider.go | 1 + internal/providerfwk/resource_ospf.go | 1293 +++++++++++++++++ internal/providerfwk/resource_ospf_test.go | 37 + .../TestAccResourceOspf_basic/1/main.tf} | 84 -- .../TestAccResourceOspf_basic/3/main.tf | 38 + .../1/main.tf | 38 + .../1/provider.tf | 10 + .../2/main.tf | 1 + internal/providerfwk/upgradestate_ospf.go | 287 ++++ .../providerfwk/upgradestate_ospf_test.go | 31 + internal/providersdk/provider.go | 1 - internal/providersdk/resource_ospf.go | 967 ------------ 14 files changed, 1746 insertions(+), 1057 deletions(-) create mode 100644 internal/providerfwk/resource_ospf.go create mode 100644 internal/providerfwk/resource_ospf_test.go rename internal/{providersdk/resource_ospf_test.go => providerfwk/testdata/TestAccResourceOspf_basic/1/main.tf} (50%) create mode 100644 internal/providerfwk/testdata/TestAccResourceOspf_basic/3/main.tf create mode 100644 internal/providerfwk/testdata/TestAccUpgradeStateResourceOspf_V0toV1_basic/1/main.tf create mode 100644 internal/providerfwk/testdata/TestAccUpgradeStateResourceOspf_V0toV1_basic/1/provider.tf create mode 120000 internal/providerfwk/testdata/TestAccUpgradeStateResourceOspf_V0toV1_basic/2/main.tf create mode 100644 internal/providerfwk/upgradestate_ospf.go create mode 100644 internal/providerfwk/upgradestate_ospf_test.go delete mode 100644 internal/providersdk/resource_ospf.go diff --git a/.changes/ospf-with-fwk.md b/.changes/ospf-with-fwk.md index 12b348f6..1d52761b 100644 --- a/.changes/ospf-with-fwk.md +++ b/.changes/ospf-with-fwk.md @@ -8,5 +8,10 @@ ENHANCEMENTS: optional boolean attributes doesn't accept value *false* optional string attributes doesn't accept *empty* value the resource schema has been upgraded to have one-blocks in single mode instead of list +* **resource/junos_ospf**: resource now use new [terraform-plugin-framework](https://github.com/hashicorp/terraform-plugin-framework) + some of config errors are now sent during Plan instead of during Apply + optional boolean attributes doesn't accept value *false* + optional string attributes doesn't accept *empty* value + the resource schema has been upgraded to have one-blocks in single mode instead of list BUG FIXES: diff --git a/docs/resources/ospf.md b/docs/resources/ospf.md index 1a9638b0..3542d140 100644 --- a/docs/resources/ospf.md +++ b/docs/resources/ospf.md @@ -24,14 +24,14 @@ resource "junos_ospf" "ospf" { The following arguments are supported: -- **routing_instance** (Optional, String, Forces new resource) - Routing instance. - Need to be `default` (for root level) or the name of routing instance. - Defaults to `default`. - **version** (Optional, String) Version of ospf. Need to be `v2` or `v3`. Defaults to `v2`. +- **routing_instance** (Optional, String, Forces new resource) + Routing instance. + Need to be `default` (for root level) or the name of routing instance. + Defaults to `default`. - **database_protection** (Optional, Block) Declare `database-protection` configuration. - **maximum_lsa** (Required, Number) @@ -77,7 +77,7 @@ The following arguments are supported: - **labeled_preference** (Optional, Number) Preference of labeled routes. - **lsa_refresh_interval** (Optional, Number) - LSA refresh interval (minutes) (25..50). + LSA refresh interval (25..50 minutes). - **no_nssa_abr** (Optional, Boolean) Disable full NSSA functionality at ABR. - **no_rfc1583** (Optional, Boolean) diff --git a/internal/providerfwk/provider.go b/internal/providerfwk/provider.go index 2069cf31..ff05f24e 100644 --- a/internal/providerfwk/provider.go +++ b/internal/providerfwk/provider.go @@ -252,6 +252,7 @@ func (p *junosProvider) Resources(_ context.Context) []func() resource.Resource newMultichassisResource, newMultichassisProtectionPeerResource, newOamGretunnelInterfaceResource, + newOspfResource, newOspfAreaResource, newPolicyoptionsASPathResource, newPolicyoptionsASPathGroupResource, diff --git a/internal/providerfwk/resource_ospf.go b/internal/providerfwk/resource_ospf.go new file mode 100644 index 00000000..8762ebaf --- /dev/null +++ b/internal/providerfwk/resource_ospf.go @@ -0,0 +1,1293 @@ +package providerfwk + +import ( + "context" + "errors" + "fmt" + "regexp" + "strings" + + "github.com/jeremmfr/terraform-provider-junos/internal/junos" + "github.com/jeremmfr/terraform-provider-junos/internal/tfdata" + "github.com/jeremmfr/terraform-provider-junos/internal/tfdiag" + "github.com/jeremmfr/terraform-provider-junos/internal/tfplanmodifier" + "github.com/jeremmfr/terraform-provider-junos/internal/tfvalidator" + "github.com/jeremmfr/terraform-provider-junos/internal/utils" + + "github.com/hashicorp/terraform-plugin-framework-validators/int64validator" + "github.com/hashicorp/terraform-plugin-framework-validators/listvalidator" + "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/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" + balt "github.com/jeremmfr/go-utils/basicalter" +) + +// Ensure the implementation satisfies the expected interfaces. +var ( + _ resource.Resource = &ospf{} + _ resource.ResourceWithConfigure = &ospf{} + _ resource.ResourceWithValidateConfig = &ospf{} + _ resource.ResourceWithImportState = &ospf{} + _ resource.ResourceWithUpgradeState = &ospf{} +) + +type ospf struct { + client *junos.Client +} + +func newOspfResource() resource.Resource { + return &ospf{} +} + +func (rsc *ospf) typeName() string { + return providerName + "_ospf" +} + +func (rsc *ospf) junosName() string { + return "protocols ospf|ospf3" +} + +func (rsc *ospf) junosClient() *junos.Client { + return rsc.client +} + +func (rsc *ospf) Metadata( + _ context.Context, _ resource.MetadataRequest, resp *resource.MetadataResponse, +) { + resp.TypeName = rsc.typeName() +} + +func (rsc *ospf) Configure( + ctx context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse, +) { + // Prevent panic if the provider has not been configured. + if req.ProviderData == nil { + return + } + client, ok := req.ProviderData.(*junos.Client) + if !ok { + unexpectedResourceConfigureType(ctx, req, resp) + + return + } + rsc.client = client +} + +func (rsc *ospf) Schema( + _ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse, +) { + resp.Schema = schema.Schema{ + Version: 1, + Description: "Configure static configuration in `" + rsc.junosName() + "` block", + Attributes: map[string]schema.Attribute{ + "id": schema.StringAttribute{ + Computed: true, + Description: "An identifier for the resource with format " + + "`" + junos.IDSeparator + "`.", + PlanModifiers: []planmodifier.String{ + stringplanmodifier.UseStateForUnknown(), + }, + }, + "version": schema.StringAttribute{ + Optional: true, + Computed: true, + Default: stringdefault.StaticString("v2"), + Description: "Version of ospf.", + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + }, + Validators: []validator.String{ + stringvalidator.OneOf("v2", "v3"), + }, + }, + "routing_instance": schema.StringAttribute{ + Optional: true, + Computed: true, + Default: stringdefault.StaticString(junos.DefaultW), + Description: "Routing instance for ospf protocol if not root level.", + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + }, + Validators: []validator.String{ + stringvalidator.LengthBetween(1, 63), + tfvalidator.StringFormat(tfvalidator.DefaultFormat), + }, + }, + "disable": schema.BoolAttribute{ + Optional: true, + Description: "Disable OSPF.", + Validators: []validator.Bool{ + tfvalidator.BoolTrue(), + }, + }, + "domain_id": schema.StringAttribute{ + Optional: true, + Description: "Configure domain ID.", + Validators: []validator.String{ + stringvalidator.LengthAtLeast(1), + tfvalidator.StringDoubleQuoteExclusion(), + }, + }, + "export": schema.ListAttribute{ + ElementType: types.StringType, + Optional: true, + Description: "Export policy.", + Validators: []validator.List{ + listvalidator.SizeAtLeast(1), + listvalidator.ValueStringsAre( + stringvalidator.LengthAtLeast(1), + tfvalidator.StringDoubleQuoteExclusion(), + ), + }, + }, + "external_preference": schema.Int64Attribute{ + Optional: true, + Description: "Preference of external routes.", + Validators: []validator.Int64{ + int64validator.Between(0, 4294967295), + }, + }, + "forwarding_address_to_broadcast": schema.BoolAttribute{ + Optional: true, + Description: "Set forwarding address in Type 5 LSA in broadcast network.", + Validators: []validator.Bool{ + tfvalidator.BoolTrue(), + }, + }, + "import": schema.ListAttribute{ + ElementType: types.StringType, + Optional: true, + Description: "Import policy (for external routes or setting priority).", + Validators: []validator.List{ + listvalidator.SizeAtLeast(1), + listvalidator.ValueStringsAre( + stringvalidator.LengthAtLeast(1), + tfvalidator.StringDoubleQuoteExclusion(), + ), + }, + }, + "labeled_preference": schema.Int64Attribute{ + Optional: true, + Description: "Preference of labeled routes.", + Validators: []validator.Int64{ + int64validator.Between(0, 4294967295), + }, + }, + "lsa_refresh_interval": schema.Int64Attribute{ + Optional: true, + Description: "SA refresh interval (minutes).", + Validators: []validator.Int64{ + int64validator.Between(25, 50), + }, + }, + "no_nssa_abr": schema.BoolAttribute{ + Optional: true, + Description: "Disable full NSSA functionality at ABR.", + Validators: []validator.Bool{ + tfvalidator.BoolTrue(), + }, + }, + "no_rfc1583": schema.BoolAttribute{ + Optional: true, + Description: "Disable RFC1583 compatibility.", + Validators: []validator.Bool{ + tfvalidator.BoolTrue(), + }, + }, + "preference": schema.Int64Attribute{ + Optional: true, + Description: "Preference of internal routes.", + Validators: []validator.Int64{ + int64validator.Between(0, 4294967295), + }, + }, + "prefix_export_limit": schema.Int64Attribute{ + Optional: true, + Description: "Maximum number of prefixes that can be exported.", + Validators: []validator.Int64{ + int64validator.Between(0, 4294967295), + }, + }, + "reference_bandwidth": schema.StringAttribute{ + Optional: true, + Description: "Bandwidth for calculating metric defaults.", + Validators: []validator.String{ + stringvalidator.RegexMatches(regexp.MustCompile( + `^(\d)+(m|k|g)?$`), + `must be a bandwidth ^(\d)+(m|k|g)?$`), + }, + }, + "rib_group": schema.StringAttribute{ + Optional: true, + Description: "Routing table group for importing OSPF routes.", + Validators: []validator.String{ + stringvalidator.LengthAtLeast(1), + tfvalidator.StringDoubleQuoteExclusion(), + }, + }, + "sham_link": schema.BoolAttribute{ + Optional: true, + Description: "Configure parameters for sham links.", + Validators: []validator.Bool{ + tfvalidator.BoolTrue(), + }, + }, + "sham_link_local": schema.StringAttribute{ + Optional: true, + Description: "Local sham link endpoint address.", + Validators: []validator.String{ + tfvalidator.StringIPAddress(), + }, + }, + }, + Blocks: map[string]schema.Block{ + "database_protection": schema.SingleNestedBlock{ + Description: "Declare `database-protection` configuration.", + Attributes: map[string]schema.Attribute{ + "maximum_lsa": schema.Int64Attribute{ + Required: false, // true when SingleNestedBlock is specified + Optional: true, + Description: "Maximum allowed non self-generated LSAs.", + Validators: []validator.Int64{ + int64validator.Between(1, 1000000), + }, + }, + "ignore_count": schema.Int64Attribute{ + Optional: true, + Description: "Maximum number of times to go into ignore state.", + Validators: []validator.Int64{ + int64validator.Between(1, 32), + }, + }, + "ignore_time": schema.Int64Attribute{ + Optional: true, + Description: "Time to stay in ignore state and ignore all neighbors.", + Validators: []validator.Int64{ + int64validator.Between(30, 3600), + }, + }, + "reset_time": schema.Int64Attribute{ + Optional: true, + Description: "Time after which the ignore count gets reset to zero.", + Validators: []validator.Int64{ + int64validator.Between(60, 86400), + }, + }, + "warning_only": schema.BoolAttribute{ + Optional: true, + Description: "Emit only a warning when LSA maximum limit is exceeded.", + Validators: []validator.Bool{ + tfvalidator.BoolTrue(), + }, + }, + "warning_threshold": schema.Int64Attribute{ + Optional: true, + Description: "Percentage of LSA maximum above which to trigger warning (percent).", + Validators: []validator.Int64{ + int64validator.Between(30, 100), + }, + }, + }, + PlanModifiers: []planmodifier.Object{ + tfplanmodifier.BlockRemoveNull(), + }, + }, + "graceful_restart": schema.SingleNestedBlock{ + Description: "Declare `graceful-restart` configuration.", + Attributes: map[string]schema.Attribute{ + "disable": schema.BoolAttribute{ + Optional: true, + Description: "Disable OSPF graceful restart capability.", + Validators: []validator.Bool{ + tfvalidator.BoolTrue(), + }, + }, + "helper_disable": schema.BoolAttribute{ + Optional: true, + Description: "Disable graceful restart helper capability.", + Validators: []validator.Bool{ + tfvalidator.BoolTrue(), + }, + }, + "helper_disable_type": schema.StringAttribute{ + Optional: true, + Description: "Disable graceful restart helper capability for specific type.", + Validators: []validator.String{ + stringvalidator.OneOf("both", "restart-signaling", "standard"), + }, + }, + "no_strict_lsa_checking": schema.BoolAttribute{ + Optional: true, + Description: "Do not abort graceful helper mode upon LSA changes.", + Validators: []validator.Bool{ + tfvalidator.BoolTrue(), + }, + }, + "notify_duration": schema.Int64Attribute{ + Optional: true, + Description: "Time to send all max-aged grace LSAs (seconds).", + Validators: []validator.Int64{ + int64validator.Between(1, 3600), + }, + }, + "restart_duration": schema.Int64Attribute{ + Optional: true, + Description: "Time for all neighbors to become full (seconds).", + Validators: []validator.Int64{ + int64validator.Between(1, 3600), + }, + }, + }, + PlanModifiers: []planmodifier.Object{ + tfplanmodifier.BlockRemoveNull(), + }, + }, + "overload": schema.SingleNestedBlock{ + Description: "Set the overload mode (repel transit traffic).", + Attributes: map[string]schema.Attribute{ + "allow_route_leaking": schema.BoolAttribute{ + Optional: true, + Description: "Allow routes to be leaked when overload is configured.", + Validators: []validator.Bool{ + tfvalidator.BoolTrue(), + }, + }, + "as_external": schema.BoolAttribute{ + Optional: true, + Description: "Advertise As External with maximum usable metric.", + Validators: []validator.Bool{ + tfvalidator.BoolTrue(), + }, + }, + "stub_network": schema.BoolAttribute{ + Optional: true, + Description: "Advertise Stub Network with maximum metric.", + Validators: []validator.Bool{ + tfvalidator.BoolTrue(), + }, + }, + "timeout": schema.Int64Attribute{ + Optional: true, + Description: "Time after which overload mode is reset (seconds).", + Validators: []validator.Int64{ + int64validator.Between(60, 1800), + }, + }, + }, + PlanModifiers: []planmodifier.Object{ + tfplanmodifier.BlockRemoveNull(), + }, + }, + "spf_options": schema.SingleNestedBlock{ + Description: "Declare `spf-options` configuration.", + Attributes: map[string]schema.Attribute{ + "delay": schema.Int64Attribute{ + Optional: true, + Description: "Time to wait before running an SPF (milliseconds).", + Validators: []validator.Int64{ + int64validator.Between(50, 8000), + }, + }, + "holddown": schema.Int64Attribute{ + Optional: true, + Description: "Time to hold down before running an SPF (milliseconds).", + Validators: []validator.Int64{ + int64validator.Between(2000, 20000), + }, + }, + "no_ignore_our_externals": schema.BoolAttribute{ + Optional: true, + Description: "Do not ignore self-generated external and NSSA LSAs.", + Validators: []validator.Bool{ + tfvalidator.BoolTrue(), + }, + }, + "rapid_runs": schema.Int64Attribute{ + Optional: true, + Description: "Number of maximum rapid SPF runs before holddown.", + Validators: []validator.Int64{ + int64validator.Between(1, 10), + }, + }, + }, + PlanModifiers: []planmodifier.Object{ + tfplanmodifier.BlockRemoveNull(), + }, + }, + }, + } +} + +type ospfData struct { + ID types.String `tfsdk:"id"` + Version types.String `tfsdk:"version"` + RoutingInstance types.String `tfsdk:"routing_instance"` + Disable types.Bool `tfsdk:"disable"` + DomainID types.String `tfsdk:"domain_id"` + Export []types.String `tfsdk:"export"` + ExternalPreference types.Int64 `tfsdk:"external_preference"` + ForwardingAddressToBroadcast types.Bool `tfsdk:"forwarding_address_to_broadcast"` + Import []types.String `tfsdk:"import"` + LabeledPreference types.Int64 `tfsdk:"labeled_preference"` + LsaRefreshInterval types.Int64 `tfsdk:"lsa_refresh_interval"` + NoNssaAbr types.Bool `tfsdk:"no_nssa_abr"` + NoRfc1583 types.Bool `tfsdk:"no_rfc1583"` + Preference types.Int64 `tfsdk:"preference"` + PrefixExportLimit types.Int64 `tfsdk:"prefix_export_limit"` + ReferenceBandwidth types.String `tfsdk:"reference_bandwidth"` + RibGroup types.String `tfsdk:"rib_group"` + ShamLink types.Bool `tfsdk:"sham_link"` + ShamLinkLocal types.String `tfsdk:"sham_link_local"` + DatabaseProtection *ospfBlockDatabaseProtection `tfsdk:"database_protection"` + GracefulRestart *ospfBlockGracefulRestart `tfsdk:"graceful_restart"` + Overload *ospfBlockOverload `tfsdk:"overload"` + SpfOptions *ospfBlockSpfOptions `tfsdk:"spf_options"` +} + +type ospfConfig struct { + ID types.String `tfsdk:"id"` + Version types.String `tfsdk:"version"` + RoutingInstance types.String `tfsdk:"routing_instance"` + Disable types.Bool `tfsdk:"disable"` + DomainID types.String `tfsdk:"domain_id"` + Export types.List `tfsdk:"export"` + ExternalPreference types.Int64 `tfsdk:"external_preference"` + ForwardingAddressToBroadcast types.Bool `tfsdk:"forwarding_address_to_broadcast"` + Import types.List `tfsdk:"import"` + LabeledPreference types.Int64 `tfsdk:"labeled_preference"` + LsaRefreshInterval types.Int64 `tfsdk:"lsa_refresh_interval"` + NoNssaAbr types.Bool `tfsdk:"no_nssa_abr"` + NoRfc1583 types.Bool `tfsdk:"no_rfc1583"` + Preference types.Int64 `tfsdk:"preference"` + PrefixExportLimit types.Int64 `tfsdk:"prefix_export_limit"` + ReferenceBandwidth types.String `tfsdk:"reference_bandwidth"` + RibGroup types.String `tfsdk:"rib_group"` + ShamLink types.Bool `tfsdk:"sham_link"` + ShamLinkLocal types.String `tfsdk:"sham_link_local"` + DatabaseProtection *ospfBlockDatabaseProtection `tfsdk:"database_protection"` + GracefulRestart *ospfBlockGracefulRestart `tfsdk:"graceful_restart"` + Overload *ospfBlockOverload `tfsdk:"overload"` + SpfOptions *ospfBlockSpfOptions `tfsdk:"spf_options"` +} + +type ospfBlockDatabaseProtection struct { + MaximumLsa types.Int64 `tfsdk:"maximum_lsa"` + IgnoreCount types.Int64 `tfsdk:"ignore_count"` + IgnoreTime types.Int64 `tfsdk:"ignore_time"` + ResetTime types.Int64 `tfsdk:"reset_time"` + WarningOnly types.Bool `tfsdk:"warning_only"` + WarningThreshold types.Int64 `tfsdk:"warning_threshold"` +} + +type ospfBlockGracefulRestart struct { + Disable types.Bool `tfsdk:"disable"` + HelperDisable types.Bool `tfsdk:"helper_disable"` + HelperDisableType types.String `tfsdk:"helper_disable_type"` + NoStrictLsaChecking types.Bool `tfsdk:"no_strict_lsa_checking"` + NotifyDuration types.Int64 `tfsdk:"notify_duration"` + RestartDuration types.Int64 `tfsdk:"restart_duration"` +} + +func (block *ospfBlockGracefulRestart) isEmpty() bool { + return tfdata.CheckBlockIsEmpty(block) +} + +type ospfBlockOverload struct { + AllowRouteLeaking types.Bool `tfsdk:"allow_route_leaking"` + ASExternal types.Bool `tfsdk:"as_external"` + StubNetwork types.Bool `tfsdk:"stub_network"` + Timeout types.Int64 `tfsdk:"timeout"` +} + +type ospfBlockSpfOptions struct { + Delay types.Int64 `tfsdk:"delay"` + Holddown types.Int64 `tfsdk:"holddown"` + NoIgnoreOurExternals types.Bool `tfsdk:"no_ignore_our_externals"` + RapidRuns types.Int64 `tfsdk:"rapid_runs"` +} + +func (block *ospfBlockSpfOptions) isEmpty() bool { + return tfdata.CheckBlockIsEmpty(block) +} + +func (rsc *ospf) ValidateConfig( + ctx context.Context, req resource.ValidateConfigRequest, resp *resource.ValidateConfigResponse, +) { + var config ospfConfig + resp.Diagnostics.Append(req.Config.Get(ctx, &config)...) + if resp.Diagnostics.HasError() { + return + } + + if !config.DomainID.IsNull() && !config.DomainID.IsUnknown() { + if config.RoutingInstance.IsNull() { + resp.Diagnostics.AddAttributeError( + path.Root("domain_id"), + tfdiag.MissingConfigErrSummary, + "routing_instance must be specified with domain_id", + ) + } else if !config.RoutingInstance.IsUnknown() && + config.RoutingInstance.ValueString() == junos.DefaultW { + resp.Diagnostics.AddAttributeError( + path.Root("domain_id"), + tfdiag.ConflictConfigErrSummary, + fmt.Sprintf("routing_instance cannot be %q with domain_id", junos.DefaultW), + ) + } + } + if !config.ShamLinkLocal.IsNull() && !config.ShamLinkLocal.IsUnknown() && + config.ShamLink.IsNull() { + resp.Diagnostics.AddAttributeError( + path.Root("sham_link_local"), + tfdiag.MissingConfigErrSummary, + "sham_link must be specified with sham_link_local", + ) + } + + if config.GracefulRestart != nil { + if config.GracefulRestart.isEmpty() { + resp.Diagnostics.AddAttributeError( + path.Root("graceful_restart"), + tfdiag.MissingConfigErrSummary, + "graceful_restart block is empty", + ) + } + if !config.GracefulRestart.HelperDisableType.IsNull() && !config.GracefulRestart.HelperDisableType.IsUnknown() && + config.GracefulRestart.HelperDisable.IsNull() { + resp.Diagnostics.AddAttributeError( + path.Root("graceful_restart").AtName("helper_disable_type"), + tfdiag.MissingConfigErrSummary, + "helper_disable must be specified with helper_disable_type"+ + " in graceful_restart block", + ) + } + if !config.GracefulRestart.NoStrictLsaChecking.IsNull() && !config.GracefulRestart.NoStrictLsaChecking.IsUnknown() && + !config.GracefulRestart.HelperDisable.IsNull() && !config.GracefulRestart.HelperDisable.IsUnknown() { + resp.Diagnostics.AddAttributeError( + path.Root("graceful_restart").AtName("no_strict_lsa_checking"), + tfdiag.ConflictConfigErrSummary, + "no_strict_lsa_checking and helper_disable cannot be configured together"+ + " in graceful_restart block", + ) + } + } + if config.SpfOptions != nil { + if config.SpfOptions.isEmpty() { + resp.Diagnostics.AddAttributeError( + path.Root("spf_options"), + tfdiag.MissingConfigErrSummary, + "spf_options block is empty", + ) + } + } +} + +func (rsc *ospf) Create( + ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse, +) { + var plan ospfData + resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) + if resp.Diagnostics.HasError() { + return + } + if plan.Version.ValueString() == "" { + resp.Diagnostics.AddAttributeError( + path.Root("version"), + "Empty Version", + defaultResourceCouldNotCreateWithEmptyMessage(rsc, "version"), + ) + + return + } + + defaultResourceCreate( + ctx, + rsc, + func(fnCtx context.Context, junSess *junos.Session) bool { + if v := plan.RoutingInstance.ValueString(); v != "" && v != junos.DefaultW { + instanceExists, err := checkRoutingInstanceExists(fnCtx, v, junSess) + if err != nil { + resp.Diagnostics.AddError(tfdiag.PreCheckErrSummary, err.Error()) + + return false + } + if !instanceExists { + resp.Diagnostics.AddAttributeError( + path.Root("routing_instance"), + tfdiag.MissingConfigErrSummary, + fmt.Sprintf("routing instance %q doesn't exist", v), + ) + + return false + } + } + + return true + }, + nil, + &plan, + resp, + ) +} + +func (rsc *ospf) Read( + ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse, +) { + var state, data ospfData + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + + junSess, err := rsc.junosClient().StartNewSession(ctx) + if err != nil { + resp.Diagnostics.AddError(tfdiag.StartSessErrSummary, err.Error()) + + return + } + defer junSess.Close() + + junos.MutexLock() + if v := state.RoutingInstance.ValueString(); v != "" && v != junos.DefaultW { + instanceExists, err := checkRoutingInstanceExists(ctx, v, junSess) + if err != nil { + junos.MutexUnlock() + resp.Diagnostics.AddError(tfdiag.ConfigReadErrSummary, err.Error()) + + return + } + if !instanceExists { + junos.MutexUnlock() + resp.State.RemoveResource(ctx) + + return + } + } + + err = data.read(ctx, state.Version.ValueString(), state.RoutingInstance.ValueString(), junSess) + junos.MutexUnlock() + if err != nil { + resp.Diagnostics.AddError(tfdiag.ConfigReadErrSummary, err.Error()) + + return + } + + if data.nullID() { + resp.State.RemoveResource(ctx) + + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} + +func (rsc *ospf) Update( + ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse, +) { + var plan, state ospfData + resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + + defaultResourceUpdate( + ctx, + rsc, + &state, + &plan, + resp, + ) +} + +func (rsc *ospf) Delete( + ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse, +) { + var state ospfData + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + + defaultResourceDelete( + ctx, + rsc, + &state, + resp, + ) +} + +func (rsc *ospf) ImportState( + ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse, +) { + junSess, err := rsc.junosClient().StartNewSession(ctx) + if err != nil { + resp.Diagnostics.AddError(tfdiag.StartSessErrSummary, err.Error()) + + return + } + defer junSess.Close() + + idList := strings.Split(req.ID, junos.IDSeparator) + if len(idList) < 2 { + resp.Diagnostics.AddError( + "Bad ID Format", + fmt.Sprintf("missing element(s) in id with separator %q", junos.IDSeparator), + ) + + return + } + if idList[0] != "v2" && idList[0] != "v3" { + resp.Diagnostics.AddError( + "Bad ID Format", + fmt.Sprintf("%q is not a valid version", idList[0]), + ) + + return + } + if idList[1] != junos.DefaultW { + instanceExists, err := checkRoutingInstanceExists(ctx, idList[1], junSess) + if err != nil { + resp.Diagnostics.AddError(tfdiag.ConfigReadErrSummary, err.Error()) + + return + } + if !instanceExists { + resp.Diagnostics.AddError( + tfdiag.NotFoundErrSummary, + fmt.Sprintf("routing instance %q doesn't exist", idList[1]), + ) + + return + } + } + + var data ospfData + if err := data.read(ctx, idList[0], idList[1], junSess); err != nil { + resp.Diagnostics.AddError(tfdiag.ConfigReadErrSummary, err.Error()) + + return + } + if data.nullID() { + resp.Diagnostics.AddError( + tfdiag.NotFoundErrSummary, + defaultResourceImportDontFindMessage(rsc, req.ID)+ + " (id must be _-_)", + ) + + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, data)...) +} + +func (rscData *ospfData) fillID() { + if v := rscData.RoutingInstance.ValueString(); v != "" { + rscData.ID = types.StringValue(rscData.Version.ValueString() + junos.IDSeparator + v) + } else { + rscData.ID = types.StringValue(rscData.Version.ValueString() + junos.IDSeparator + junos.DefaultW) + } +} + +func (rscData *ospfData) nullID() bool { + return rscData.ID.IsNull() +} + +func (rscData *ospfData) set( + _ context.Context, junSess *junos.Session, +) ( + path.Path, error, +) { + configSet := make([]string, 0) + setPrefix := junos.SetLS + + routingInstance := rscData.RoutingInstance.ValueString() + if routingInstance != "" && routingInstance != junos.DefaultW { + setPrefix = junos.SetRoutingInstances + routingInstance + " " + } + ospfVersion := junos.OspfV2 + if rscData.Version.ValueString() == "v3" { + ospfVersion = junos.OspfV3 + } + setPrefix += "protocols " + ospfVersion + " " + + if rscData.Disable.ValueBool() { + configSet = append(configSet, setPrefix+"disable") + } + if v := rscData.DomainID.ValueString(); v != "" { + if routingInstance == "" || routingInstance == junos.DefaultW { + return path.Root("domain_id"), + fmt.Errorf("domain_id cannot be configured when routing_instance = %q", junos.DefaultW) + } + configSet = append(configSet, setPrefix+"domain-id \""+v+"\"") + } + for _, v := range rscData.Export { + configSet = append(configSet, setPrefix+"export \""+v.ValueString()+"\"") + } + if !rscData.ExternalPreference.IsNull() { + configSet = append(configSet, setPrefix+"external-preference "+ + utils.ConvI64toa(rscData.ExternalPreference.ValueInt64())) + } + if rscData.ForwardingAddressToBroadcast.ValueBool() { + configSet = append(configSet, setPrefix+"forwarding-address-to-broadcast") + } + for _, v := range rscData.Import { + configSet = append(configSet, setPrefix+"import \""+v.ValueString()+"\"") + } + if !rscData.LabeledPreference.IsNull() { + configSet = append(configSet, setPrefix+"labeled-preference "+ + utils.ConvI64toa(rscData.LabeledPreference.ValueInt64())) + } + if !rscData.LsaRefreshInterval.IsNull() { + configSet = append(configSet, setPrefix+"lsa-refresh-interval "+ + utils.ConvI64toa(rscData.LsaRefreshInterval.ValueInt64())) + } + if rscData.NoNssaAbr.ValueBool() { + configSet = append(configSet, setPrefix+"no-nssa-abr") + } + if rscData.NoRfc1583.ValueBool() { + configSet = append(configSet, setPrefix+"no-rfc-1583") + } + if !rscData.Preference.IsNull() { + configSet = append(configSet, setPrefix+"preference "+ + utils.ConvI64toa(rscData.Preference.ValueInt64())) + } + if !rscData.PrefixExportLimit.IsNull() { + configSet = append(configSet, setPrefix+"prefix-export-limit "+ + utils.ConvI64toa(rscData.PrefixExportLimit.ValueInt64())) + } + if v := rscData.ReferenceBandwidth.ValueString(); v != "" { + configSet = append(configSet, setPrefix+"reference-bandwidth "+v) + } + if v := rscData.RibGroup.ValueString(); v != "" { + configSet = append(configSet, setPrefix+"rib-group \""+v+"\"") + } + if rscData.ShamLink.ValueBool() { + configSet = append(configSet, setPrefix+"sham-link") + if v := rscData.ShamLinkLocal.ValueString(); v != "" { + configSet = append(configSet, setPrefix+"sham-link local "+v) + } + } else if rscData.ShamLinkLocal.ValueString() != "" { + return path.Root("sham_link_local"), + errors.New("sham_link must be specified with sham_link_local") + } + + if rscData.DatabaseProtection != nil { + configSet = append(configSet, rscData.DatabaseProtection.configSet(setPrefix)...) + } + if rscData.GracefulRestart != nil { + if rscData.GracefulRestart.isEmpty() { + return path.Root("graceful_restart").AtName("*"), + errors.New("graceful_restart block is empty") + } + + blockSet, pathErr, err := rscData.GracefulRestart.configSet(setPrefix, path.Root("graceful_restart")) + if err != nil { + return pathErr, err + } + configSet = append(configSet, blockSet...) + } + if rscData.Overload != nil { + configSet = append(configSet, rscData.Overload.configSet(setPrefix)...) + } + if rscData.SpfOptions != nil { + if rscData.SpfOptions.isEmpty() { + return path.Root("spf_options").AtName("*"), + errors.New("spf_options block is empty") + } + + configSet = append(configSet, rscData.SpfOptions.configSet(setPrefix)...) + } + + return path.Empty(), junSess.ConfigSet(configSet) +} + +func (block *ospfBlockDatabaseProtection) configSet(setPrefix string) []string { + setPrefix += "database-protection " + configSet := []string{ + setPrefix + "maximum-lsa " + utils.ConvI64toa(block.MaximumLsa.ValueInt64()), + } + + if !block.IgnoreCount.IsNull() { + configSet = append(configSet, setPrefix+"ignore-count "+ + utils.ConvI64toa(block.IgnoreCount.ValueInt64())) + } + if !block.IgnoreTime.IsNull() { + configSet = append(configSet, setPrefix+"ignore-time "+ + utils.ConvI64toa(block.IgnoreTime.ValueInt64())) + } + if !block.ResetTime.IsNull() { + configSet = append(configSet, setPrefix+"reset-time "+ + utils.ConvI64toa(block.ResetTime.ValueInt64())) + } + if block.WarningOnly.ValueBool() { + configSet = append(configSet, setPrefix+"warning-only") + } + if !block.WarningThreshold.IsNull() { + configSet = append(configSet, setPrefix+"warning-threshold "+ + utils.ConvI64toa(block.WarningThreshold.ValueInt64())) + } + + return configSet +} + +func (block *ospfBlockGracefulRestart) configSet( + setPrefix string, pathRoot path.Path, +) ( + []string, // configSet + path.Path, // pathErr + error, // error +) { + configSet := make([]string, 0) + setPrefix += "graceful-restart " + + if block.Disable.ValueBool() { + configSet = append(configSet, setPrefix+"disable") + } + if block.HelperDisable.ValueBool() { + configSet = append(configSet, setPrefix+"helper-disable") + if v := block.HelperDisableType.ValueString(); v != "" { + configSet = append(configSet, setPrefix+"helper-disable "+v) + } + } else if block.HelperDisableType.ValueString() != "" { + return configSet, + pathRoot.AtName("helper_disable_type"), + errors.New("helper_disable must be specified with helper_disable_type" + + " in graceful_restart block") + } + if block.NoStrictLsaChecking.ValueBool() { + configSet = append(configSet, setPrefix+"no-strict-lsa-checking") + } + if !block.NotifyDuration.IsNull() { + configSet = append(configSet, setPrefix+"notify-duration "+ + utils.ConvI64toa(block.NotifyDuration.ValueInt64())) + } + if !block.RestartDuration.IsNull() { + configSet = append(configSet, setPrefix+"restart-duration "+ + utils.ConvI64toa(block.RestartDuration.ValueInt64())) + } + + return configSet, path.Empty(), nil +} + +func (block *ospfBlockOverload) configSet(setPrefix string) []string { + setPrefix += "overload " + configSet := []string{ + setPrefix, + } + + if block.AllowRouteLeaking.ValueBool() { + configSet = append(configSet, setPrefix+"allow-route-leaking") + } + if block.ASExternal.ValueBool() { + configSet = append(configSet, setPrefix+"as-external") + } + if block.StubNetwork.ValueBool() { + configSet = append(configSet, setPrefix+"stub-network") + } + if !block.Timeout.IsNull() { + configSet = append(configSet, setPrefix+"timeout "+ + utils.ConvI64toa(block.Timeout.ValueInt64())) + } + + return configSet +} + +func (block *ospfBlockSpfOptions) configSet(setPrefix string) []string { + configSet := make([]string, 0, 1) + setPrefix += "spf-options " + + if !block.Delay.IsNull() { + configSet = append(configSet, setPrefix+"delay "+ + utils.ConvI64toa(block.Delay.ValueInt64())) + } + if !block.Holddown.IsNull() { + configSet = append(configSet, setPrefix+"holddown "+ + utils.ConvI64toa(block.Holddown.ValueInt64())) + } + if block.NoIgnoreOurExternals.ValueBool() { + configSet = append(configSet, setPrefix+"no-ignore-our-externals") + } + if !block.RapidRuns.IsNull() { + configSet = append(configSet, setPrefix+"rapid-runs "+ + utils.ConvI64toa(block.RapidRuns.ValueInt64())) + } + + return configSet +} + +func (rscData *ospfData) read( + _ context.Context, version, routingInstance string, junSess *junos.Session, +) ( + err error, +) { + var showConfig string + ospfVersion := junos.OspfV2 + if version == "v3" { + ospfVersion = junos.OspfV3 + } + if routingInstance == junos.DefaultW { + showConfig, err = junSess.Command(junos.CmdShowConfig + + "protocols " + ospfVersion + junos.PipeDisplaySetRelative) + if err != nil { + return err + } + } else { + showConfig, err = junSess.Command(junos.CmdShowConfig + junos.RoutingInstancesWS + routingInstance + " " + + "protocols " + ospfVersion + junos.PipeDisplaySetRelative) + if err != nil { + return err + } + } + + rscData.Version = types.StringValue(version) + rscData.RoutingInstance = types.StringValue(routingInstance) + rscData.fillID() + if showConfig != junos.EmptyW { + for _, item := range strings.Split(showConfig, "\n") { + if strings.Contains(item, junos.XMLStartTagConfigOut) { + continue + } + if strings.Contains(item, junos.XMLEndTagConfigOut) { + break + } + itemTrim := strings.TrimPrefix(item, junos.SetLS) + switch { + case itemTrim == "disable": + rscData.Disable = types.BoolValue(true) + case balt.CutPrefixInString(&itemTrim, "domain-id "): + rscData.DomainID = types.StringValue(strings.Trim(itemTrim, "\"")) + case balt.CutPrefixInString(&itemTrim, "export "): + rscData.Export = append(rscData.Export, types.StringValue(strings.Trim(itemTrim, "\""))) + case balt.CutPrefixInString(&itemTrim, "external-preference "): + rscData.ExternalPreference, err = tfdata.ConvAtoi64Value(itemTrim) + if err != nil { + return err + } + case itemTrim == "forwarding-address-to-broadcast": + rscData.ForwardingAddressToBroadcast = types.BoolValue(true) + case balt.CutPrefixInString(&itemTrim, "import "): + rscData.Import = append(rscData.Import, types.StringValue(strings.Trim(itemTrim, "\""))) + case balt.CutPrefixInString(&itemTrim, "labeled-preference "): + rscData.LabeledPreference, err = tfdata.ConvAtoi64Value(itemTrim) + if err != nil { + return err + } + case balt.CutPrefixInString(&itemTrim, "lsa-refresh-interval "): + rscData.LsaRefreshInterval, err = tfdata.ConvAtoi64Value(itemTrim) + if err != nil { + return err + } + case itemTrim == "no-nssa-abr": + rscData.NoNssaAbr = types.BoolValue(true) + case itemTrim == "no-rfc-1583": + rscData.NoRfc1583 = types.BoolValue(true) + case balt.CutPrefixInString(&itemTrim, "preference "): + rscData.Preference, err = tfdata.ConvAtoi64Value(itemTrim) + if err != nil { + return err + } + case balt.CutPrefixInString(&itemTrim, "prefix-export-limit "): + rscData.PrefixExportLimit, err = tfdata.ConvAtoi64Value(itemTrim) + if err != nil { + return err + } + case balt.CutPrefixInString(&itemTrim, "reference-bandwidth "): + rscData.ReferenceBandwidth = types.StringValue(itemTrim) + case balt.CutPrefixInString(&itemTrim, "rib-group "): + rscData.RibGroup = types.StringValue(strings.Trim(itemTrim, "\"")) + case balt.CutPrefixInString(&itemTrim, "sham-link"): + rscData.ShamLink = types.BoolValue(true) + if balt.CutPrefixInString(&itemTrim, " local ") { + rscData.ShamLinkLocal = types.StringValue(itemTrim) + } + case balt.CutPrefixInString(&itemTrim, "database-protection "): + if rscData.DatabaseProtection == nil { + rscData.DatabaseProtection = &ospfBlockDatabaseProtection{} + } + + if err := rscData.DatabaseProtection.read(itemTrim); err != nil { + return err + } + case balt.CutPrefixInString(&itemTrim, "graceful-restart "): + if rscData.GracefulRestart == nil { + rscData.GracefulRestart = &ospfBlockGracefulRestart{} + } + + if err := rscData.GracefulRestart.read(itemTrim); err != nil { + return err + } + case balt.CutPrefixInString(&itemTrim, "overload"): + if rscData.Overload == nil { + rscData.Overload = &ospfBlockOverload{} + } + + if balt.CutPrefixInString(&itemTrim, " ") { + if err := rscData.Overload.read(itemTrim); err != nil { + return err + } + } + case balt.CutPrefixInString(&itemTrim, "spf-options "): + if rscData.SpfOptions == nil { + rscData.SpfOptions = &ospfBlockSpfOptions{} + } + + if err := rscData.SpfOptions.read(itemTrim); err != nil { + return err + } + } + } + } + + return nil +} + +func (block *ospfBlockDatabaseProtection) read(itemTrim string) (err error) { + switch { + case balt.CutPrefixInString(&itemTrim, "ignore-count "): + block.IgnoreCount, err = tfdata.ConvAtoi64Value(itemTrim) + if err != nil { + return err + } + case balt.CutPrefixInString(&itemTrim, "ignore-time "): + block.IgnoreTime, err = tfdata.ConvAtoi64Value(itemTrim) + if err != nil { + return err + } + case balt.CutPrefixInString(&itemTrim, "maximum-lsa "): + block.MaximumLsa, err = tfdata.ConvAtoi64Value(itemTrim) + if err != nil { + return err + } + case balt.CutPrefixInString(&itemTrim, "reset-time "): + block.ResetTime, err = tfdata.ConvAtoi64Value(itemTrim) + if err != nil { + return err + } + case itemTrim == "warning-only": + block.WarningOnly = types.BoolValue(true) + case balt.CutPrefixInString(&itemTrim, "warning-threshold "): + block.WarningThreshold, err = tfdata.ConvAtoi64Value(itemTrim) + if err != nil { + return err + } + } + + return nil +} + +func (block *ospfBlockGracefulRestart) read(itemTrim string) (err error) { + switch { + case itemTrim == "disable": + block.Disable = types.BoolValue(true) + case balt.CutPrefixInString(&itemTrim, "helper-disable"): + block.HelperDisable = types.BoolValue(true) + if balt.CutPrefixInString(&itemTrim, " ") { + block.HelperDisableType = types.StringValue(itemTrim) + } + case itemTrim == "no-strict-lsa-checking": + block.NoStrictLsaChecking = types.BoolValue(true) + case balt.CutPrefixInString(&itemTrim, "notify-duration "): + block.NotifyDuration, err = tfdata.ConvAtoi64Value(itemTrim) + if err != nil { + return err + } + case balt.CutPrefixInString(&itemTrim, "restart-duration "): + block.RestartDuration, err = tfdata.ConvAtoi64Value(itemTrim) + if err != nil { + return err + } + } + + return nil +} + +func (block *ospfBlockOverload) read(itemTrim string) (err error) { + switch { + case itemTrim == "allow-route-leaking": + block.AllowRouteLeaking = types.BoolValue(true) + case itemTrim == "as-external": + block.ASExternal = types.BoolValue(true) + case itemTrim == "stub-network": + block.StubNetwork = types.BoolValue(true) + case balt.CutPrefixInString(&itemTrim, "timeout "): + block.Timeout, err = tfdata.ConvAtoi64Value(itemTrim) + if err != nil { + return err + } + } + + return nil +} + +func (block *ospfBlockSpfOptions) read(itemTrim string) (err error) { + switch { + case balt.CutPrefixInString(&itemTrim, "delay "): + block.Delay, err = tfdata.ConvAtoi64Value(itemTrim) + if err != nil { + return err + } + case balt.CutPrefixInString(&itemTrim, "holddown "): + block.Holddown, err = tfdata.ConvAtoi64Value(itemTrim) + if err != nil { + return err + } + case itemTrim == "no-ignore-our-externals": + block.NoIgnoreOurExternals = types.BoolValue(true) + case balt.CutPrefixInString(&itemTrim, "rapid-runs "): + block.RapidRuns, err = tfdata.ConvAtoi64Value(itemTrim) + if err != nil { + return err + } + } + + return nil +} + +func (rscData *ospfData) del( + _ context.Context, junSess *junos.Session, +) error { + ospfVersion := junos.OspfV2 + if rscData.Version.ValueString() == "v3" { + ospfVersion = junos.OspfV3 + } + delPrefix := junos.DeleteLS + if v := rscData.RoutingInstance.ValueString(); v != junos.DefaultW { + delPrefix = junos.DelRoutingInstances + v + " " + } + delPrefix += "protocols " + ospfVersion + " " + + listLinesToDelete := []string{ + "database-protection", + "disable", + "domain-id", + "export", + "external-preference", + "forwarding-address-to-broadcast", + "graceful-restart", + "import", + "labeled-preference", + "lsa-refresh-interval", + "no-nssa-abr", + "no-rfc-1583", + "overload", + "preference", + "prefix-export-limit", + "reference-bandwidth", + "rib-group", + "sham-link", + "spf-options", + } + configSet := make([]string, len(listLinesToDelete)) + for k, line := range listLinesToDelete { + configSet[k] = delPrefix + line + } + + return junSess.ConfigSet(configSet) +} diff --git a/internal/providerfwk/resource_ospf_test.go b/internal/providerfwk/resource_ospf_test.go new file mode 100644 index 00000000..479ed572 --- /dev/null +++ b/internal/providerfwk/resource_ospf_test.go @@ -0,0 +1,37 @@ +package providerfwk_test + +import ( + "os" + "testing" + + "github.com/hashicorp/terraform-plugin-testing/config" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" +) + +func TestAccResourceOspf_basic(t *testing.T) { + if os.Getenv("TESTACC_SWITCH") == "" { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProtoV5ProviderFactories: testAccProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + ConfigDirectory: config.TestStepDirectory(), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("junos_ospf.testacc_ospf", + "import.#", "1"), + resource.TestCheckResourceAttr("junos_ospf.testacc_ospf", + "export.#", "1"), + ), + }, + { + ResourceName: "junos_ospf.testacc_ospf", + ImportState: true, + ImportStateVerify: true, + }, + { + ConfigDirectory: config.TestStepDirectory(), + }, + }, + }) + } +} diff --git a/internal/providersdk/resource_ospf_test.go b/internal/providerfwk/testdata/TestAccResourceOspf_basic/1/main.tf similarity index 50% rename from internal/providersdk/resource_ospf_test.go rename to internal/providerfwk/testdata/TestAccResourceOspf_basic/1/main.tf index d291df0f..c4a81370 100644 --- a/internal/providersdk/resource_ospf_test.go +++ b/internal/providerfwk/testdata/TestAccResourceOspf_basic/1/main.tf @@ -1,42 +1,3 @@ -package providersdk_test - -import ( - "os" - "testing" - - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" -) - -func TestAccResourceOspf_basic(t *testing.T) { - if os.Getenv("TESTACC_SWITCH") == "" { - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - ProtoV5ProviderFactories: testAccProtoV5ProviderFactories, - Steps: []resource.TestStep{ - { - Config: testAccResourceOspfConfigCreate(), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("junos_ospf.testacc_ospf", - "import.#", "1"), - resource.TestCheckResourceAttr("junos_ospf.testacc_ospf", - "export.#", "1"), - ), - }, - { - ResourceName: "junos_ospf.testacc_ospf", - ImportState: true, - ImportStateVerify: true, - }, - { - Config: testAccResourceOspfConfigUpdate(), - }, - }, - }) - } -} - -func testAccResourceOspfConfigCreate() string { - return ` resource "junos_policyoptions_policy_statement" "testacc_ospf" { name = "testacc_ospf" then { @@ -105,48 +66,3 @@ resource "junos_ospf" "testacc_ospf_v3" { export = [junos_policyoptions_policy_statement.testacc_ospf.name] import = [junos_policyoptions_policy_statement.testacc_ospf.name] } -` -} - -func testAccResourceOspfConfigUpdate() string { - return ` -resource "junos_policyoptions_policy_statement" "testacc_ospf" { - name = "testacc_ospf" - then { - action = "accept" - } -} -resource "junos_ospf" "testacc_ospf" { - database_protection { - maximum_lsa = 10 - } - disable = true - export = [junos_policyoptions_policy_statement.testacc_ospf.name] - external_preference = 3600 - forwarding_address_to_broadcast = true - graceful_restart { - disable = true - no_strict_lsa_checking = true - notify_duration = 900 - restart_duration = 960 - } - import = [junos_policyoptions_policy_statement.testacc_ospf.name] - labeled_preference = 5000 - lsa_refresh_interval = 40 - no_nssa_abr = true - no_rfc1583 = true - overload {} - preference = 1000 - prefix_export_limit = 2000 - reference_bandwidth = "10k" - sham_link = true - sham_link_local = "192.0.2.3" - spf_options { - delay = 1250 - holddown = 10500 - no_ignore_our_externals = true - rapid_runs = 5 - } -} -` -} diff --git a/internal/providerfwk/testdata/TestAccResourceOspf_basic/3/main.tf b/internal/providerfwk/testdata/TestAccResourceOspf_basic/3/main.tf new file mode 100644 index 00000000..c9ca42dd --- /dev/null +++ b/internal/providerfwk/testdata/TestAccResourceOspf_basic/3/main.tf @@ -0,0 +1,38 @@ +resource "junos_policyoptions_policy_statement" "testacc_ospf" { + name = "testacc_ospf" + then { + action = "accept" + } +} +resource "junos_ospf" "testacc_ospf" { + database_protection { + maximum_lsa = 10 + } + disable = true + export = [junos_policyoptions_policy_statement.testacc_ospf.name] + external_preference = 3600 + forwarding_address_to_broadcast = true + graceful_restart { + disable = true + no_strict_lsa_checking = true + notify_duration = 900 + restart_duration = 960 + } + import = [junos_policyoptions_policy_statement.testacc_ospf.name] + labeled_preference = 5000 + lsa_refresh_interval = 40 + no_nssa_abr = true + no_rfc1583 = true + overload {} + preference = 1000 + prefix_export_limit = 2000 + reference_bandwidth = "10k" + sham_link = true + sham_link_local = "192.0.2.3" + spf_options { + delay = 1250 + holddown = 10500 + no_ignore_our_externals = true + rapid_runs = 5 + } +} diff --git a/internal/providerfwk/testdata/TestAccUpgradeStateResourceOspf_V0toV1_basic/1/main.tf b/internal/providerfwk/testdata/TestAccUpgradeStateResourceOspf_V0toV1_basic/1/main.tf new file mode 100644 index 00000000..c9ca42dd --- /dev/null +++ b/internal/providerfwk/testdata/TestAccUpgradeStateResourceOspf_V0toV1_basic/1/main.tf @@ -0,0 +1,38 @@ +resource "junos_policyoptions_policy_statement" "testacc_ospf" { + name = "testacc_ospf" + then { + action = "accept" + } +} +resource "junos_ospf" "testacc_ospf" { + database_protection { + maximum_lsa = 10 + } + disable = true + export = [junos_policyoptions_policy_statement.testacc_ospf.name] + external_preference = 3600 + forwarding_address_to_broadcast = true + graceful_restart { + disable = true + no_strict_lsa_checking = true + notify_duration = 900 + restart_duration = 960 + } + import = [junos_policyoptions_policy_statement.testacc_ospf.name] + labeled_preference = 5000 + lsa_refresh_interval = 40 + no_nssa_abr = true + no_rfc1583 = true + overload {} + preference = 1000 + prefix_export_limit = 2000 + reference_bandwidth = "10k" + sham_link = true + sham_link_local = "192.0.2.3" + spf_options { + delay = 1250 + holddown = 10500 + no_ignore_our_externals = true + rapid_runs = 5 + } +} diff --git a/internal/providerfwk/testdata/TestAccUpgradeStateResourceOspf_V0toV1_basic/1/provider.tf b/internal/providerfwk/testdata/TestAccUpgradeStateResourceOspf_V0toV1_basic/1/provider.tf new file mode 100644 index 00000000..713fa309 --- /dev/null +++ b/internal/providerfwk/testdata/TestAccUpgradeStateResourceOspf_V0toV1_basic/1/provider.tf @@ -0,0 +1,10 @@ +terraform { + required_providers { + junos = { + source = "registry.terraform.io/jeremmfr/junos" + version = "1.33.0" + } + } +} + +provider "junos" {} diff --git a/internal/providerfwk/testdata/TestAccUpgradeStateResourceOspf_V0toV1_basic/2/main.tf b/internal/providerfwk/testdata/TestAccUpgradeStateResourceOspf_V0toV1_basic/2/main.tf new file mode 120000 index 00000000..7a6c4026 --- /dev/null +++ b/internal/providerfwk/testdata/TestAccUpgradeStateResourceOspf_V0toV1_basic/2/main.tf @@ -0,0 +1 @@ +../1/main.tf \ No newline at end of file diff --git a/internal/providerfwk/upgradestate_ospf.go b/internal/providerfwk/upgradestate_ospf.go new file mode 100644 index 00000000..e5f19ffe --- /dev/null +++ b/internal/providerfwk/upgradestate_ospf.go @@ -0,0 +1,287 @@ +package providerfwk + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/types" +) + +func (rsc *ospf) UpgradeState(_ context.Context) map[int64]resource.StateUpgrader { + return map[int64]resource.StateUpgrader{ + 0: { + PriorSchema: &schema.Schema{ + Attributes: map[string]schema.Attribute{ + "id": schema.StringAttribute{ + Computed: true, + }, + "version": schema.StringAttribute{ + Optional: true, + Computed: true, + }, + "routing_instance": schema.StringAttribute{ + Optional: true, + Computed: true, + }, + "disable": schema.BoolAttribute{ + Optional: true, + }, + "domain_id": schema.StringAttribute{ + Optional: true, + }, + "export": schema.ListAttribute{ + ElementType: types.StringType, + Optional: true, + }, + "external_preference": schema.Int64Attribute{ + Optional: true, + }, + "forwarding_address_to_broadcast": schema.BoolAttribute{ + Optional: true, + }, + "import": schema.ListAttribute{ + ElementType: types.StringType, + Optional: true, + }, + "labeled_preference": schema.Int64Attribute{ + Optional: true, + }, + "lsa_refresh_interval": schema.Int64Attribute{ + Optional: true, + }, + "no_nssa_abr": schema.BoolAttribute{ + Optional: true, + }, + "no_rfc1583": schema.BoolAttribute{ + Optional: true, + }, + "preference": schema.Int64Attribute{ + Optional: true, + }, + "prefix_export_limit": schema.Int64Attribute{ + Optional: true, + }, + "reference_bandwidth": schema.StringAttribute{ + Optional: true, + }, + "rib_group": schema.StringAttribute{ + Optional: true, + }, + "sham_link": schema.BoolAttribute{ + Optional: true, + }, + "sham_link_local": schema.StringAttribute{ + Optional: true, + }, + }, + Blocks: map[string]schema.Block{ + "database_protection": schema.ListNestedBlock{ + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "maximum_lsa": schema.Int64Attribute{ + Required: true, + }, + "ignore_count": schema.Int64Attribute{ + Optional: true, + }, + "ignore_time": schema.Int64Attribute{ + Optional: true, + }, + "reset_time": schema.Int64Attribute{ + Optional: true, + }, + "warning_only": schema.BoolAttribute{ + Optional: true, + }, + "warning_threshold": schema.Int64Attribute{ + Optional: true, + }, + }, + }, + }, + "graceful_restart": schema.ListNestedBlock{ + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "disable": schema.BoolAttribute{ + Optional: true, + }, + "helper_disable": schema.BoolAttribute{ + Optional: true, + }, + "helper_disable_type": schema.StringAttribute{ + Optional: true, + }, + "no_strict_lsa_checking": schema.BoolAttribute{ + Optional: true, + }, + "notify_duration": schema.Int64Attribute{ + Optional: true, + }, + "restart_duration": schema.Int64Attribute{ + Optional: true, + }, + }, + }, + }, + "overload": schema.ListNestedBlock{ + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "allow_route_leaking": schema.BoolAttribute{ + Optional: true, + }, + "as_external": schema.BoolAttribute{ + Optional: true, + }, + "stub_network": schema.BoolAttribute{ + Optional: true, + }, + "timeout": schema.Int64Attribute{ + Optional: true, + }, + }, + }, + }, + "spf_options": schema.ListNestedBlock{ + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "delay": schema.Int64Attribute{ + Optional: true, + }, + "holddown": schema.Int64Attribute{ + Optional: true, + }, + "no_ignore_our_externals": schema.BoolAttribute{ + Optional: true, + }, + "rapid_runs": schema.Int64Attribute{ + Optional: true, + }, + }, + }, + }, + }, + }, + StateUpgrader: upgradeOspfV0toV1, + }, + } +} + +func upgradeOspfV0toV1( + ctx context.Context, req resource.UpgradeStateRequest, resp *resource.UpgradeStateResponse, +) { + type modelV0 struct { + ID types.String `tfsdk:"id"` + Version types.String `tfsdk:"version"` + RoutingInstance types.String `tfsdk:"routing_instance"` + Disable types.Bool `tfsdk:"disable"` + DomainID types.String `tfsdk:"domain_id"` + Export []types.String `tfsdk:"export"` + ExternalPreference types.Int64 `tfsdk:"external_preference"` + ForwardingAddressToBroadcast types.Bool `tfsdk:"forwarding_address_to_broadcast"` + Import []types.String `tfsdk:"import"` + LabeledPreference types.Int64 `tfsdk:"labeled_preference"` + LsaRefreshInterval types.Int64 `tfsdk:"lsa_refresh_interval"` + NoNssaAbr types.Bool `tfsdk:"no_nssa_abr"` + NoRfc1583 types.Bool `tfsdk:"no_rfc1583"` + Preference types.Int64 `tfsdk:"preference"` + PrefixExportLimit types.Int64 `tfsdk:"prefix_export_limit"` + ReferenceBandwidth types.String `tfsdk:"reference_bandwidth"` + RibGroup types.String `tfsdk:"rib_group"` + ShamLink types.Bool `tfsdk:"sham_link"` + ShamLinkLocal types.String `tfsdk:"sham_link_local"` + DatabaseProtection []struct { + MaximumLsa types.Int64 `tfsdk:"maximum_lsa"` + IgnoreCount types.Int64 `tfsdk:"ignore_count"` + IgnoreTime types.Int64 `tfsdk:"ignore_time"` + ResetTime types.Int64 `tfsdk:"reset_time"` + WarningOnly types.Bool `tfsdk:"warning_only"` + WarningThreshold types.Int64 `tfsdk:"warning_threshold"` + } `tfsdk:"database_protection"` + GracefulRestart []struct { + Disable types.Bool `tfsdk:"disable"` + HelperDisable types.Bool `tfsdk:"helper_disable"` + HelperDisableType types.String `tfsdk:"helper_disable_type"` + NoStrictLsaChecking types.Bool `tfsdk:"no_strict_lsa_checking"` + NotifyDuration types.Int64 `tfsdk:"notify_duration"` + RestartDuration types.Int64 `tfsdk:"restart_duration"` + } `tfsdk:"graceful_restart"` + Overload []struct { + AllowRouteLeaking types.Bool `tfsdk:"allow_route_leaking"` + ASExternal types.Bool `tfsdk:"as_external"` + StubNetwork types.Bool `tfsdk:"stub_network"` + Timeout types.Int64 `tfsdk:"timeout"` + } `tfsdk:"overload"` + SpfOptions []struct { + Delay types.Int64 `tfsdk:"delay"` + Holddown types.Int64 `tfsdk:"holddown"` + NoIgnoreOurExternals types.Bool `tfsdk:"no_ignore_our_externals"` + RapidRuns types.Int64 `tfsdk:"rapid_runs"` + } `tfsdk:"spf_options"` + } + + var dataV0 modelV0 + resp.Diagnostics.Append(req.State.Get(ctx, &dataV0)...) + if resp.Diagnostics.HasError() { + return + } + + var dataV1 ospfData + dataV1.ID = dataV0.ID + dataV1.Version = dataV0.Version + dataV1.RoutingInstance = dataV0.RoutingInstance + dataV1.Disable = dataV0.Disable + dataV1.DomainID = dataV0.DomainID + dataV1.Export = dataV0.Export + dataV1.ExternalPreference = dataV0.ExternalPreference + dataV1.ForwardingAddressToBroadcast = dataV0.ForwardingAddressToBroadcast + dataV1.Import = dataV0.Import + dataV1.LabeledPreference = dataV0.LabeledPreference + dataV1.LsaRefreshInterval = dataV0.LsaRefreshInterval + dataV1.NoNssaAbr = dataV0.NoNssaAbr + dataV1.NoRfc1583 = dataV0.NoRfc1583 + dataV1.Preference = dataV0.Preference + dataV1.PrefixExportLimit = dataV0.PrefixExportLimit + dataV1.ReferenceBandwidth = dataV0.ReferenceBandwidth + dataV1.RibGroup = dataV0.RibGroup + dataV1.ShamLink = dataV0.ShamLink + dataV1.ShamLinkLocal = dataV0.ShamLinkLocal + if len(dataV0.DatabaseProtection) > 0 { + dataV1.DatabaseProtection = &ospfBlockDatabaseProtection{ + MaximumLsa: dataV0.DatabaseProtection[0].MaximumLsa, + IgnoreCount: dataV0.DatabaseProtection[0].IgnoreCount, + IgnoreTime: dataV0.DatabaseProtection[0].IgnoreTime, + ResetTime: dataV0.DatabaseProtection[0].ResetTime, + WarningOnly: dataV0.DatabaseProtection[0].WarningOnly, + WarningThreshold: dataV0.DatabaseProtection[0].WarningThreshold, + } + } + if len(dataV0.GracefulRestart) > 0 { + dataV1.GracefulRestart = &ospfBlockGracefulRestart{ + Disable: dataV0.GracefulRestart[0].Disable, + HelperDisable: dataV0.GracefulRestart[0].HelperDisable, + HelperDisableType: dataV0.GracefulRestart[0].HelperDisableType, + NoStrictLsaChecking: dataV0.GracefulRestart[0].NoStrictLsaChecking, + NotifyDuration: dataV0.GracefulRestart[0].NotifyDuration, + RestartDuration: dataV0.GracefulRestart[0].RestartDuration, + } + } + if len(dataV0.Overload) > 0 { + dataV1.Overload = &ospfBlockOverload{ + AllowRouteLeaking: dataV0.Overload[0].AllowRouteLeaking, + ASExternal: dataV0.Overload[0].ASExternal, + StubNetwork: dataV0.Overload[0].StubNetwork, + Timeout: dataV0.Overload[0].Timeout, + } + } + if len(dataV0.SpfOptions) > 0 { + dataV1.SpfOptions = &ospfBlockSpfOptions{ + Delay: dataV0.SpfOptions[0].Delay, + Holddown: dataV0.SpfOptions[0].Holddown, + NoIgnoreOurExternals: dataV0.SpfOptions[0].NoIgnoreOurExternals, + RapidRuns: dataV0.SpfOptions[0].RapidRuns, + } + } + + resp.Diagnostics.Append(resp.State.Set(ctx, dataV1)...) +} diff --git a/internal/providerfwk/upgradestate_ospf_test.go b/internal/providerfwk/upgradestate_ospf_test.go new file mode 100644 index 00000000..04e4290b --- /dev/null +++ b/internal/providerfwk/upgradestate_ospf_test.go @@ -0,0 +1,31 @@ +package providerfwk_test + +import ( + "os" + "testing" + + "github.com/hashicorp/terraform-plugin-testing/config" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/plancheck" +) + +func TestAccUpgradeStateResourceOspf_V0toV1_basic(t *testing.T) { + if os.Getenv("TESTACC_SWITCH") == "" { + resource.Test(t, resource.TestCase{ + Steps: []resource.TestStep{ + { + ConfigDirectory: config.TestStepDirectory(), + }, + { + ProtoV5ProviderFactories: testAccProtoV5ProviderFactories, + ConfigDirectory: config.TestStepDirectory(), + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectEmptyPlan(), + }, + }, + }, + }, + }) + } +} diff --git a/internal/providersdk/provider.go b/internal/providersdk/provider.go index cdc52179..f0c25bb8 100644 --- a/internal/providersdk/provider.go +++ b/internal/providersdk/provider.go @@ -179,7 +179,6 @@ func Provider() *schema.Provider { "junos_lldp_interface": resourceLldpInterface(), "junos_lldpmed_interface": resourceLldpMedInterface(), "junos_null_commit_file": resourceNullCommitFile(), - "junos_ospf": resourceOspf(), "junos_rib_group": resourceRibGroup(), "junos_rip_group": resourceRipGroup(), "junos_rip_neighbor": resourceRipNeighbor(), diff --git a/internal/providersdk/resource_ospf.go b/internal/providersdk/resource_ospf.go deleted file mode 100644 index e54ef902..00000000 --- a/internal/providersdk/resource_ospf.go +++ /dev/null @@ -1,967 +0,0 @@ -package providersdk - -import ( - "context" - "errors" - "fmt" - "regexp" - "strconv" - "strings" - - "github.com/jeremmfr/terraform-provider-junos/internal/junos" - - "github.com/hashicorp/terraform-plugin-sdk/v2/diag" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" - balt "github.com/jeremmfr/go-utils/basicalter" -) - -type ospfOptions struct { - disable bool - forwardingAddressToBroadcast bool - noNssaAbr bool - noRfc1583 bool - shamLink bool - externalPreference int - labeledPreference int - lsaRefreshInterval int - preference int - prefixExportLimit int - domainID string - referenceBandwidth string - ribGroup string - routingInstance string - shamLinkLocal string - version string - export []string - importL []string - databaseProtection []map[string]interface{} - gracefulRestart []map[string]interface{} - spfOptions []map[string]interface{} - overload []map[string]interface{} -} - -func resourceOspf() *schema.Resource { - return &schema.Resource{ - CreateWithoutTimeout: resourceOspfCreate, - ReadWithoutTimeout: resourceOspfRead, - UpdateWithoutTimeout: resourceOspfUpdate, - DeleteWithoutTimeout: resourceOspfDelete, - Importer: &schema.ResourceImporter{ - StateContext: resourceOspfImport, - }, - Schema: map[string]*schema.Schema{ - "routing_instance": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - Default: junos.DefaultW, - ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, formatDefault), - }, - "version": { - Type: schema.TypeString, - Optional: true, - Default: "v2", - ForceNew: true, - ValidateFunc: validation.StringInSlice([]string{"v2", "v3"}, false), - }, - "database_protection": { - Type: schema.TypeList, - Optional: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "maximum_lsa": { - Type: schema.TypeInt, - Required: true, - ValidateFunc: validation.IntBetween(1, 1000000), - }, - "ignore_count": { - Type: schema.TypeInt, - Optional: true, - ValidateFunc: validation.IntBetween(1, 32), - }, - "ignore_time": { - Type: schema.TypeInt, - Optional: true, - ValidateFunc: validation.IntBetween(30, 3600), - }, - "reset_time": { - Type: schema.TypeInt, - Optional: true, - ValidateFunc: validation.IntBetween(60, 86400), - }, - "warning_only": { - Type: schema.TypeBool, - Optional: true, - }, - "warning_threshold": { - Type: schema.TypeInt, - Optional: true, - ValidateFunc: validation.IntBetween(30, 100), - }, - }, - }, - }, - "disable": { - Type: schema.TypeBool, - Optional: true, - }, - "domain_id": { // only if routing_instance != default - Type: schema.TypeString, - Optional: true, - }, - "export": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{ - Type: schema.TypeString, - ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, formatDefault), - }, - }, - "external_preference": { - Type: schema.TypeInt, - Optional: true, - ValidateFunc: validation.IntBetween(0, 4294967295), - Default: -1, - }, - "forwarding_address_to_broadcast": { - Type: schema.TypeBool, - Optional: true, - }, - "graceful_restart": { - Type: schema.TypeList, - Optional: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "disable": { - Type: schema.TypeBool, - Optional: true, - }, - "helper_disable": { - Type: schema.TypeBool, - Optional: true, - }, - "helper_disable_type": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: validation.StringInSlice([]string{"both", "restart-signaling", "standard"}, false), - RequiredWith: []string{"graceful_restart.0.helper_disable"}, - }, - "no_strict_lsa_checking": { - Type: schema.TypeBool, - Optional: true, - ConflictsWith: []string{"graceful_restart.0.helper_disable"}, - }, - "notify_duration": { - Type: schema.TypeInt, - Optional: true, - ValidateFunc: validation.IntBetween(1, 3600), - }, - "restart_duration": { - Type: schema.TypeInt, - Optional: true, - ValidateFunc: validation.IntBetween(1, 3600), - }, - }, - }, - }, - "import": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{ - Type: schema.TypeString, - ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, formatDefault), - }, - }, - "labeled_preference": { - Type: schema.TypeInt, - Optional: true, - ValidateFunc: validation.IntBetween(0, 4294967295), - Default: -1, - }, - "lsa_refresh_interval": { - Type: schema.TypeInt, - Optional: true, - ValidateFunc: validation.IntBetween(25, 50), - }, - "no_nssa_abr": { - Type: schema.TypeBool, - Optional: true, - }, - "no_rfc1583": { - Type: schema.TypeBool, - Optional: true, - }, - "overload": { - Type: schema.TypeList, - Optional: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "allow_route_leaking": { - Type: schema.TypeBool, - Optional: true, - }, - "as_external": { - Type: schema.TypeBool, - Optional: true, - }, - "stub_network": { - Type: schema.TypeBool, - Optional: true, - }, - "timeout": { - Type: schema.TypeInt, - Optional: true, - ValidateFunc: validation.IntBetween(60, 1800), - }, - }, - }, - }, - "preference": { - Type: schema.TypeInt, - Optional: true, - ValidateFunc: validation.IntBetween(0, 4294967295), - Default: -1, - }, - "prefix_export_limit": { - Type: schema.TypeInt, - Optional: true, - ValidateFunc: validation.IntBetween(0, 4294967295), - Default: -1, - }, - "reference_bandwidth": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: validation.StringMatch(regexp.MustCompile(`^(\d)+(m|k|g)?$`), - `must be a bandwidth ^(\d)+(m|k|g)?$`), - }, - "rib_group": { - Type: schema.TypeString, - Optional: true, - ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, formatDefault), - }, - "sham_link": { - Type: schema.TypeBool, - Optional: true, - }, - "sham_link_local": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: validation.IsIPAddress, - RequiredWith: []string{"sham_link"}, - }, - "spf_options": { - Type: schema.TypeList, - Optional: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "delay": { - Type: schema.TypeInt, - Optional: true, - ValidateFunc: validation.IntBetween(50, 8000), - }, - "holddown": { - Type: schema.TypeInt, - Optional: true, - ValidateFunc: validation.IntBetween(2000, 20000), - }, - "no_ignore_our_externals": { - Type: schema.TypeBool, - Optional: true, - }, - "rapid_runs": { - Type: schema.TypeInt, - Optional: true, - ValidateFunc: validation.IntBetween(1, 10), - }, - }, - }, - }, - }, - } -} - -func resourceOspfCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { - clt := m.(*junos.Client) - if clt.FakeCreateSetFile() { - junSess := clt.NewSessionWithoutNetconf(ctx) - if err := setOspf(d, junSess); err != nil { - return diag.FromErr(err) - } - d.SetId(d.Get("version").(string) + junos.IDSeparator + d.Get("routing_instance").(string)) - - return nil - } - junSess, err := clt.StartNewSession(ctx) - if err != nil { - return diag.FromErr(err) - } - defer junSess.Close() - if err := junSess.ConfigLock(ctx); err != nil { - return diag.FromErr(err) - } - var diagWarns diag.Diagnostics - if d.Get("routing_instance").(string) != junos.DefaultW { - instanceExists, err := checkRoutingInstanceExists(d.Get("routing_instance").(string), junSess) - if err != nil { - appendDiagWarns(&diagWarns, junSess.ConfigClear()) - - return append(diagWarns, diag.FromErr(err)...) - } - if !instanceExists { - appendDiagWarns(&diagWarns, junSess.ConfigClear()) - - return append(diagWarns, - diag.FromErr(fmt.Errorf("routing instance %v doesn't exist", d.Get("routing_instance").(string)))...) - } - } - if err := setOspf(d, junSess); err != nil { - appendDiagWarns(&diagWarns, junSess.ConfigClear()) - - return append(diagWarns, diag.FromErr(err)...) - } - warns, err := junSess.CommitConf(ctx, "create resource junos_ospf") - appendDiagWarns(&diagWarns, warns) - if err != nil { - appendDiagWarns(&diagWarns, junSess.ConfigClear()) - - return append(diagWarns, diag.FromErr(err)...) - } - d.SetId(d.Get("version").(string) + junos.IDSeparator + d.Get("routing_instance").(string)) - - return append(diagWarns, resourceOspfReadWJunSess(d, junSess)...) -} - -func resourceOspfRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { - clt := m.(*junos.Client) - junSess, err := clt.StartNewSession(ctx) - if err != nil { - return diag.FromErr(err) - } - defer junSess.Close() - - return resourceOspfReadWJunSess(d, junSess) -} - -func resourceOspfReadWJunSess(d *schema.ResourceData, junSess *junos.Session) diag.Diagnostics { - junos.MutexLock() - if d.Get("routing_instance").(string) != junos.DefaultW { - instanceExists, err := checkRoutingInstanceExists(d.Get("routing_instance").(string), junSess) - if err != nil { - junos.MutexUnlock() - - return diag.FromErr(err) - } - if !instanceExists { - junos.MutexUnlock() - d.SetId("") - - return nil - } - } - ospfOptions, err := readOspf(d.Get("version").(string), d.Get("routing_instance").(string), junSess) - junos.MutexUnlock() - if err != nil { - return diag.FromErr(err) - } - fillOspfData(d, ospfOptions) - - return nil -} - -func resourceOspfUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { - d.Partial(true) - clt := m.(*junos.Client) - if clt.FakeUpdateAlso() { - junSess := clt.NewSessionWithoutNetconf(ctx) - if err := delOspf(d, junSess); err != nil { - return diag.FromErr(err) - } - if err := setOspf(d, junSess); err != nil { - return diag.FromErr(err) - } - d.Partial(false) - - return nil - } - junSess, err := clt.StartNewSession(ctx) - if err != nil { - return diag.FromErr(err) - } - defer junSess.Close() - if err := junSess.ConfigLock(ctx); err != nil { - return diag.FromErr(err) - } - var diagWarns diag.Diagnostics - if err := delOspf(d, junSess); err != nil { - appendDiagWarns(&diagWarns, junSess.ConfigClear()) - - return append(diagWarns, diag.FromErr(err)...) - } - if err := setOspf(d, junSess); err != nil { - appendDiagWarns(&diagWarns, junSess.ConfigClear()) - - return append(diagWarns, diag.FromErr(err)...) - } - warns, err := junSess.CommitConf(ctx, "update resource junos_ospf") - appendDiagWarns(&diagWarns, warns) - if err != nil { - appendDiagWarns(&diagWarns, junSess.ConfigClear()) - - return append(diagWarns, diag.FromErr(err)...) - } - d.Partial(false) - - return append(diagWarns, resourceOspfReadWJunSess(d, junSess)...) -} - -func resourceOspfDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { - clt := m.(*junos.Client) - if clt.FakeDeleteAlso() { - junSess := clt.NewSessionWithoutNetconf(ctx) - if err := delOspf(d, junSess); err != nil { - return diag.FromErr(err) - } - - return nil - } - - junSess, err := clt.StartNewSession(ctx) - if err != nil { - return diag.FromErr(err) - } - defer junSess.Close() - if err := junSess.ConfigLock(ctx); err != nil { - return diag.FromErr(err) - } - var diagWarns diag.Diagnostics - if err := delOspf(d, junSess); err != nil { - appendDiagWarns(&diagWarns, junSess.ConfigClear()) - - return append(diagWarns, diag.FromErr(err)...) - } - warns, err := junSess.CommitConf(ctx, "delete resource junos_ospf") - appendDiagWarns(&diagWarns, warns) - if err != nil { - appendDiagWarns(&diagWarns, junSess.ConfigClear()) - - return append(diagWarns, diag.FromErr(err)...) - } - - return diagWarns -} - -func resourceOspfImport(ctx context.Context, d *schema.ResourceData, m interface{}, -) ([]*schema.ResourceData, error) { - clt := m.(*junos.Client) - junSess, err := clt.StartNewSession(ctx) - if err != nil { - return nil, err - } - defer junSess.Close() - result := make([]*schema.ResourceData, 1) - idSplit := strings.Split(d.Id(), junos.IDSeparator) - if len(idSplit) < 2 { - return nil, fmt.Errorf("missing element(s) in id with separator %v", junos.IDSeparator) - } - if idSplit[0] != "v2" && idSplit[0] != "v3" { - return nil, fmt.Errorf("%s is not a valid version", idSplit[0]) - } - if idSplit[1] != junos.DefaultW { - instanceExists, err := checkRoutingInstanceExists(idSplit[1], junSess) - if err != nil { - return nil, err - } - if !instanceExists { - return nil, fmt.Errorf("routing instance %v doesn't exist", idSplit[1]) - } - } - ospfOptions, err := readOspf(idSplit[0], idSplit[1], junSess) - if err != nil { - return nil, err - } - fillOspfData(d, ospfOptions) - result[0] = d - - return result, nil -} - -func setOspf(d *schema.ResourceData, junSess *junos.Session) error { - configSet := make([]string, 0) - setPrefix := junos.SetLS - if d.Get("routing_instance").(string) != junos.DefaultW { - setPrefix = junos.SetRoutingInstances + d.Get("routing_instance").(string) + " " - } - ospfVersion := junos.OspfV2 - if d.Get("version").(string) == "v3" { - ospfVersion = junos.OspfV3 - } - setPrefix += "protocols " + ospfVersion + " " - - for _, dbPro := range d.Get("database_protection").([]interface{}) { - dbProM := dbPro.(map[string]interface{}) - configSet = append(configSet, setPrefix+"database-protection maximum-lsa "+strconv.Itoa(dbProM["maximum_lsa"].(int))) - if v := dbProM["ignore_count"].(int); v != 0 { - configSet = append(configSet, setPrefix+"database-protection ignore-count "+strconv.Itoa(v)) - } - if v := dbProM["ignore_time"].(int); v != 0 { - configSet = append(configSet, setPrefix+"database-protection ignore-time "+strconv.Itoa(v)) - } - if v := dbProM["reset_time"].(int); v != 0 { - configSet = append(configSet, setPrefix+"database-protection reset-time "+strconv.Itoa(v)) - } - if dbProM["warning_only"].(bool) { - configSet = append(configSet, setPrefix+"database-protection warning-only") - } - if v := dbProM["warning_threshold"].(int); v != 0 { - configSet = append(configSet, setPrefix+"database-protection warning-threshold "+strconv.Itoa(v)) - } - } - if d.Get("disable").(bool) { - configSet = append(configSet, setPrefix+"disable") - } - if v := d.Get("domain_id").(string); v != "" { - if d.Get("routing_instance").(string) == junos.DefaultW { - return errors.New("domain_id not compatible with routing_instance=default") - } - configSet = append(configSet, setPrefix+"domain-id \""+v+"\"") - } - for _, v := range d.Get("export").([]interface{}) { - configSet = append(configSet, setPrefix+"export \""+v.(string)+"\"") - } - if v := d.Get("external_preference").(int); v != -1 { - configSet = append(configSet, setPrefix+"external-preference "+strconv.Itoa(v)) - } - if d.Get("forwarding_address_to_broadcast").(bool) { - configSet = append(configSet, setPrefix+"forwarding-address-to-broadcast") - } - for _, grR := range d.Get("graceful_restart").([]interface{}) { - if grR == nil { - return errors.New("graceful_restart block is empty") - } - grRM := grR.(map[string]interface{}) - if grRM["disable"].(bool) { - configSet = append(configSet, setPrefix+"graceful-restart disable") - } - if grRM["helper_disable"].(bool) { - configSet = append(configSet, setPrefix+"graceful-restart helper-disable") - if v := grRM["helper_disable_type"].(string); v != "" { - configSet = append(configSet, setPrefix+"graceful-restart helper-disable "+v) - } - } else if grRM["helper_disable_type"].(string) != "" { - return errors.New("helper_disable need to be true with helper_disable_type") - } - if grRM["no_strict_lsa_checking"].(bool) { - configSet = append(configSet, setPrefix+"graceful-restart no-strict-lsa-checking") - } - if v := grRM["notify_duration"].(int); v != 0 { - configSet = append(configSet, setPrefix+"graceful-restart notify-duration "+strconv.Itoa(v)) - } - if v := grRM["restart_duration"].(int); v != 0 { - configSet = append(configSet, setPrefix+"graceful-restart restart-duration "+strconv.Itoa(v)) - } - } - for _, v := range d.Get("import").([]interface{}) { - configSet = append(configSet, setPrefix+"import \""+v.(string)+"\"") - } - if v := d.Get("labeled_preference").(int); v != -1 { - configSet = append(configSet, setPrefix+"labeled-preference "+strconv.Itoa(v)) - } - if v := d.Get("lsa_refresh_interval").(int); v != 0 { - configSet = append(configSet, setPrefix+"lsa-refresh-interval "+strconv.Itoa(v)) - } - if d.Get("no_nssa_abr").(bool) { - configSet = append(configSet, setPrefix+"no-nssa-abr") - } - if d.Get("no_rfc1583").(bool) { - configSet = append(configSet, setPrefix+"no-rfc-1583") - } - for _, ovL := range d.Get("overload").([]interface{}) { - configSet = append(configSet, setPrefix+"overload") - if ovL != nil { - ovLM := ovL.(map[string]interface{}) - if ovLM["allow_route_leaking"].(bool) { - configSet = append(configSet, setPrefix+"overload allow-route-leaking") - } - if ovLM["as_external"].(bool) { - configSet = append(configSet, setPrefix+"overload as-external") - } - if ovLM["stub_network"].(bool) { - configSet = append(configSet, setPrefix+"overload stub-network") - } - if v := ovLM["timeout"].(int); v != 0 { - configSet = append(configSet, setPrefix+"overload timeout "+strconv.Itoa(v)) - } - } - } - if v := d.Get("preference").(int); v != -1 { - configSet = append(configSet, setPrefix+"preference "+strconv.Itoa(v)) - } - if v := d.Get("prefix_export_limit").(int); v != -1 { - configSet = append(configSet, setPrefix+"prefix-export-limit "+strconv.Itoa(v)) - } - if v := d.Get("reference_bandwidth").(string); v != "" { - configSet = append(configSet, setPrefix+"reference-bandwidth "+v) - } - if v := d.Get("rib_group").(string); v != "" { - configSet = append(configSet, setPrefix+"rib-group "+v) - } - if d.Get("sham_link").(bool) { - configSet = append(configSet, setPrefix+"sham-link") - if v := d.Get("sham_link_local").(string); v != "" { - configSet = append(configSet, setPrefix+"sham-link local "+v) - } - } else if d.Get("sham_link_local").(string) != "" { - return errors.New("sham_link need to be true with sham_link_local") - } - for _, spfO := range d.Get("spf_options").([]interface{}) { - if spfO == nil { - return errors.New("spf_options block is empty") - } - sfpOM := spfO.(map[string]interface{}) - if v := sfpOM["delay"].(int); v != 0 { - configSet = append(configSet, setPrefix+"spf-options delay "+strconv.Itoa(v)) - } - if v := sfpOM["holddown"].(int); v != 0 { - configSet = append(configSet, setPrefix+"spf-options holddown "+strconv.Itoa(v)) - } - if sfpOM["no_ignore_our_externals"].(bool) { - configSet = append(configSet, setPrefix+"spf-options no-ignore-our-externals") - } - if v := sfpOM["rapid_runs"].(int); v != 0 { - configSet = append(configSet, setPrefix+"spf-options rapid-runs "+strconv.Itoa(v)) - } - } - - return junSess.ConfigSet(configSet) -} - -func readOspf(version, routingInstance string, junSess *junos.Session, -) (confRead ospfOptions, err error) { - // default -1 - confRead.externalPreference = -1 - confRead.labeledPreference = -1 - confRead.preference = -1 - confRead.prefixExportLimit = -1 - var showConfig string - ospfVersion := junos.OspfV2 - if version == "v3" { - ospfVersion = junos.OspfV3 - } - if routingInstance == junos.DefaultW { - showConfig, err = junSess.Command(junos.CmdShowConfig + - "protocols " + ospfVersion + junos.PipeDisplaySetRelative) - if err != nil { - return confRead, err - } - } else { - showConfig, err = junSess.Command(junos.CmdShowConfig + junos.RoutingInstancesWS + routingInstance + " " + - "protocols " + ospfVersion + junos.PipeDisplaySetRelative) - if err != nil { - return confRead, err - } - } - - confRead.version = version - confRead.routingInstance = routingInstance - if showConfig != junos.EmptyW { - for _, item := range strings.Split(showConfig, "\n") { - if strings.Contains(item, junos.XMLStartTagConfigOut) { - continue - } - if strings.Contains(item, junos.XMLEndTagConfigOut) { - break - } - itemTrim := strings.TrimPrefix(item, junos.SetLS) - switch { - case balt.CutPrefixInString(&itemTrim, "database-protection"): - if len(confRead.databaseProtection) == 0 { - confRead.databaseProtection = append(confRead.databaseProtection, map[string]interface{}{ - "ignore_count": 0, - "ignore_time": 0, - "maximum_lsa": 0, - "reset_time": 0, - "warning_only": false, - "warning_threshold": 0, - }) - } - dbPro := confRead.databaseProtection[0] - switch { - case balt.CutPrefixInString(&itemTrim, " ignore-count "): - dbPro["ignore_count"], err = strconv.Atoi(itemTrim) - if err != nil { - return confRead, fmt.Errorf(failedConvAtoiError, itemTrim, err) - } - case balt.CutPrefixInString(&itemTrim, " ignore-time "): - dbPro["ignore_time"], err = strconv.Atoi(itemTrim) - if err != nil { - return confRead, fmt.Errorf(failedConvAtoiError, itemTrim, err) - } - case balt.CutPrefixInString(&itemTrim, " maximum-lsa "): - dbPro["maximum_lsa"], err = strconv.Atoi(itemTrim) - if err != nil { - return confRead, fmt.Errorf(failedConvAtoiError, itemTrim, err) - } - case balt.CutPrefixInString(&itemTrim, " reset-time "): - dbPro["reset_time"], err = strconv.Atoi(itemTrim) - if err != nil { - return confRead, fmt.Errorf(failedConvAtoiError, itemTrim, err) - } - case itemTrim == " warning-only": - dbPro["warning_only"] = true - case balt.CutPrefixInString(&itemTrim, " warning-threshold "): - dbPro["warning_threshold"], err = strconv.Atoi(itemTrim) - if err != nil { - return confRead, fmt.Errorf(failedConvAtoiError, itemTrim, err) - } - } - case itemTrim == "disable": - confRead.disable = true - case balt.CutPrefixInString(&itemTrim, "domain-id "): - confRead.domainID = strings.Trim(itemTrim, "\"") - case balt.CutPrefixInString(&itemTrim, "export "): - confRead.export = append(confRead.export, strings.Trim(itemTrim, "\"")) - case balt.CutPrefixInString(&itemTrim, "external-preference "): - confRead.externalPreference, err = strconv.Atoi(itemTrim) - if err != nil { - return confRead, fmt.Errorf(failedConvAtoiError, itemTrim, err) - } - case itemTrim == "forwarding-address-to-broadcast": - confRead.forwardingAddressToBroadcast = true - case balt.CutPrefixInString(&itemTrim, "graceful-restart "): - if len(confRead.gracefulRestart) == 0 { - confRead.gracefulRestart = append(confRead.gracefulRestart, map[string]interface{}{ - "disable": false, - "helper_disable": false, - "helper_disable_type": "", - "no_strict_lsa_checking": false, - "notify_duration": 0, - "restart_duration": 0, - }) - } - grR := confRead.gracefulRestart[0] - switch { - case itemTrim == "disable": - grR["disable"] = true - case balt.CutPrefixInString(&itemTrim, "helper-disable"): - grR["helper_disable"] = true - if balt.CutPrefixInString(&itemTrim, " ") { - grR["helper_disable_type"] = itemTrim - } - case itemTrim == "no-strict-lsa-checking": - grR["no_strict_lsa_checking"] = true - case balt.CutPrefixInString(&itemTrim, "notify-duration "): - grR["notify_duration"], err = strconv.Atoi(itemTrim) - if err != nil { - return confRead, fmt.Errorf(failedConvAtoiError, itemTrim, err) - } - case balt.CutPrefixInString(&itemTrim, "restart-duration "): - grR["restart_duration"], err = strconv.Atoi(itemTrim) - if err != nil { - return confRead, fmt.Errorf(failedConvAtoiError, itemTrim, err) - } - } - case balt.CutPrefixInString(&itemTrim, "import "): - confRead.importL = append(confRead.importL, strings.Trim(itemTrim, "\"")) - case balt.CutPrefixInString(&itemTrim, "labeled-preference "): - confRead.labeledPreference, err = strconv.Atoi(itemTrim) - if err != nil { - return confRead, fmt.Errorf(failedConvAtoiError, itemTrim, err) - } - case balt.CutPrefixInString(&itemTrim, "lsa-refresh-interval "): - confRead.lsaRefreshInterval, err = strconv.Atoi(itemTrim) - if err != nil { - return confRead, fmt.Errorf(failedConvAtoiError, itemTrim, err) - } - case itemTrim == "no-nssa-abr": - confRead.noNssaAbr = true - case itemTrim == "no-rfc-1583": - confRead.noRfc1583 = true - case balt.CutPrefixInString(&itemTrim, "overload"): - if len(confRead.overload) == 0 { - confRead.overload = append(confRead.overload, map[string]interface{}{ - "allow_route_leaking": false, - "as_external": false, - "stub_network": false, - "timeout": 0, - }) - } - switch { - case itemTrim == " allow-route-leaking": - confRead.overload[0]["allow_route_leaking"] = true - case itemTrim == " as-external": - confRead.overload[0]["as_external"] = true - case itemTrim == " stub-network": - confRead.overload[0]["stub_network"] = true - case balt.CutPrefixInString(&itemTrim, " timeout "): - confRead.overload[0]["timeout"], err = strconv.Atoi(itemTrim) - if err != nil { - return confRead, fmt.Errorf(failedConvAtoiError, itemTrim, err) - } - } - case balt.CutPrefixInString(&itemTrim, "preference "): - confRead.preference, err = strconv.Atoi(itemTrim) - if err != nil { - return confRead, fmt.Errorf(failedConvAtoiError, itemTrim, err) - } - case balt.CutPrefixInString(&itemTrim, "prefix-export-limit "): - confRead.prefixExportLimit, err = strconv.Atoi(itemTrim) - if err != nil { - return confRead, fmt.Errorf(failedConvAtoiError, itemTrim, err) - } - case balt.CutPrefixInString(&itemTrim, "reference-bandwidth "): - confRead.referenceBandwidth = itemTrim - case balt.CutPrefixInString(&itemTrim, "rib-group "): - confRead.ribGroup = itemTrim - case balt.CutPrefixInString(&itemTrim, "sham-link"): - confRead.shamLink = true - if balt.CutPrefixInString(&itemTrim, " local ") { - confRead.shamLinkLocal = itemTrim - } - case balt.CutPrefixInString(&itemTrim, "spf-options "): - if len(confRead.spfOptions) == 0 { - confRead.spfOptions = append(confRead.spfOptions, map[string]interface{}{ - "delay": 0, - "holddown": 0, - "no_ignore_our_externals": false, - "rapid_runs": 0, - }) - } - switch { - case balt.CutPrefixInString(&itemTrim, "delay "): - confRead.spfOptions[0]["delay"], err = strconv.Atoi(itemTrim) - if err != nil { - return confRead, fmt.Errorf(failedConvAtoiError, itemTrim, err) - } - case balt.CutPrefixInString(&itemTrim, "holddown "): - confRead.spfOptions[0]["holddown"], err = strconv.Atoi(itemTrim) - if err != nil { - return confRead, fmt.Errorf(failedConvAtoiError, itemTrim, err) - } - case itemTrim == "no-ignore-our-externals": - confRead.spfOptions[0]["no_ignore_our_externals"] = true - case balt.CutPrefixInString(&itemTrim, "rapid-runs "): - confRead.spfOptions[0]["rapid_runs"], err = strconv.Atoi(itemTrim) - if err != nil { - return confRead, fmt.Errorf(failedConvAtoiError, itemTrim, err) - } - } - } - } - } - - return confRead, nil -} - -func delOspf(d *schema.ResourceData, junSess *junos.Session) error { - ospfVersion := junos.OspfV2 - if d.Get("version").(string) == "v3" { - ospfVersion = junos.OspfV3 - } - delPrefix := junos.DeleteLS - if d.Get("routing_instance").(string) != junos.DefaultW { - delPrefix = junos.DelRoutingInstances + d.Get("routing_instance").(string) + " " - } - delPrefix += "protocols " + ospfVersion + " " - - listLinesToDelete := []string{ - "database-protection", - "disable", - "domain-id", - "export", - "external-preference", - "forwarding-address-to-broadcast", - "graceful-restart", - "import", - "labeled-preference", - "lsa-refresh-interval", - "no-nssa-abr", - "no-rfc-1583", - "overload", - "preference", - "prefix-export-limit", - "reference-bandwidth", - "rib-group", - "sham-link", - "spf-options", - } - configSet := make([]string, len(listLinesToDelete)) - for k, line := range listLinesToDelete { - configSet[k] = delPrefix + line - } - - return junSess.ConfigSet(configSet) -} - -func fillOspfData(d *schema.ResourceData, ospfOptions ospfOptions) { - if tfErr := d.Set("routing_instance", ospfOptions.routingInstance); tfErr != nil { - panic(tfErr) - } - if tfErr := d.Set("version", ospfOptions.version); tfErr != nil { - panic(tfErr) - } - if tfErr := d.Set("database_protection", ospfOptions.databaseProtection); tfErr != nil { - panic(tfErr) - } - if tfErr := d.Set("disable", ospfOptions.disable); tfErr != nil { - panic(tfErr) - } - if tfErr := d.Set("domain_id", ospfOptions.domainID); tfErr != nil { - panic(tfErr) - } - if tfErr := d.Set("export", ospfOptions.export); tfErr != nil { - panic(tfErr) - } - if tfErr := d.Set("external_preference", ospfOptions.externalPreference); tfErr != nil { - panic(tfErr) - } - if tfErr := d.Set("forwarding_address_to_broadcast", ospfOptions.forwardingAddressToBroadcast); tfErr != nil { - panic(tfErr) - } - if tfErr := d.Set("graceful_restart", ospfOptions.gracefulRestart); tfErr != nil { - panic(tfErr) - } - if tfErr := d.Set("import", ospfOptions.importL); tfErr != nil { - panic(tfErr) - } - if tfErr := d.Set("labeled_preference", ospfOptions.labeledPreference); tfErr != nil { - panic(tfErr) - } - if tfErr := d.Set("lsa_refresh_interval", ospfOptions.lsaRefreshInterval); tfErr != nil { - panic(tfErr) - } - if tfErr := d.Set("no_nssa_abr", ospfOptions.noNssaAbr); tfErr != nil { - panic(tfErr) - } - if tfErr := d.Set("no_rfc1583", ospfOptions.noRfc1583); tfErr != nil { - panic(tfErr) - } - if tfErr := d.Set("overload", ospfOptions.overload); tfErr != nil { - panic(tfErr) - } - if tfErr := d.Set("preference", ospfOptions.preference); tfErr != nil { - panic(tfErr) - } - if tfErr := d.Set("prefix_export_limit", ospfOptions.prefixExportLimit); tfErr != nil { - panic(tfErr) - } - if tfErr := d.Set("reference_bandwidth", ospfOptions.referenceBandwidth); tfErr != nil { - panic(tfErr) - } - if tfErr := d.Set("rib_group", ospfOptions.ribGroup); tfErr != nil { - panic(tfErr) - } - if tfErr := d.Set("sham_link", ospfOptions.shamLink); tfErr != nil { - panic(tfErr) - } - if tfErr := d.Set("sham_link_local", ospfOptions.shamLinkLocal); tfErr != nil { - panic(tfErr) - } - if tfErr := d.Set("spf_options", ospfOptions.spfOptions); tfErr != nil { - panic(tfErr) - } -} From 93a93f42fafbc07292a0573213dd4496a7bad7de Mon Sep 17 00:00:00 2001 From: Jeremy Muriel Date: Mon, 1 Apr 2024 20:37:16 +0200 Subject: [PATCH 09/25] providersdk: insert empty lines in ResourcesMap to avoid reformat when move resources to providerfwk --- internal/providersdk/provider.go | 67 ++++++++++++++++++++------------ 1 file changed, 42 insertions(+), 25 deletions(-) diff --git a/internal/providersdk/provider.go b/internal/providersdk/provider.go index f0c25bb8..c4694e0a 100644 --- a/internal/providersdk/provider.go +++ b/internal/providersdk/provider.go @@ -167,24 +167,36 @@ func Provider() *schema.Provider { }, }, ResourcesMap: map[string]*schema.Resource{ - "junos_access_address_assignment_pool": resourceAccessAddressAssignPool(), - "junos_chassis_cluster": resourceChassisCluster(), - "junos_chassis_redundancy": resourceChassisRedundancy(), - "junos_forwardingoptions_dhcprelay": resourceForwardingOptionsDhcpRelay(), - "junos_forwardingoptions_dhcprelay_group": resourceForwardingOptionsDhcpRelayGroup(), - "junos_forwardingoptions_dhcprelay_servergroup": resourceForwardingOptionsDhcpRelayServerGroup(), - "junos_group_dual_system": resourceGroupDualSystem(), - "junos_igmp_snooping_vlan": resourceIgmpSnoopingVlan(), - "junos_layer2_control": resourceLayer2Control(), - "junos_lldp_interface": resourceLldpInterface(), - "junos_lldpmed_interface": resourceLldpMedInterface(), - "junos_null_commit_file": resourceNullCommitFile(), - "junos_rib_group": resourceRibGroup(), - "junos_rip_group": resourceRipGroup(), - "junos_rip_neighbor": resourceRipNeighbor(), - "junos_routing_options": resourceRoutingOptions(), - "junos_rstp": resourceRstp(), - "junos_rstp_interface": resourceRstpInterface(), + "junos_access_address_assignment_pool": resourceAccessAddressAssignPool(), + + "junos_chassis_cluster": resourceChassisCluster(), + "junos_chassis_redundancy": resourceChassisRedundancy(), + + "junos_forwardingoptions_dhcprelay": resourceForwardingOptionsDhcpRelay(), + "junos_forwardingoptions_dhcprelay_group": resourceForwardingOptionsDhcpRelayGroup(), + "junos_forwardingoptions_dhcprelay_servergroup": resourceForwardingOptionsDhcpRelayServerGroup(), + + "junos_group_dual_system": resourceGroupDualSystem(), + + "junos_igmp_snooping_vlan": resourceIgmpSnoopingVlan(), + + "junos_layer2_control": resourceLayer2Control(), + + "junos_lldp_interface": resourceLldpInterface(), + "junos_lldpmed_interface": resourceLldpMedInterface(), + + "junos_null_commit_file": resourceNullCommitFile(), + + "junos_rib_group": resourceRibGroup(), + + "junos_rip_group": resourceRipGroup(), + "junos_rip_neighbor": resourceRipNeighbor(), + + "junos_routing_options": resourceRoutingOptions(), + + "junos_rstp": resourceRstp(), + "junos_rstp_interface": resourceRstpInterface(), + "junos_security_dynamic_address_feed_server": resourceSecurityDynamicAddressFeedServer(), "junos_security_dynamic_address_name": resourceSecurityDynamicAddressName(), "junos_security_idp_custom_attack": resourceSecurityIdpCustomAttack(), @@ -199,7 +211,9 @@ func Provider() *schema.Provider { "junos_security_utm_profile_web_filtering_juniper_enhanced": resourceSecurityUtmProfileWebFilteringEnhanced(), "junos_security_utm_profile_web_filtering_juniper_local": resourceSecurityUtmProfileWebFilteringLocal(), "junos_security_utm_profile_web_filtering_websense_redirect": resourceSecurityUtmProfileWebFilteringWebsense(), - "junos_services": resourceServices(), + + "junos_services": resourceServices(), + "junos_services_advanced_anti_malware_policy": resourceServicesAdvancedAntiMalwarePolicy(), "junos_services_proxy_profile": resourceServicesProxyProfile(), "junos_services_rpm_probe": resourceServicesRpmProbe(), @@ -208,12 +222,15 @@ func Provider() *schema.Provider { "junos_services_security_intelligence_profile": resourceServicesSecurityIntellProfile(), "junos_services_user_identification_ad_access_domain": resourceServicesUserIdentAdAccessDomain(), "junos_services_user_identification_device_identity_profile": resourceServicesUserIdentDeviceIdentityProfile(), - "junos_system_login_class": resourceSystemLoginClass(), - "junos_system_login_user": resourceSystemLoginUser(), - "junos_system_ntp_server": resourceSystemNtpServer(), - "junos_system_root_authentication": resourceSystemRootAuthentication(), - "junos_system_services_dhcp_localserver_group": resourceSystemServicesDhcpLocalServerGroup(), - "junos_vlan": resourceVlan(), + + "junos_system_login_class": resourceSystemLoginClass(), + "junos_system_login_user": resourceSystemLoginUser(), + "junos_system_ntp_server": resourceSystemNtpServer(), + "junos_system_root_authentication": resourceSystemRootAuthentication(), + "junos_system_services_dhcp_localserver_group": resourceSystemServicesDhcpLocalServerGroup(), + + "junos_vlan": resourceVlan(), + "junos_vstp": resourceVstp(), "junos_vstp_interface": resourceVstpInterface(), "junos_vstp_vlan": resourceVstpVlan(), From bed41f5e805ca8789af03db47cc44e0b26fbaca7 Mon Sep 17 00:00:00 2001 From: Jeremy Muriel Date: Wed, 3 Apr 2024 18:48:10 +0200 Subject: [PATCH 10/25] d/interfaces_physical_present: add interfaces block map attribute with same attributes as interface_statuses and additional logical_interface_names attribute deprecate interface_statuses attribute (read the interfaces attribute instead) Fix #641 --- .changes/issue-641.md | 10 ++++ .../interfaces_physical_present.md | 17 +++++- internal/junos/netconf_rpc.go | 9 ++- ...data_source_interfaces_physical_present.go | 56 ++++++++++++++++--- ...source_interfaces_physical_present_test.go | 16 ++++++ .../3/main.tf | 4 ++ .../4/main.tf | 4 ++ 7 files changed, 101 insertions(+), 15 deletions(-) create mode 100644 .changes/issue-641.md diff --git a/.changes/issue-641.md b/.changes/issue-641.md new file mode 100644 index 00000000..78bed4aa --- /dev/null +++ b/.changes/issue-641.md @@ -0,0 +1,10 @@ + +FEATURES: + +ENHANCEMENTS: + +* **data-source/junos_interfaces_physical_present**: + * add `interfaces` block map attribute with same attributes as `interface_statuses` and additional `logical_interface_names` attribute (Fix [#641](https://github.com/jeremmfr/terraform-provider-junos/issues/641)) + * deprecate `interface_statuses` attribute (read the `interfaces` attribute instead) + +BUG FIXES: diff --git a/docs/data-sources/interfaces_physical_present.md b/docs/data-sources/interfaces_physical_present.md index 4c06d810..89bb6bfa 100644 --- a/docs/data-sources/interfaces_physical_present.md +++ b/docs/data-sources/interfaces_physical_present.md @@ -35,9 +35,20 @@ The following attributes are exported: - **id** (String) An identifier for the data source. - **interface_names** (List of String) - List of interface names found. -- **interface_statuses** (Block List) - For each interface name. + Found interface names. +- **interfaces** (Block Map) + Dictionary of found interfaces with interface name as key. + - **name** (String) + Interface name (as the map key). + - **admin_status** (String) + Admin status. + - **oper_status** (String) + Operational status. + - **logical_interface_names** (List of String) + Logical interface names under this physical interface. +- **interface_statuses** (Block List, **Deprecated**) + For each found interface name, its status. + Deprecated attribute, use the `interfaces` attribute instead. - **name** (String) Interface name. - **admin_status** (String) diff --git a/internal/junos/netconf_rpc.go b/internal/junos/netconf_rpc.go index 5cc967d6..582c5d85 100644 --- a/internal/junos/netconf_rpc.go +++ b/internal/junos/netconf_rpc.go @@ -70,9 +70,12 @@ type commitResults struct { type RPCGetPhysicalInterfaceTerseReply struct { XMLName xml.Name `xml:"interface-information"` PhysicalInterface []struct { - Name string `xml:"name"` - AdminStatus string `xml:"admin-status"` - OperStatus string `xml:"oper-status"` + Name string `xml:"name"` + AdminStatus string `xml:"admin-status"` + OperStatus string `xml:"oper-status"` + LogicalInterface []struct { + Name string `xml:"name"` + } `xml:"logical-interface"` } `xml:"physical-interface"` } diff --git a/internal/providerfwk/data_source_interfaces_physical_present.go b/internal/providerfwk/data_source_interfaces_physical_present.go index 08af2a10..84e54c08 100644 --- a/internal/providerfwk/data_source_interfaces_physical_present.go +++ b/internal/providerfwk/data_source_interfaces_physical_present.go @@ -99,11 +99,24 @@ func (dsc *interfacesPhysicalPresentDataSource) Schema( "interface_names": schema.ListAttribute{ ElementType: types.StringType, Computed: true, - Description: "List of interface names found.", + Description: "Found interface names.", }, - "interface_statuses": schema.ListAttribute{ + "interfaces": schema.MapAttribute{ Computed: true, - Description: "For each interface name.", + Description: "Dictionary of found interfaces with interface name as key.", + ElementType: types.ObjectType{ + AttrTypes: map[string]attr.Type{ + "name": types.StringType, + "admin_status": types.StringType, + "oper_status": types.StringType, + "logical_interface_names": types.ListType{}.WithElementType(types.StringType), + }, + }, + }, + "interface_statuses": schema.ListAttribute{ + Computed: true, + DeprecationMessage: "Use the \"interfaces\" attribute instead.", + Description: "For each found interface name, its status.", ElementType: types.ObjectType{ AttrTypes: map[string]attr.Type{ "name": types.StringType, @@ -117,12 +130,13 @@ func (dsc *interfacesPhysicalPresentDataSource) Schema( } type interfacesPhysicalPresentDataSourceData struct { - ID types.String `tfsdk:"id"` - MatchName types.String `tfsdk:"match_name"` - MatchAdminUp types.Bool `tfsdk:"match_admin_up"` - MatchOperUp types.Bool `tfsdk:"match_oper_up"` - InterfaceNames []types.String `tfsdk:"interface_names"` - InterfaceStatuses []interfacesPhysicalPresentDataSourceBlockInterfaceStatuses `tfsdk:"interface_statuses"` + ID types.String `tfsdk:"id"` + MatchName types.String `tfsdk:"match_name"` + MatchAdminUp types.Bool `tfsdk:"match_admin_up"` + MatchOperUp types.Bool `tfsdk:"match_oper_up"` + InterfaceNames []types.String `tfsdk:"interface_names"` + Interfaces map[string]interfacesPhysicalPresentDataSourceBlockInterfaces `tfsdk:"interfaces"` + InterfaceStatuses []interfacesPhysicalPresentDataSourceBlockInterfaceStatuses `tfsdk:"interface_statuses"` } type interfacesPhysicalPresentDataSourceConfig struct { @@ -131,9 +145,17 @@ type interfacesPhysicalPresentDataSourceConfig struct { MatchAdminUp types.Bool `tfsdk:"match_admin_up"` MatchOperUp types.Bool `tfsdk:"match_oper_up"` InterfaceNames types.List `tfsdk:"interface_names"` + Interfaces types.Map `tfsdk:"interfaces"` InterfaceStatuses types.List `tfsdk:"interface_statuses"` } +type interfacesPhysicalPresentDataSourceBlockInterfaces struct { + Name types.String `tfsdk:"name"` + AdminStatus types.String `tfsdk:"admin_status"` + OperStatus types.String `tfsdk:"oper_status"` + LogicalInterfaceNames []types.String `tfsdk:"logical_interface_names"` +} + type interfacesPhysicalPresentDataSourceBlockInterfaceStatuses struct { Name types.String `tfsdk:"name"` AdminStatus types.String `tfsdk:"admin_status"` @@ -195,6 +217,12 @@ func (dscData *interfacesPhysicalPresentDataSourceData) read( if err != nil { return fmt.Errorf("unmarshaling xml reply %q: %w", replyData, err) } + + dscData.InterfaceNames = make([]types.String, 0, len(reply.PhysicalInterface)) + dscData.Interfaces = make(map[string]interfacesPhysicalPresentDataSourceBlockInterfaces) + dscData.InterfaceStatuses = make( + []interfacesPhysicalPresentDataSourceBlockInterfaceStatuses, 0, len(reply.PhysicalInterface), + ) for _, iFace := range reply.PhysicalInterface { if matchName != "" { matched, err := regexp.MatchString(matchName, strings.TrimSpace(iFace.Name)) @@ -212,6 +240,16 @@ func (dscData *interfacesPhysicalPresentDataSourceData) read( continue } dscData.InterfaceNames = append(dscData.InterfaceNames, types.StringValue(strings.TrimSpace(iFace.Name))) + logicalInterfaceNames := make([]types.String, len(iFace.LogicalInterface)) + for i, loIface := range iFace.LogicalInterface { + logicalInterfaceNames[i] = types.StringValue(strings.TrimSpace(loIface.Name)) + } + dscData.Interfaces[strings.TrimSpace(iFace.Name)] = interfacesPhysicalPresentDataSourceBlockInterfaces{ + Name: types.StringValue(strings.TrimSpace(iFace.Name)), + AdminStatus: types.StringValue(strings.TrimSpace(iFace.AdminStatus)), + OperStatus: types.StringValue(strings.TrimSpace(iFace.OperStatus)), + LogicalInterfaceNames: logicalInterfaceNames, + } dscData.InterfaceStatuses = append(dscData.InterfaceStatuses, interfacesPhysicalPresentDataSourceBlockInterfaceStatuses{ Name: types.StringValue(strings.TrimSpace(iFace.Name)), diff --git a/internal/providerfwk/data_source_interfaces_physical_present_test.go b/internal/providerfwk/data_source_interfaces_physical_present_test.go index e2a14dcc..741c2b97 100644 --- a/internal/providerfwk/data_source_interfaces_physical_present_test.go +++ b/internal/providerfwk/data_source_interfaces_physical_present_test.go @@ -58,6 +58,16 @@ func TestAccDataSourceInterfacesPhysicalPresent_basic(t *testing.T) { "interface_names.*", testaccInterface), resource.TestCheckResourceAttr("data.junos_interfaces_physical_present.testacc_dataIfacesPhysPresentEth003", "interface_names.#", "1"), + resource.TestCheckResourceAttr("data.junos_interfaces_physical_present.testacc_dataIfacesPhysPresentEth003", + "interfaces.%", "1"), + resource.TestCheckResourceAttr("data.junos_interfaces_physical_present.testacc_dataIfacesPhysPresentEth003", + "interfaces."+testaccInterface+".name", testaccInterface), + resource.TestCheckResourceAttr("data.junos_interfaces_physical_present.testacc_dataIfacesPhysPresentEth003", + "interfaces."+testaccInterface+".admin_status", "up"), + resource.TestCheckResourceAttr("data.junos_interfaces_physical_present.testacc_dataIfacesPhysPresentEth003", + "interfaces."+testaccInterface+".oper_status", "down"), + resource.TestCheckResourceAttr("data.junos_interfaces_physical_present.testacc_dataIfacesPhysPresentEth003", + "interfaces."+testaccInterface+".logical_interface_names.#", "1"), resource.TestCheckResourceAttr("data.junos_interfaces_physical_present.testacc_dataIfacesPhysPresentEth003", "interface_statuses.#", "1"), resource.TestCheckResourceAttr("data.junos_interfaces_physical_present.testacc_dataIfacesPhysPresentEth003", @@ -143,6 +153,12 @@ func TestAccDataSourceInterfacesPhysicalPresent_switch(t *testing.T) { "interface_names.*", testaccInterface), resource.TestCheckResourceAttr("data.junos_interfaces_physical_present.testacc_dataIfacesPhysPresentEth003", "interface_names.#", "1"), + resource.TestCheckResourceAttr("data.junos_interfaces_physical_present.testacc_dataIfacesPhysPresentEth003", + "interfaces.%", "1"), + resource.TestCheckResourceAttr("data.junos_interfaces_physical_present.testacc_dataIfacesPhysPresentEth003", + "interfaces."+testaccInterface+".name", testaccInterface), + resource.TestCheckResourceAttr("data.junos_interfaces_physical_present.testacc_dataIfacesPhysPresentEth003", + "interfaces."+testaccInterface+".admin_status", "up"), resource.TestCheckResourceAttr("data.junos_interfaces_physical_present.testacc_dataIfacesPhysPresentEth003", "interface_statuses.#", "1"), resource.TestCheckResourceAttr("data.junos_interfaces_physical_present.testacc_dataIfacesPhysPresentEth003", diff --git a/internal/providerfwk/testdata/TestAccDataSourceInterfacesPhysicalPresent_basic/3/main.tf b/internal/providerfwk/testdata/TestAccDataSourceInterfacesPhysicalPresent_basic/3/main.tf index 82f65077..40e2a4b4 100644 --- a/internal/providerfwk/testdata/TestAccDataSourceInterfacesPhysicalPresent_basic/3/main.tf +++ b/internal/providerfwk/testdata/TestAccDataSourceInterfacesPhysicalPresent_basic/3/main.tf @@ -2,5 +2,9 @@ resource "junos_interface_physical" "testacc_dataIfacesPhysPresent" { name = var.interface description = "testacc_dataIfacesPhysPresent" } +resource "junos_interface_logical" "testacc_dataIfacesPhysPresent" { + name = "${junos_interface_physical.testacc_dataIfacesPhysPresent.name}.0" + family_inet {} +} data "junos_interfaces_physical_present" "testacc_dataIfacesPhysPresent" { } diff --git a/internal/providerfwk/testdata/TestAccDataSourceInterfacesPhysicalPresent_basic/4/main.tf b/internal/providerfwk/testdata/TestAccDataSourceInterfacesPhysicalPresent_basic/4/main.tf index b7ab33a5..0f79796d 100644 --- a/internal/providerfwk/testdata/TestAccDataSourceInterfacesPhysicalPresent_basic/4/main.tf +++ b/internal/providerfwk/testdata/TestAccDataSourceInterfacesPhysicalPresent_basic/4/main.tf @@ -2,6 +2,10 @@ resource "junos_interface_physical" "testacc_dataIfacesPhysPresent" { name = var.interface description = "testacc_dataIfacesPhysPresent" } +resource "junos_interface_logical" "testacc_dataIfacesPhysPresent" { + name = "${junos_interface_physical.testacc_dataIfacesPhysPresent.name}.0" + family_inet {} +} data "junos_interfaces_physical_present" "testacc_dataIfacesPhysPresentEth" { match_name = "^${split("-", var.interface)[0]}-.*$" } From 8135398bd9f7eada44cc245a00da17c05d2d8f3f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Apr 2024 01:01:46 +0000 Subject: [PATCH 11/25] deps: bump golang.org/x/crypto from 0.21.0 to 0.22.0 Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.21.0 to 0.22.0. - [Commits](https://github.com/golang/crypto/compare/v0.21.0...v0.22.0) --- updated-dependencies: - dependency-name: golang.org/x/crypto dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 4 ++-- go.sum | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/go.mod b/go.mod index e9fdaa06..f43270a1 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/jeremmfr/go-netconf v0.4.15 github.com/jeremmfr/go-utils v0.12.0 github.com/jeremmfr/junosdecode v1.1.1 - golang.org/x/crypto v0.21.0 + golang.org/x/crypto v0.22.0 ) require ( @@ -55,7 +55,7 @@ require ( github.com/zclconf/go-cty v1.14.3 // indirect golang.org/x/mod v0.15.0 // indirect golang.org/x/net v0.21.0 // indirect - golang.org/x/sys v0.18.0 // indirect + golang.org/x/sys v0.19.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/tools v0.13.0 // indirect google.golang.org/appengine v1.6.8 // indirect diff --git a/go.sum b/go.sum index b3059272..e2865f27 100644 --- a/go.sum +++ b/go.sum @@ -158,8 +158,8 @@ github.com/zclconf/go-cty v1.14.3/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgr golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= -golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= -golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.15.0 h1:SernR4v+D55NyBH2QiEQrlBAnj1ECL6AGrA5+dPaMY8= @@ -193,15 +193,15 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= -golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= -golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= -golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= +golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q= +golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= From 010b225d422158e7d8099b95c8eca3f2d10bb739 Mon Sep 17 00:00:00 2001 From: Jeremy Muriel Date: Fri, 5 Apr 2024 15:14:21 +0200 Subject: [PATCH 12/25] providerfwk: rewrite read block identifier to check duplicate blocks --- internal/providerfwk/resource_application.go | 1 + internal/providerfwk/resource_bgp_group.go | 9 +- internal/providerfwk/resource_bgp_neighbor.go | 9 +- .../resource_eventoptions_destination.go | 8 +- .../providerfwk/resource_firewall_filter.go | 2 +- .../resource_forwardingoptions_sampling.go | 96 ++++++---- ...rce_forwardingoptions_sampling_instance.go | 96 ++++++---- .../providerfwk/resource_interface_logical.go | 172 +++++++++--------- .../resource_interface_physical.go | 24 +-- .../resource_policyoptions_as_path_group.go | 16 +- ...resource_policyoptions_policy_statement.go | 7 + .../resource_security_address_book.go | 43 +++-- .../resource_security_global_policy.go | 8 +- .../resource_security_ipsec_vpn.go | 16 +- .../resource_security_nat_destination.go | 1 + .../resource_security_nat_source.go | 1 - .../providerfwk/resource_security_policy.go | 8 +- .../providerfwk/resource_security_zone.go | 45 +++-- .../providerfwk/resource_snmp_community.go | 1 + .../resource_snmp_v3_vacm_accessgroup.go | 3 + internal/providerfwk/resource_static_route.go | 7 +- internal/providerfwk/resource_system.go | 21 ++- .../resource_system_syslog_file.go | 3 +- .../providerfwk/resource_virtual_chassis.go | 27 ++- 24 files changed, 344 insertions(+), 280 deletions(-) diff --git a/internal/providerfwk/resource_application.go b/internal/providerfwk/resource_application.go index c2fdbb56..dc8cbf61 100644 --- a/internal/providerfwk/resource_application.go +++ b/internal/providerfwk/resource_application.go @@ -670,6 +670,7 @@ func (rscData *applicationData) set( fmt.Errorf("multiple term blocks with the same name %q", name) } termName[name] = struct{}{} + blockSet, pathErr, err := block.configSet(setPrefix, path.Root("term").AtListIndex(i)) if err != nil { return pathErr, err diff --git a/internal/providerfwk/resource_bgp_group.go b/internal/providerfwk/resource_bgp_group.go index f4bdc7ce..ee7f76a9 100644 --- a/internal/providerfwk/resource_bgp_group.go +++ b/internal/providerfwk/resource_bgp_group.go @@ -1065,9 +1065,8 @@ func (rsc *bgpGroup) ValidateConfig( tfdiag.DuplicateConfigErrSummary, fmt.Sprintf("multiple family_evpn blocks with the same nlri_type %q", nlriType), ) - } else { - familyEvpnNlriType[nlriType] = struct{}{} } + familyEvpnNlriType[nlriType] = struct{}{} } if block.AcceptedPrefixLimit != nil { if block.AcceptedPrefixLimit.Maximum.IsNull() { @@ -1129,9 +1128,8 @@ func (rsc *bgpGroup) ValidateConfig( tfdiag.DuplicateConfigErrSummary, fmt.Sprintf("multiple family_inet blocks with the same nlri_type %q", nlriType), ) - } else { - familyInetNlriType[nlriType] = struct{}{} } + familyInetNlriType[nlriType] = struct{}{} } if block.AcceptedPrefixLimit != nil { if block.AcceptedPrefixLimit.Maximum.IsNull() { @@ -1193,9 +1191,8 @@ func (rsc *bgpGroup) ValidateConfig( tfdiag.DuplicateConfigErrSummary, fmt.Sprintf("multiple family_inet6 blocks with the same nlri_type %q", nlriType), ) - } else { - familyInet6NlriType[nlriType] = struct{}{} } + familyInet6NlriType[nlriType] = struct{}{} } if block.AcceptedPrefixLimit != nil { if block.AcceptedPrefixLimit.Maximum.IsNull() { diff --git a/internal/providerfwk/resource_bgp_neighbor.go b/internal/providerfwk/resource_bgp_neighbor.go index 3307dfa3..24dbbdcd 100644 --- a/internal/providerfwk/resource_bgp_neighbor.go +++ b/internal/providerfwk/resource_bgp_neighbor.go @@ -1064,9 +1064,8 @@ func (rsc *bgpNeighbor) ValidateConfig( tfdiag.DuplicateConfigErrSummary, fmt.Sprintf("multiple family_evpn blocks with the same nlri_type %q", nlriType), ) - } else { - familyEvpnNlriType[nlriType] = struct{}{} } + familyEvpnNlriType[nlriType] = struct{}{} } if block.AcceptedPrefixLimit != nil { if block.AcceptedPrefixLimit.Maximum.IsNull() { @@ -1128,9 +1127,8 @@ func (rsc *bgpNeighbor) ValidateConfig( tfdiag.DuplicateConfigErrSummary, fmt.Sprintf("multiple family_inet blocks with the same nlri_type %q", nlriType), ) - } else { - familyInetNlriType[nlriType] = struct{}{} } + familyInetNlriType[nlriType] = struct{}{} } if block.AcceptedPrefixLimit != nil { if block.AcceptedPrefixLimit.Maximum.IsNull() { @@ -1192,9 +1190,8 @@ func (rsc *bgpNeighbor) ValidateConfig( tfdiag.DuplicateConfigErrSummary, fmt.Sprintf("multiple family_inet6 blocks with the same nlri_type %q", nlriType), ) - } else { - familyInet6NlriType[nlriType] = struct{}{} } + familyInet6NlriType[nlriType] = struct{}{} } if block.AcceptedPrefixLimit != nil { if block.AcceptedPrefixLimit.Maximum.IsNull() { diff --git a/internal/providerfwk/resource_eventoptions_destination.go b/internal/providerfwk/resource_eventoptions_destination.go index e41771c9..fc8c5b88 100644 --- a/internal/providerfwk/resource_eventoptions_destination.go +++ b/internal/providerfwk/resource_eventoptions_destination.go @@ -183,15 +183,15 @@ func (rsc *eventoptionsDestination) ValidateConfig( if block.URL.IsUnknown() { continue } - if _, ok := archiveSiteURL[block.URL.ValueString()]; ok { + url := block.URL.ValueString() + if _, ok := archiveSiteURL[url]; ok { resp.Diagnostics.AddAttributeError( path.Root("archive_site").AtListIndex(i).AtName("url"), tfdiag.DuplicateConfigErrSummary, - fmt.Sprintf("multiple archive_site blocks with the same url %q", - block.URL.ValueString()), + fmt.Sprintf("multiple archive_site blocks with the same url %q", url), ) } - archiveSiteURL[block.URL.ValueString()] = struct{}{} + archiveSiteURL[url] = struct{}{} } } } diff --git a/internal/providerfwk/resource_firewall_filter.go b/internal/providerfwk/resource_firewall_filter.go index 0e613b2f..52cbb59d 100644 --- a/internal/providerfwk/resource_firewall_filter.go +++ b/internal/providerfwk/resource_firewall_filter.go @@ -1701,11 +1701,11 @@ func (rscData *firewallFilterData) set( fmt.Errorf("multiple term blocks with the same name %q", name) } termName[name] = struct{}{} + setPrefixTerm := setPrefix + "term \"" + name + "\" " if v := block.Filter.ValueString(); v != "" { configSet = append(configSet, setPrefixTerm+"filter \""+v+"\"") } - if block.From != nil { blockSet, pathErr, err := block.From.configSet(setPrefixTerm, path.Root("term").AtListIndex(i).AtName("from")) if err != nil { diff --git a/internal/providerfwk/resource_forwardingoptions_sampling.go b/internal/providerfwk/resource_forwardingoptions_sampling.go index a50c43f6..3ef7b648 100644 --- a/internal/providerfwk/resource_forwardingoptions_sampling.go +++ b/internal/providerfwk/resource_forwardingoptions_sampling.go @@ -992,15 +992,16 @@ func (rsc *forwardingoptionsSampling) ValidateConfig( if block.Hostname.IsUnknown() { continue } - if _, ok := flowServerHostname[block.Hostname.ValueString()]; ok { + hostname := block.Hostname.ValueString() + if _, ok := flowServerHostname[hostname]; ok { resp.Diagnostics.AddAttributeError( path.Root("family_inet_output").AtName("flow_server"), tfdiag.DuplicateConfigErrSummary, - fmt.Sprintf("multiple flow_server blocks with the same hostname %q in family_inet_output block", - block.Hostname.ValueString()), + fmt.Sprintf("multiple flow_server blocks with the same hostname %q"+ + " in family_inet_output block", hostname), ) } - flowServerHostname[block.Hostname.ValueString()] = struct{}{} + flowServerHostname[hostname] = struct{}{} } } if !config.FamilyInetOutput.Interface.IsNull() && !config.FamilyInetOutput.Interface.IsUnknown() { @@ -1016,15 +1017,16 @@ func (rsc *forwardingoptionsSampling) ValidateConfig( if block.Name.IsUnknown() { continue } - if _, ok := interfaceName[block.Name.ValueString()]; ok { + name := block.Name.ValueString() + if _, ok := interfaceName[name]; ok { resp.Diagnostics.AddAttributeError( path.Root("family_inet_output").AtName("interface").AtListIndex(i).AtName("name"), tfdiag.DuplicateConfigErrSummary, - fmt.Sprintf("multiple interface blocks with the same name %q in family_inet_output block", - block.Name.ValueString()), + fmt.Sprintf("multiple interface blocks with the same name %q"+ + " in family_inet_output block", name), ) } - interfaceName[block.Name.ValueString()] = struct{}{} + interfaceName[name] = struct{}{} } } } @@ -1072,15 +1074,16 @@ func (rsc *forwardingoptionsSampling) ValidateConfig( if block.Hostname.IsUnknown() { continue } - if _, ok := flowServerHostname[block.Hostname.ValueString()]; ok { + hostname := block.Hostname.ValueString() + if _, ok := flowServerHostname[hostname]; ok { resp.Diagnostics.AddAttributeError( path.Root("family_inet6_output").AtName("flow_server"), tfdiag.DuplicateConfigErrSummary, - fmt.Sprintf("multiple flow_server blocks with the same hostname %q in family_inet6_output block", - block.Hostname.ValueString()), + fmt.Sprintf("multiple flow_server blocks with the same hostname %q"+ + " in family_inet6_output block", hostname), ) } - flowServerHostname[block.Hostname.ValueString()] = struct{}{} + flowServerHostname[hostname] = struct{}{} } } if !config.FamilyInet6Output.Interface.IsNull() && !config.FamilyInet6Output.Interface.IsUnknown() { @@ -1096,15 +1099,16 @@ func (rsc *forwardingoptionsSampling) ValidateConfig( if block.Name.IsUnknown() { continue } - if _, ok := interfaceName[block.Name.ValueString()]; ok { + name := block.Name.ValueString() + if _, ok := interfaceName[name]; ok { resp.Diagnostics.AddAttributeError( path.Root("family_inet6_output").AtName("interface").AtListIndex(i).AtName("name"), tfdiag.DuplicateConfigErrSummary, - fmt.Sprintf("multiple interface blocks with the same name %q in family_inet6_output block", - block.Name.ValueString()), + fmt.Sprintf("multiple interface blocks with the same name %q"+ + " in family_inet6_output block", name), ) } - interfaceName[block.Name.ValueString()] = struct{}{} + interfaceName[name] = struct{}{} } } } @@ -1137,15 +1141,16 @@ func (rsc *forwardingoptionsSampling) ValidateConfig( if block.Hostname.IsUnknown() { continue } - if _, ok := flowServerHostname[block.Hostname.ValueString()]; ok { + hostname := block.Hostname.ValueString() + if _, ok := flowServerHostname[hostname]; ok { resp.Diagnostics.AddAttributeError( path.Root("family_mpls_output").AtName("flow_server"), tfdiag.DuplicateConfigErrSummary, - fmt.Sprintf("multiple flow_server blocks with the same hostname %q in family_mpls_output block", - block.Hostname.ValueString()), + fmt.Sprintf("multiple flow_server blocks with the same hostname %q"+ + " in family_mpls_output block", hostname), ) } - flowServerHostname[block.Hostname.ValueString()] = struct{}{} + flowServerHostname[hostname] = struct{}{} } } if !config.FamilyMplsOutput.Interface.IsNull() && !config.FamilyMplsOutput.Interface.IsUnknown() { @@ -1161,15 +1166,16 @@ func (rsc *forwardingoptionsSampling) ValidateConfig( if block.Name.IsUnknown() { continue } - if _, ok := interfaceName[block.Name.ValueString()]; ok { + name := block.Name.ValueString() + if _, ok := interfaceName[name]; ok { resp.Diagnostics.AddAttributeError( path.Root("family_mpls_output").AtName("interface").AtListIndex(i).AtName("name"), tfdiag.DuplicateConfigErrSummary, - fmt.Sprintf("multiple interface blocks with the same name %q in family_mpls_output block", - block.Name.ValueString()), + fmt.Sprintf("multiple interface blocks with the same name %q"+ + " in family_mpls_output block", name), ) } - interfaceName[block.Name.ValueString()] = struct{}{} + interfaceName[name] = struct{}{} } } } @@ -1539,6 +1545,7 @@ func (block *forwardingoptionsSamplingBlockFamilyInetOutput) configSet( hostname) } flowServerHostname[hostname] = struct{}{} + setPrefixFlowServer := setPrefix + "flow-server " + hostname + " " configSet = append(configSet, setPrefixFlowServer+"port "+ utils.ConvI64toa(blockFlowServer.Port.ValueInt64())) @@ -1597,13 +1604,15 @@ func (block *forwardingoptionsSamplingBlockFamilyInetOutput) configSet( } interfaceName := make(map[string]struct{}) for i, blockInterface := range block.Interface { - if _, ok := interfaceName[blockInterface.Name.ValueString()]; ok { + name := blockInterface.Name.ValueString() + if _, ok := interfaceName[name]; ok { return configSet, path.Root("family_inet_output").AtName("interface").AtListIndex(i).AtName("name"), - fmt.Errorf("multiple interface blocks with the same name %q in family_inet_output block", - blockInterface.Name.ValueString()) + fmt.Errorf("multiple interface blocks with the same name %q"+ + " in family_inet_output block", name) } - interfaceName[blockInterface.Name.ValueString()] = struct{}{} + interfaceName[name] = struct{}{} + configSet = append(configSet, blockInterface.configSet(setPrefix)...) } @@ -1637,13 +1646,15 @@ func (block *forwardingoptionsSamplingBlockFamilyInet6Output) configSet( } flowServerHostname := make(map[string]struct{}) for _, blockFlowServer := range block.FlowServer { - if _, ok := flowServerHostname[blockFlowServer.Hostname.ValueString()]; ok { + hostname := blockFlowServer.Hostname.ValueString() + if _, ok := flowServerHostname[hostname]; ok { return configSet, path.Root("family_inet6_output").AtName("flow_server"), - fmt.Errorf("multiple flow_server blocks with the same hostname %q in family_inet6_output block", - blockFlowServer.Hostname.ValueString()) + fmt.Errorf("multiple flow_server blocks with the same hostname %q"+ + " in family_inet6_output block", hostname) } - flowServerHostname[blockFlowServer.Hostname.ValueString()] = struct{}{} + flowServerHostname[hostname] = struct{}{} + blockSet, err := blockFlowServer.configSet(setPrefix) if err != nil { return configSet, path.Root("family_inet6_output").AtName("flow_server"), err @@ -1659,13 +1670,15 @@ func (block *forwardingoptionsSamplingBlockFamilyInet6Output) configSet( } interfaceName := make(map[string]struct{}) for i, blockInterface := range block.Interface { - if _, ok := interfaceName[blockInterface.Name.ValueString()]; ok { + name := blockInterface.Name.ValueString() + if _, ok := interfaceName[name]; ok { return configSet, path.Root("family_inet6_output").AtName("interface").AtListIndex(i).AtName("name"), - fmt.Errorf("multiple interface blocks with the same name %q in family_inet6_output block", - blockInterface.Name.ValueString()) + fmt.Errorf("multiple interface blocks with the same name %q"+ + " in family_inet6_output block", name) } - interfaceName[blockInterface.Name.ValueString()] = struct{}{} + interfaceName[name] = struct{}{} + configSet = append(configSet, blockInterface.configSet(setPrefix)...) } @@ -1704,6 +1717,7 @@ func (block *forwardingoptionsSamplingBlockFamilyMplsOutput) configSet( hostname) } flowServerHostname[hostname] = struct{}{} + blockSet, err := blockFlowServer.configSet(setPrefix) if err != nil { return configSet, path.Root("family_mpls_output").AtName("flow_server"), err @@ -1712,13 +1726,15 @@ func (block *forwardingoptionsSamplingBlockFamilyMplsOutput) configSet( } interfaceName := make(map[string]struct{}) for i, blockInterface := range block.Interface { - if _, ok := interfaceName[blockInterface.Name.ValueString()]; ok { + name := blockInterface.Name.ValueString() + if _, ok := interfaceName[name]; ok { return configSet, path.Root("family_mpls_output").AtName("interface").AtListIndex(i).AtName("name"), - fmt.Errorf("multiple interface blocks with the same name %q in family_mpls_output block", - blockInterface.Name.ValueString()) + fmt.Errorf("multiple interface blocks with the same name %q"+ + " in family_mpls_output block", name) } - interfaceName[blockInterface.Name.ValueString()] = struct{}{} + interfaceName[name] = struct{}{} + configSet = append(configSet, blockInterface.configSet(setPrefix)...) } diff --git a/internal/providerfwk/resource_forwardingoptions_sampling_instance.go b/internal/providerfwk/resource_forwardingoptions_sampling_instance.go index a48a0004..0dffa07a 100644 --- a/internal/providerfwk/resource_forwardingoptions_sampling_instance.go +++ b/internal/providerfwk/resource_forwardingoptions_sampling_instance.go @@ -900,15 +900,16 @@ func (rsc *forwardingoptionsSamplingInstance) ValidateConfig( if block.Hostname.IsUnknown() { continue } - if _, ok := flowServerHostname[block.Hostname.ValueString()]; ok { + hostname := block.Hostname.ValueString() + if _, ok := flowServerHostname[hostname]; ok { resp.Diagnostics.AddAttributeError( path.Root("family_inet_output").AtName("flow_server"), tfdiag.DuplicateConfigErrSummary, - fmt.Sprintf("multiple flow_server blocks with the same hostname %q in family_inet_output block", - block.Hostname.ValueString()), + fmt.Sprintf("multiple flow_server blocks with the same hostname %q"+ + " in family_inet_output block", hostname), ) } - flowServerHostname[block.Hostname.ValueString()] = struct{}{} + flowServerHostname[hostname] = struct{}{} } } if !config.FamilyInetOutput.Interface.IsNull() && !config.FamilyInetOutput.Interface.IsUnknown() { @@ -924,15 +925,16 @@ func (rsc *forwardingoptionsSamplingInstance) ValidateConfig( if block.Name.IsUnknown() { continue } - if _, ok := interfaceName[block.Name.ValueString()]; ok { + name := block.Name.ValueString() + if _, ok := interfaceName[name]; ok { resp.Diagnostics.AddAttributeError( path.Root("family_inet_output").AtName("interface").AtListIndex(i).AtName("name"), tfdiag.DuplicateConfigErrSummary, - fmt.Sprintf("multiple interface blocks with the same name %q in family_inet_output block", - block.Name.ValueString()), + fmt.Sprintf("multiple interface blocks with the same name %q"+ + " in family_inet_output block", name), ) } - interfaceName[block.Name.ValueString()] = struct{}{} + interfaceName[name] = struct{}{} } } } @@ -972,15 +974,16 @@ func (rsc *forwardingoptionsSamplingInstance) ValidateConfig( if block.Hostname.IsUnknown() { continue } - if _, ok := flowServerHostname[block.Hostname.ValueString()]; ok { + hostname := block.Hostname.ValueString() + if _, ok := flowServerHostname[hostname]; ok { resp.Diagnostics.AddAttributeError( path.Root("family_inet6_output").AtName("flow_server"), tfdiag.DuplicateConfigErrSummary, - fmt.Sprintf("multiple flow_server blocks with the same hostname %q in family_inet6_output block", - block.Hostname.ValueString()), + fmt.Sprintf("multiple flow_server blocks with the same hostname %q"+ + " in family_inet6_output block", hostname), ) } - flowServerHostname[block.Hostname.ValueString()] = struct{}{} + flowServerHostname[hostname] = struct{}{} } } if !config.FamilyInet6Output.Interface.IsNull() && !config.FamilyInet6Output.Interface.IsUnknown() { @@ -996,15 +999,16 @@ func (rsc *forwardingoptionsSamplingInstance) ValidateConfig( if block.Name.IsUnknown() { continue } - if _, ok := interfaceName[block.Name.ValueString()]; ok { + name := block.Name.ValueString() + if _, ok := interfaceName[name]; ok { resp.Diagnostics.AddAttributeError( path.Root("family_inet6_output").AtName("interface").AtListIndex(i).AtName("name"), tfdiag.DuplicateConfigErrSummary, - fmt.Sprintf("multiple interface blocks with the same name %q in family_inet6_output block", - block.Name.ValueString()), + fmt.Sprintf("multiple interface blocks with the same name %q"+ + " in family_inet6_output block", name), ) } - interfaceName[block.Name.ValueString()] = struct{}{} + interfaceName[name] = struct{}{} } } } @@ -1044,15 +1048,16 @@ func (rsc *forwardingoptionsSamplingInstance) ValidateConfig( if block.Hostname.IsUnknown() { continue } - if _, ok := flowServerHostname[block.Hostname.ValueString()]; ok { + hostname := block.Hostname.ValueString() + if _, ok := flowServerHostname[hostname]; ok { resp.Diagnostics.AddAttributeError( path.Root("family_mpls_output").AtName("flow_server"), tfdiag.DuplicateConfigErrSummary, - fmt.Sprintf("multiple flow_server blocks with the same hostname %q in family_mpls_output block", - block.Hostname.ValueString()), + fmt.Sprintf("multiple flow_server blocks with the same hostname %q"+ + " in family_mpls_output block", hostname), ) } - flowServerHostname[block.Hostname.ValueString()] = struct{}{} + flowServerHostname[hostname] = struct{}{} } } if !config.FamilyMplsOutput.Interface.IsNull() && !config.FamilyMplsOutput.Interface.IsUnknown() { @@ -1068,15 +1073,16 @@ func (rsc *forwardingoptionsSamplingInstance) ValidateConfig( if block.Name.IsUnknown() { continue } - if _, ok := interfaceName[block.Name.ValueString()]; ok { + name := block.Name.ValueString() + if _, ok := interfaceName[name]; ok { resp.Diagnostics.AddAttributeError( path.Root("family_mpls_output").AtName("interface").AtListIndex(i).AtName("name"), tfdiag.DuplicateConfigErrSummary, - fmt.Sprintf("multiple interface blocks with the same name %q in family_mpls_output block", - block.Name.ValueString()), + fmt.Sprintf("multiple interface blocks with the same name %q"+ + " in family_mpls_output block", name), ) } - interfaceName[block.Name.ValueString()] = struct{}{} + interfaceName[name] = struct{}{} } } } @@ -1457,6 +1463,7 @@ func (block *forwardingoptionsSamplingInstanceBlockFamilyInetOutput) configSet( hostname) } flowServerHostname[hostname] = struct{}{} + setPrefixFlowServer := setPrefix + "flow-server " + hostname + " " configSet = append(configSet, setPrefixFlowServer+"port "+ utils.ConvI64toa(blockFlowServer.Port.ValueInt64())) @@ -1525,13 +1532,15 @@ func (block *forwardingoptionsSamplingInstanceBlockFamilyInetOutput) configSet( } interfaceName := make(map[string]struct{}) for i, blockInterface := range block.Interface { - if _, ok := interfaceName[blockInterface.Name.ValueString()]; ok { + name := blockInterface.Name.ValueString() + if _, ok := interfaceName[name]; ok { return configSet, path.Root("family_inet_output").AtName("interface").AtListIndex(i).AtName("name"), - fmt.Errorf("multiple interface blocks with the same name %q in family_inet_output block", - blockInterface.Name.ValueString()) + fmt.Errorf("multiple interface blocks with the same name %q"+ + " in family_inet_output block", name) } - interfaceName[blockInterface.Name.ValueString()] = struct{}{} + interfaceName[name] = struct{}{} + configSet = append(configSet, blockInterface.configSet(setPrefix)...) } @@ -1565,13 +1574,15 @@ func (block *forwardingoptionsSamplingInstanceBlockFamilyInet6Output) configSet( } flowServerHostname := make(map[string]struct{}) for _, blockFlowServer := range block.FlowServer { - if _, ok := flowServerHostname[blockFlowServer.Hostname.ValueString()]; ok { + hostname := blockFlowServer.Hostname.ValueString() + if _, ok := flowServerHostname[hostname]; ok { return configSet, path.Root("family_inet6_output").AtName("flow_server"), - fmt.Errorf("multiple flow_server blocks with the same hostname %q in family_inet6_output block", - blockFlowServer.Hostname.ValueString()) + fmt.Errorf("multiple flow_server blocks with the same hostname %q"+ + " in family_inet6_output block", hostname) } - flowServerHostname[blockFlowServer.Hostname.ValueString()] = struct{}{} + flowServerHostname[hostname] = struct{}{} + blockSet, err := blockFlowServer.configSet(setPrefix) if err != nil { return configSet, path.Root("family_inet6_output").AtName("flow_server"), err @@ -1587,13 +1598,15 @@ func (block *forwardingoptionsSamplingInstanceBlockFamilyInet6Output) configSet( } interfaceName := make(map[string]struct{}) for i, blockInterface := range block.Interface { - if _, ok := interfaceName[blockInterface.Name.ValueString()]; ok { + name := blockInterface.Name.ValueString() + if _, ok := interfaceName[name]; ok { return configSet, path.Root("family_inet6_output").AtName("interface").AtListIndex(i).AtName("name"), - fmt.Errorf("multiple interface blocks with the same name %q in family_inet6_output block", - blockInterface.Name.ValueString()) + fmt.Errorf("multiple interface blocks with the same name %q"+ + " in family_inet6_output block", name) } - interfaceName[blockInterface.Name.ValueString()] = struct{}{} + interfaceName[name] = struct{}{} + configSet = append(configSet, blockInterface.configSet(setPrefix)...) } @@ -1632,6 +1645,7 @@ func (block *forwardingoptionsSamplingInstanceBlockFamilyMplsOutput) configSet( hostname) } flowServerHostname[hostname] = struct{}{} + blockSet, err := blockFlowServer.configSet(setPrefix) if err != nil { return configSet, path.Root("family_mpls_output").AtName("flow_server"), err @@ -1647,13 +1661,15 @@ func (block *forwardingoptionsSamplingInstanceBlockFamilyMplsOutput) configSet( } interfaceName := make(map[string]struct{}) for i, blockInterface := range block.Interface { - if _, ok := interfaceName[blockInterface.Name.ValueString()]; ok { + name := blockInterface.Name.ValueString() + if _, ok := interfaceName[name]; ok { return configSet, path.Root("family_mpls_output").AtName("interface").AtListIndex(i).AtName("name"), - fmt.Errorf("multiple interface blocks with the same name %q in family_mpls_output block", - blockInterface.Name.ValueString()) + fmt.Errorf("multiple interface blocks with the same name %q"+ + " in family_mpls_output block", name) } - interfaceName[blockInterface.Name.ValueString()] = struct{}{} + interfaceName[name] = struct{}{} + configSet = append(configSet, blockInterface.configSet(setPrefix)...) } diff --git a/internal/providerfwk/resource_interface_logical.go b/internal/providerfwk/resource_interface_logical.go index aebcf7e6..da9f5062 100644 --- a/internal/providerfwk/resource_interface_logical.go +++ b/internal/providerfwk/resource_interface_logical.go @@ -1354,15 +1354,16 @@ func (rsc *interfaceLogical) ValidateConfig( addressCIDRIP := make(map[string]struct{}) for i, address := range configAddress { if !address.CidrIP.IsUnknown() { - if _, ok := addressCIDRIP[address.CidrIP.ValueString()]; ok { + cidrIP := address.CidrIP.ValueString() + if _, ok := addressCIDRIP[cidrIP]; ok { resp.Diagnostics.AddAttributeError( path.Root("family_inet").AtName("address").AtListIndex(i).AtName("cidr_ip"), tfdiag.DuplicateConfigErrSummary, - fmt.Sprintf("multiple address blocks with the same cidr_ip %q in family_inet block", - address.CidrIP.ValueString()), + fmt.Sprintf("multiple address blocks with the same cidr_ip %q"+ + " in family_inet block", cidrIP), ) } - addressCIDRIP[address.CidrIP.ValueString()] = struct{}{} + addressCIDRIP[cidrIP] = struct{}{} } if !address.VRRPGroup.IsNull() && !address.VRRPGroup.IsUnknown() { var configVRRPGroup []interfaceLogicalBlockFamilyInetBlockAddressBlockVRRPGroupConfig @@ -1375,16 +1376,17 @@ func (rsc *interfaceLogical) ValidateConfig( vrrpGroupID := make(map[int64]struct{}) for ii, vrrpGroup := range configVRRPGroup { if !vrrpGroup.Identifier.IsUnknown() { - if _, ok := vrrpGroupID[vrrpGroup.Identifier.ValueInt64()]; ok { + identifier := vrrpGroup.Identifier.ValueInt64() + if _, ok := vrrpGroupID[identifier]; ok { resp.Diagnostics.AddAttributeError( path.Root("family_inet").AtName("address").AtListIndex(i). AtName("vrrp_group").AtListIndex(ii).AtName("identifier"), tfdiag.DuplicateConfigErrSummary, - fmt.Sprintf("multiple vrrp_group blocks with the same identifier %d in address block %q in family_inet block", - vrrpGroup.Identifier.ValueInt64(), address.CidrIP.ValueString()), + fmt.Sprintf("multiple vrrp_group blocks with the same identifier %d in address block %q"+ + " in family_inet block", identifier, address.CidrIP.ValueString()), ) } - vrrpGroupID[vrrpGroup.Identifier.ValueInt64()] = struct{}{} + vrrpGroupID[identifier] = struct{}{} } if !vrrpGroup.TrackInterface.IsNull() && !vrrpGroup.TrackInterface.IsUnknown() { @@ -1400,18 +1402,19 @@ func (rsc *interfaceLogical) ValidateConfig( if trackInterface.Interface.IsUnknown() { continue } - if _, ok := trackInterfaceInterface[trackInterface.Interface.ValueString()]; ok { + interFace := trackInterface.Interface.ValueString() + if _, ok := trackInterfaceInterface[interFace]; ok { resp.Diagnostics.AddAttributeError( path.Root("family_inet").AtName("address").AtListIndex(i). AtName("vrrp_group").AtListIndex(ii). AtName("track_interface").AtListIndex(iii).AtName("interface"), tfdiag.DuplicateConfigErrSummary, - fmt.Sprintf("multiple track_interface blocks with the same interface %q "+ - "in vrrp_group block %d in address block %q in family_inet block", - trackInterface.Interface.ValueString(), vrrpGroup.Identifier.ValueInt64(), address.CidrIP.ValueString()), + fmt.Sprintf("multiple track_interface blocks with the same interface %q"+ + " in vrrp_group block %d in address block %q in family_inet block", + interFace, vrrpGroup.Identifier.ValueInt64(), address.CidrIP.ValueString()), ) } - trackInterfaceInterface[trackInterface.Interface.ValueString()] = struct{}{} + trackInterfaceInterface[interFace] = struct{}{} } } if !vrrpGroup.TrackRoute.IsNull() && !vrrpGroup.TrackRoute.IsUnknown() { @@ -1427,18 +1430,19 @@ func (rsc *interfaceLogical) ValidateConfig( if trackRoute.Route.IsUnknown() { continue } - if _, ok := trackRouteRoute[trackRoute.Route.ValueString()]; ok { + route := trackRoute.Route.ValueString() + if _, ok := trackRouteRoute[route]; ok { resp.Diagnostics.AddAttributeError( path.Root("family_inet").AtName("address").AtListIndex(i). AtName("vrrp_group").AtListIndex(ii). AtName("track_route").AtListIndex(iii).AtName("route"), tfdiag.DuplicateConfigErrSummary, - fmt.Sprintf("multiple track_route blocks with the same route %q "+ - "in vrrp_group block %d in address block %q in family_inet block", - trackRoute.Route.ValueString(), vrrpGroup.Identifier.ValueInt64(), address.CidrIP.ValueString()), + fmt.Sprintf("multiple track_route blocks with the same route %q"+ + " in vrrp_group block %d in address block %q in family_inet block", + route, vrrpGroup.Identifier.ValueInt64(), address.CidrIP.ValueString()), ) } - trackRouteRoute[trackRoute.Route.ValueString()] = struct{}{} + trackRouteRoute[route] = struct{}{} } } } @@ -1491,15 +1495,16 @@ func (rsc *interfaceLogical) ValidateConfig( addressCIDRIP := make(map[string]struct{}) for i, address := range configAddress { if !address.CidrIP.IsUnknown() { - if _, ok := addressCIDRIP[address.CidrIP.ValueString()]; ok { + cidrIP := address.CidrIP.ValueString() + if _, ok := addressCIDRIP[cidrIP]; ok { resp.Diagnostics.AddAttributeError( path.Root("family_inet6").AtName("address").AtListIndex(i).AtName("cidr_ip"), tfdiag.DuplicateConfigErrSummary, - fmt.Sprintf("multiple address blocks with the same cidr_ip %q in family_inet6 block", - address.CidrIP.ValueString()), + fmt.Sprintf("multiple address blocks with the same cidr_ip %q"+ + " in family_inet6 block", cidrIP), ) } - addressCIDRIP[address.CidrIP.ValueString()] = struct{}{} + addressCIDRIP[cidrIP] = struct{}{} } if !address.VRRPGroup.IsNull() && !address.VRRPGroup.IsUnknown() { var configVRRPGroup []interfaceLogicalBlockFamilyInet6BlockAddressBlockVRRPGroupConfig @@ -1512,16 +1517,17 @@ func (rsc *interfaceLogical) ValidateConfig( vrrpGroupID := make(map[int64]struct{}) for ii, vrrpGroup := range configVRRPGroup { if !vrrpGroup.Identifier.IsUnknown() { - if _, ok := vrrpGroupID[vrrpGroup.Identifier.ValueInt64()]; ok { + identifier := vrrpGroup.Identifier.ValueInt64() + if _, ok := vrrpGroupID[identifier]; ok { resp.Diagnostics.AddAttributeError( path.Root("family_inet6").AtName("address").AtListIndex(i). AtName("vrrp_group").AtListIndex(ii).AtName("identifier"), tfdiag.DuplicateConfigErrSummary, - fmt.Sprintf("multiple vrrp_group blocks with the same identifier %d in address block %q in family_inet6 block", - vrrpGroup.Identifier.ValueInt64(), address.CidrIP.ValueString()), + fmt.Sprintf("multiple vrrp_group blocks with the same identifier %d"+ + " in address block %q in family_inet6 block", identifier, address.CidrIP.ValueString()), ) } - vrrpGroupID[vrrpGroup.Identifier.ValueInt64()] = struct{}{} + vrrpGroupID[identifier] = struct{}{} } if !vrrpGroup.TrackInterface.IsNull() && !vrrpGroup.TrackInterface.IsUnknown() { @@ -1537,18 +1543,19 @@ func (rsc *interfaceLogical) ValidateConfig( if trackInterface.Interface.IsUnknown() { continue } - if _, ok := trackInterfaceInterface[trackInterface.Interface.ValueString()]; ok { + interFace := trackInterface.Interface.ValueString() + if _, ok := trackInterfaceInterface[interFace]; ok { resp.Diagnostics.AddAttributeError( path.Root("family_inet6").AtName("address").AtListIndex(i). AtName("vrrp_group").AtListIndex(ii). AtName("track_interface").AtListIndex(iii).AtName("interface"), tfdiag.DuplicateConfigErrSummary, - fmt.Sprintf("multiple track_interface blocks with the same interface %q "+ - "in vrrp_group block %d in address block %q in family_inet6 block", - trackInterface.Interface.ValueString(), vrrpGroup.Identifier.ValueInt64(), address.CidrIP.ValueString()), + fmt.Sprintf("multiple track_interface blocks with the same interface %q"+ + " in vrrp_group block %d in address block %q in family_inet6 block", + interFace, vrrpGroup.Identifier.ValueInt64(), address.CidrIP.ValueString()), ) } - trackInterfaceInterface[trackInterface.Interface.ValueString()] = struct{}{} + trackInterfaceInterface[interFace] = struct{}{} } } if !vrrpGroup.TrackRoute.IsNull() && !vrrpGroup.TrackRoute.IsUnknown() { @@ -1564,18 +1571,19 @@ func (rsc *interfaceLogical) ValidateConfig( if trackRoute.Route.IsUnknown() { continue } - if _, ok := trackRouteRoute[trackRoute.Route.ValueString()]; ok { + route := trackRoute.Route.ValueString() + if _, ok := trackRouteRoute[route]; ok { resp.Diagnostics.AddAttributeError( path.Root("family_inet6").AtName("address").AtListIndex(i). AtName("vrrp_group").AtListIndex(ii). AtName("track_route").AtListIndex(iii).AtName("route"), tfdiag.DuplicateConfigErrSummary, - fmt.Sprintf("multiple track_route blocks with the same route %q "+ - "in vrrp_group block %d in address block %q in family_inet6 block", - trackRoute.Route.ValueString(), vrrpGroup.Identifier.ValueInt64(), address.CidrIP.ValueString()), + fmt.Sprintf("multiple track_route blocks with the same route %q"+ + " in vrrp_group block %d in address block %q in family_inet6 block", + route, vrrpGroup.Identifier.ValueInt64(), address.CidrIP.ValueString()), ) } - trackRouteRoute[trackRoute.Route.ValueString()] = struct{}{} + trackRouteRoute[route] = struct{}{} } } } @@ -2302,11 +2310,14 @@ func (rscData *interfaceLogicalData) set( addressCIDRIP := make(map[string]struct{}) for i, address := range rscData.FamilyInet.Address { - if _, ok := addressCIDRIP[address.CidrIP.ValueString()]; ok { + cidrIP := address.CidrIP.ValueString() + if _, ok := addressCIDRIP[cidrIP]; ok { return path.Root("family_inet").AtName("address").AtListIndex(i).AtName("cidr_ip"), - fmt.Errorf("multiple address blocks with the same cidr_ip %q in family_inet block", address.CidrIP.ValueString()) + fmt.Errorf("multiple address blocks with the same cidr_ip %q"+ + " in family_inet block", cidrIP) } - addressCIDRIP[address.CidrIP.ValueString()] = struct{}{} + addressCIDRIP[cidrIP] = struct{}{} + blockSet, pathErr, err := address.configSet(setPrefix, path.Root("family_inet").AtName("address").AtListIndex(i)) if err != nil { return pathErr, err @@ -2347,11 +2358,14 @@ func (rscData *interfaceLogicalData) set( addressCIDRIP := make(map[string]struct{}) for i, address := range rscData.FamilyInet6.Address { - if _, ok := addressCIDRIP[address.CidrIP.ValueString()]; ok { + cidrIP := address.CidrIP.ValueString() + if _, ok := addressCIDRIP[cidrIP]; ok { return path.Root("family_inet6").AtName("address").AtListIndex(i).AtName("cidr_ip"), - fmt.Errorf("multiple address blocks with the same cidr_ip %q in family_inet6 block", address.CidrIP.ValueString()) + fmt.Errorf("multiple address blocks with the same cidr_ip %q"+ + " in family_inet6 block", cidrIP) } - addressCIDRIP[address.CidrIP.ValueString()] = struct{}{} + addressCIDRIP[cidrIP] = struct{}{} + blockSet, pathErr, err := address.configSet(setPrefix, path.Root("family_inet6").AtName("address").AtListIndex(i)) if err != nil { return pathErr, err @@ -2469,12 +2483,13 @@ func (block *interfaceLogicalBlockFamilyInetBlockAddress) configSet( errors.New("vrrp not available on st0 interface") } - if _, ok := vrrpGroupID[vrrpGroup.Identifier.ValueInt64()]; ok { + identifier := vrrpGroup.Identifier.ValueInt64() + if _, ok := vrrpGroupID[identifier]; ok { return configSet, pathRoot.AtName("vrrp_group").AtListIndex(i).AtName("identifier"), - fmt.Errorf("multiple vrrp_group blocks with the same identifier %d in address block %q in family_inet block", - vrrpGroup.Identifier.ValueInt64(), block.CidrIP.ValueString()) + fmt.Errorf("multiple vrrp_group blocks with the same identifier %d"+ + " in address block %q in family_inet block", identifier, block.CidrIP.ValueString()) } - vrrpGroupID[vrrpGroup.Identifier.ValueInt64()] = struct{}{} + vrrpGroupID[identifier] = struct{}{} setPrefixVRRPGroup := setPrefix + " vrrp-group " + utils.ConvI64toa(vrrpGroup.Identifier.ValueInt64()) + " " for _, v := range vrrpGroup.VirtualAddress { @@ -2512,34 +2527,30 @@ func (block *interfaceLogicalBlockFamilyInetBlockAddress) configSet( } trackInterfaceInterface := make(map[string]struct{}) for ii, trackInterface := range vrrpGroup.TrackInterface { - if _, ok := trackInterfaceInterface[trackInterface.Interface.ValueString()]; ok { + interFace := trackInterface.Interface.ValueString() + if _, ok := trackInterfaceInterface[interFace]; ok { return configSet, pathRoot.AtName("vrrp_group").AtListIndex(i).AtName("track_interface").AtListIndex(ii).AtName("interface"), - fmt.Errorf("multiple track_interface blocks with the same interface %q "+ - "in vrrp_group block %d in address block %q in family_inet block", - trackInterface.Interface.ValueString(), - vrrpGroup.Identifier.ValueInt64(), - block.CidrIP.ValueString(), - ) + fmt.Errorf("multiple track_interface blocks with the same interface %q"+ + " in vrrp_group block %d in address block %q in family_inet block", + interFace, vrrpGroup.Identifier.ValueInt64(), block.CidrIP.ValueString()) } - trackInterfaceInterface[trackInterface.Interface.ValueString()] = struct{}{} + trackInterfaceInterface[interFace] = struct{}{} configSet = append(configSet, setPrefixVRRPGroup+"track interface "+trackInterface.Interface.ValueString()+ " priority-cost "+utils.ConvI64toa(trackInterface.PriorityCost.ValueInt64())) } trackRouteRoute := make(map[string]struct{}) for ii, trackRoute := range vrrpGroup.TrackRoute { - if _, ok := trackRouteRoute[trackRoute.Route.ValueString()]; ok { + route := trackRoute.Route.ValueString() + if _, ok := trackRouteRoute[route]; ok { return configSet, pathRoot.AtName("vrrp_group").AtListIndex(i).AtName("track_route").AtListIndex(ii).AtName("route"), - fmt.Errorf("multiple track_route blocks with the same route %q "+ - "in vrrp_group block %d in address block %q in family_inet block", - trackRoute.Route.ValueString(), - vrrpGroup.Identifier.ValueInt64(), - block.CidrIP.ValueString(), - ) + fmt.Errorf("multiple track_route blocks with the same route %q"+ + " in vrrp_group block %d in address block %q in family_inet block", + route, vrrpGroup.Identifier.ValueInt64(), block.CidrIP.ValueString()) } - trackRouteRoute[trackRoute.Route.ValueString()] = struct{}{} + trackRouteRoute[route] = struct{}{} configSet = append(configSet, setPrefixVRRPGroup+"track route "+trackRoute.Route.ValueString()+ " routing-instance "+trackRoute.RoutingInstance.ValueString()+ @@ -2575,12 +2586,13 @@ func (block *interfaceLogicalBlockFamilyInet6BlockAddress) configSet( errors.New("vrrp not available on st0 interface") } - if _, ok := vrrpGroupID[vrrpGroup.Identifier.ValueInt64()]; ok { + identifier := vrrpGroup.Identifier.ValueInt64() + if _, ok := vrrpGroupID[identifier]; ok { return configSet, pathRoot.AtName("vrrp_group").AtListIndex(i).AtName("identifier"), - fmt.Errorf("multiple blocks vrrp_group with the same identifier %d in address block %q in family_inet6 block", - vrrpGroup.Identifier.ValueInt64(), block.CidrIP.ValueString()) + fmt.Errorf("multiple blocks vrrp_group with the same identifier %d"+ + " in address block %q in family_inet6 block", identifier, block.CidrIP.ValueString()) } - vrrpGroupID[vrrpGroup.Identifier.ValueInt64()] = struct{}{} + vrrpGroupID[identifier] = struct{}{} setPrefixVRRPGroup := setPrefix + " vrrp-inet6-group " + utils.ConvI64toa(vrrpGroup.Identifier.ValueInt64()) + " " for _, v := range vrrpGroup.VirtualAddress { @@ -2615,34 +2627,30 @@ func (block *interfaceLogicalBlockFamilyInet6BlockAddress) configSet( } trackInterfaceInterface := make(map[string]struct{}) for ii, trackInterface := range vrrpGroup.TrackInterface { - if _, ok := trackInterfaceInterface[trackInterface.Interface.ValueString()]; ok { + interFace := trackInterface.Interface.ValueString() + if _, ok := trackInterfaceInterface[interFace]; ok { return configSet, pathRoot.AtName("vrrp_group").AtListIndex(i).AtName("track_interface").AtListIndex(ii).AtName("interface"), - fmt.Errorf("multiple track_interface blocks with the same interface %q "+ - "in vrrp_group block %d in address block %q in family_inet6 block", - trackInterface.Interface.ValueString(), - vrrpGroup.Identifier.ValueInt64(), - block.CidrIP.ValueString(), - ) + fmt.Errorf("multiple track_interface blocks with the same interface %q"+ + " in vrrp_group block %d in address block %q in family_inet6 block", + interFace, vrrpGroup.Identifier.ValueInt64(), block.CidrIP.ValueString()) } - trackInterfaceInterface[trackInterface.Interface.ValueString()] = struct{}{} + trackInterfaceInterface[interFace] = struct{}{} configSet = append(configSet, setPrefixVRRPGroup+"track interface "+trackInterface.Interface.ValueString()+ " priority-cost "+utils.ConvI64toa(trackInterface.PriorityCost.ValueInt64())) } trackRouteRoute := make(map[string]struct{}) for ii, trackRoute := range vrrpGroup.TrackRoute { - if _, ok := trackRouteRoute[trackRoute.Route.ValueString()]; ok { + route := trackRoute.Route.ValueString() + if _, ok := trackRouteRoute[route]; ok { return configSet, pathRoot.AtName("vrrp_group").AtListIndex(i).AtName("track_route").AtListIndex(ii).AtName("route"), - fmt.Errorf("multiple track_route blocks with the same route %q "+ - "in vrrp_group block %d in address block %q in family_inet6 block", - trackRoute.Route.ValueString(), - vrrpGroup.Identifier.ValueInt64(), - block.CidrIP.ValueString(), - ) + fmt.Errorf("multiple track_route blocks with the same route %q"+ + " in vrrp_group block %d in address block %q in family_inet6 block", + route, vrrpGroup.Identifier.ValueInt64(), block.CidrIP.ValueString()) } - trackRouteRoute[trackRoute.Route.ValueString()] = struct{}{} + trackRouteRoute[route] = struct{}{} configSet = append(configSet, setPrefixVRRPGroup+"track route "+trackRoute.Route.ValueString()+ " routing-instance "+trackRoute.RoutingInstance.ValueString()+ diff --git a/internal/providerfwk/resource_interface_physical.go b/internal/providerfwk/resource_interface_physical.go index d8d68203..6736cdb5 100644 --- a/internal/providerfwk/resource_interface_physical.go +++ b/internal/providerfwk/resource_interface_physical.go @@ -1047,8 +1047,8 @@ func (rsc *interfacePhysical) ValidateConfig( resp.Diagnostics.AddAttributeError( path.Root("parent_ether_opts").AtName("*"), tfdiag.ConflictConfigErrSummary, - fmt.Sprintf("parent_ether_opts not compatible with this interface %q "+ - "(need to be ae* or reth* interface)", v), + fmt.Sprintf("parent_ether_opts not compatible with this interface %q"+ + " (need to be ae* or reth* interface)", v), ) } } @@ -1109,8 +1109,8 @@ func (rsc *interfacePhysical) ValidateConfig( resp.Diagnostics.AddAttributeError( path.Root("parent_ether_opts").AtName("mc_ae").AtName("*"), tfdiag.ConflictConfigErrSummary, - fmt.Sprintf("mc_ae in parent_ether_opts block not compatible with this interface %q "+ - "(need to be ae* interface)", v), + fmt.Sprintf("mc_ae in parent_ether_opts block not compatible with this interface %q"+ + " (need to be ae* interface)", v), ) } } @@ -1149,8 +1149,8 @@ func (rsc *interfacePhysical) ValidateConfig( resp.Diagnostics.AddAttributeError( path.Root("parent_ether_opts").AtName("redundancy_group"), tfdiag.ConflictConfigErrSummary, - fmt.Sprintf("redundancy_group in parent_ether_opts block not compatible with this interface %q "+ - "(need to be reth* interface)", v), + fmt.Sprintf("redundancy_group in parent_ether_opts block not compatible with this interface %q"+ + " (need to be reth* interface)", v), ) } } @@ -1971,8 +1971,8 @@ func (block *interfacePhysicalBlockParentEtherOpts) configSet( default: return configSet, path.Root("parent_ether_opts").AtName("*"), - fmt.Errorf("parent_ether_opts not compatible with this interface %q "+ - "(need to be ae* or reth* interface)", interfaceName) + fmt.Errorf("parent_ether_opts not compatible with this interface %q"+ + " (need to be ae* or reth* interface)", interfaceName) } if block.BFDLivenessDetection != nil { @@ -2067,8 +2067,8 @@ func (block *interfacePhysicalBlockParentEtherOpts) configSet( if !strings.HasPrefix(interfaceName, "ae") { return configSet, path.Root("parent_ether_opts").AtName("mc_ae").AtName("*"), - fmt.Errorf("mc_ae in parent_ether_opts block not compatible with this interface %q "+ - "(need to be ae* interface)", interfaceName) + fmt.Errorf("mc_ae in parent_ether_opts block not compatible with this interface %q"+ + " (need to be ae* interface)", interfaceName) } configSet = append(configSet, setPrefix+"mc-ae chassis-id "+ utils.ConvI64toa(block.MCAE.ChassisID.ValueInt64())) @@ -2121,8 +2121,8 @@ func (block *interfacePhysicalBlockParentEtherOpts) configSet( if !strings.HasPrefix(interfaceName, "reth") { return configSet, path.Root("parent_ether_opts").AtName("redundancy_group"), - fmt.Errorf("redundancy_group in parent_ether_opts block not compatible with this interface %q "+ - "(need to be reth* interface)", interfaceName) + fmt.Errorf("redundancy_group in parent_ether_opts block not compatible with this interface %q"+ + " (need to be reth* interface)", interfaceName) } configSet = append(configSet, setPrefix+"redundancy-group "+ utils.ConvI64toa(block.RedundancyGroup.ValueInt64())) diff --git a/internal/providerfwk/resource_policyoptions_as_path_group.go b/internal/providerfwk/resource_policyoptions_as_path_group.go index 01bcbe3e..f6b3c119 100644 --- a/internal/providerfwk/resource_policyoptions_as_path_group.go +++ b/internal/providerfwk/resource_policyoptions_as_path_group.go @@ -181,15 +181,15 @@ func (rsc *policyoptionsASPathGroup) ValidateConfig( if asPath.Name.IsUnknown() { continue } - if _, ok := asPathName[asPath.Name.ValueString()]; ok { + name := asPath.Name.ValueString() + if _, ok := asPathName[name]; ok { resp.Diagnostics.AddAttributeError( path.Root("as_path").AtListIndex(i).AtName("name"), tfdiag.DuplicateConfigErrSummary, - fmt.Sprintf("multiple as_path blocks with the same name %q", - asPath.Name.ValueString()), + fmt.Sprintf("multiple as_path blocks with the same name %q", name), ) } - asPathName[asPath.Name.ValueString()] = struct{}{} + asPathName[name] = struct{}{} } } } @@ -365,11 +365,13 @@ func (rscData *policyoptionsASPathGroupData) set( asPathName := make(map[string]struct{}) for i, block := range rscData.ASPath { - if _, ok := asPathName[block.Name.ValueString()]; ok { + name := block.Name.ValueString() + if _, ok := asPathName[name]; ok { return path.Root("as_path").AtListIndex(i).AtName("name"), - fmt.Errorf("multiple as_path blocks with the same name %q", block.Name.ValueString()) + fmt.Errorf("multiple as_path blocks with the same name %q", name) } - asPathName[block.Name.ValueString()] = struct{}{} + asPathName[name] = struct{}{} + configSet = append(configSet, setPrefix+ "as-path \""+block.Name.ValueString()+"\""+ " \""+block.Path.ValueString()+"\"") diff --git a/internal/providerfwk/resource_policyoptions_policy_statement.go b/internal/providerfwk/resource_policyoptions_policy_statement.go index 73997c50..c8d8f825 100644 --- a/internal/providerfwk/resource_policyoptions_policy_statement.go +++ b/internal/providerfwk/resource_policyoptions_policy_statement.go @@ -1878,6 +1878,7 @@ func (rscData *policyoptionsPolicyStatementData) set( return path.Root("term").AtListIndex(i).AtName("name"), fmt.Errorf("term block %q is empty", name) } + setPrefixTerm := setPrefix + "term \"" + name + "\" " if block.From != nil { if block.From.isEmpty() { @@ -1943,6 +1944,7 @@ func (block *policyoptionsPolicyStatementBlockFrom) configSet( fmt.Errorf("multiple bgp_as_path_calc_length blocks with the same count %d in from block", count) } bgpASPathCalcLengthCount[count] = struct{}{} + configSet = append(configSet, setPrefix+"as-path-calc-length "+utils.ConvI64toa(count)+" "+v.Match.ValueString()) } @@ -1958,6 +1960,7 @@ func (block *policyoptionsPolicyStatementBlockFrom) configSet( fmt.Errorf("multiple bgp_as_path_unique_count blocks with the same count %d in from block", count) } bgpASPathUniqueCountCount[count] = struct{}{} + configSet = append(configSet, setPrefix+"as-path-unique-count "+utils.ConvI64toa(count)+" "+v.Match.ValueString()) } @@ -1973,6 +1976,7 @@ func (block *policyoptionsPolicyStatementBlockFrom) configSet( fmt.Errorf("multiple bgp_community_count blocks with the same count %d in from block", count) } bgpCommunityCountCount[count] = struct{}{} + configSet = append(configSet, setPrefix+"community-count "+utils.ConvI64toa(count)+" "+v.Match.ValueString()) } @@ -2029,6 +2033,7 @@ func (block *policyoptionsPolicyStatementBlockFrom) configSet( fmt.Errorf("multiple next_hop_weight blocks with the same argument values %q in from block", values) } nextHopWeightBlock[values] = struct{}{} + configSet = append(configSet, setPrefix+"nexthop-weight "+v.Match.ValueString()+" "+utils.ConvI64toa(v.Weight.ValueInt64())) } @@ -2057,6 +2062,7 @@ func (block *policyoptionsPolicyStatementBlockFrom) configSet( fmt.Errorf("multiple route_filter blocks with the same argument values %q in from block", values) } routeFilterBlock[values] = struct{}{} + setRoutFilter := setPrefix + "route-filter " + v.Route.ValueString() + " " + v.Option.ValueString() if v2 := v.OptionValue.ValueString(); v2 != "" { @@ -2175,6 +2181,7 @@ func (block *policyoptionsPolicyStatementBlockThen) configSet( fmt.Errorf("multiple community blocks with the same argument values %q in then block", values) } communityBlock[values] = struct{}{} + configSet = append(configSet, setPrefix+ "community "+v.Action.ValueString()+" \""+v.Value.ValueString()+"\"") } diff --git a/internal/providerfwk/resource_security_address_book.go b/internal/providerfwk/resource_security_address_book.go index 38de1ae1..c6c93d16 100644 --- a/internal/providerfwk/resource_security_address_book.go +++ b/internal/providerfwk/resource_security_address_book.go @@ -412,15 +412,15 @@ func (rsc *securityAddressBook) ValidateConfig( if block.Name.IsUnknown() { continue } - if _, ok := addressName[block.Name.ValueString()]; ok { + name := block.Name.ValueString() + if _, ok := addressName[name]; ok { resp.Diagnostics.AddAttributeError( path.Root("network_address"), tfdiag.DuplicateConfigErrSummary, - fmt.Sprintf("multiple addresses with the same name %q", block.Name.ValueString()), + fmt.Sprintf("multiple addresses with the same name %q", name), ) - } else { - addressName[block.Name.ValueString()] = struct{}{} } + addressName[name] = struct{}{} } } if !config.DNSName.IsNull() && !config.DNSName.IsUnknown() { @@ -443,15 +443,15 @@ func (rsc *securityAddressBook) ValidateConfig( if block.Name.IsUnknown() { continue } - if _, ok := addressName[block.Name.ValueString()]; ok { + name := block.Name.ValueString() + if _, ok := addressName[name]; ok { resp.Diagnostics.AddAttributeError( path.Root("dns_name"), tfdiag.DuplicateConfigErrSummary, - fmt.Sprintf("multiple addresses with the same name %q", block.Name.ValueString()), + fmt.Sprintf("multiple addresses with the same name %q", name), ) - } else { - addressName[block.Name.ValueString()] = struct{}{} } + addressName[name] = struct{}{} } } if !config.RangeAddress.IsNull() && !config.RangeAddress.IsUnknown() { @@ -466,15 +466,15 @@ func (rsc *securityAddressBook) ValidateConfig( if block.Name.IsUnknown() { continue } + name := block.Name.ValueString() if _, ok := addressName[block.Name.ValueString()]; ok { resp.Diagnostics.AddAttributeError( path.Root("range_address"), tfdiag.DuplicateConfigErrSummary, - fmt.Sprintf("multiple addresses with the same name %q", block.Name.ValueString()), + fmt.Sprintf("multiple addresses with the same name %q", name), ) - } else { - addressName[block.Name.ValueString()] = struct{}{} } + addressName[name] = struct{}{} } } if !config.WildcardAddress.IsNull() && !config.WildcardAddress.IsUnknown() { @@ -489,15 +489,15 @@ func (rsc *securityAddressBook) ValidateConfig( if block.Name.IsUnknown() { continue } - if _, ok := addressName[block.Name.ValueString()]; ok { + name := block.Name.ValueString() + if _, ok := addressName[name]; ok { resp.Diagnostics.AddAttributeError( path.Root("wildcard_address"), tfdiag.DuplicateConfigErrSummary, - fmt.Sprintf("multiple addresses with the same name %q", block.Name.ValueString()), + fmt.Sprintf("multiple addresses with the same name %q", name), ) - } else { - addressName[block.Name.ValueString()] = struct{}{} } + addressName[name] = struct{}{} } } if !config.AddressSet.IsNull() && !config.AddressSet.IsUnknown() { @@ -520,15 +520,15 @@ func (rsc *securityAddressBook) ValidateConfig( if block.Name.IsUnknown() { continue } - if _, ok := addressName[block.Name.ValueString()]; ok { + name := block.Name.ValueString() + if _, ok := addressName[name]; ok { resp.Diagnostics.AddAttributeError( path.Root("address_set"), tfdiag.DuplicateConfigErrSummary, - fmt.Sprintf("multiple addresses or address-sets with the same name %q", block.Name.ValueString()), + fmt.Sprintf("multiple addresses or address-sets with the same name %q", name), ) - } else { - addressName[block.Name.ValueString()] = struct{}{} } + addressName[name] = struct{}{} } } @@ -748,6 +748,7 @@ func (rscData *securityAddressBookData) set( fmt.Errorf("multiple addresses with the same name %q", name) } addressName[name] = struct{}{} + setPrefixAddr := setPrefix + "address " + name + " " configSet = append(configSet, setPrefixAddr+block.Value.ValueString()) if v := block.Description.ValueString(); v != "" { @@ -761,6 +762,7 @@ func (rscData *securityAddressBookData) set( fmt.Errorf("multiple addresses with the same name %q", name) } addressName[name] = struct{}{} + setPrefixAddr := setPrefix + "address " + name + " " configSet = append(configSet, setPrefixAddr+"dns-name "+block.Value.ValueString()) if block.IPv4Only.ValueBool() { @@ -780,6 +782,7 @@ func (rscData *securityAddressBookData) set( fmt.Errorf("multiple addresses with the same name %q", name) } addressName[name] = struct{}{} + setPrefixAddr := setPrefix + "address " + name + " " configSet = append(configSet, setPrefixAddr+"range-address "+block.From.ValueString()+" to "+block.To.ValueString()) if v := block.Description.ValueString(); v != "" { @@ -793,6 +796,7 @@ func (rscData *securityAddressBookData) set( fmt.Errorf("multiple addresses with the same name %q", name) } addressName[name] = struct{}{} + setPrefixAddr := setPrefix + "address " + name + " " configSet = append(configSet, setPrefixAddr+"wildcard-address "+block.Value.ValueString()) if v := block.Description.ValueString(); v != "" { @@ -806,6 +810,7 @@ func (rscData *securityAddressBookData) set( fmt.Errorf("multiple addresses or address-sets with the same name %q", name) } addressName[name] = struct{}{} + setPrefixAddrSet := setPrefix + "address-set " + name + " " if len(block.Address) == 0 && len(block.AddressSet) == 0 { return path.Root("address_set"), diff --git a/internal/providerfwk/resource_security_global_policy.go b/internal/providerfwk/resource_security_global_policy.go index 89500735..dc399b59 100644 --- a/internal/providerfwk/resource_security_global_policy.go +++ b/internal/providerfwk/resource_security_global_policy.go @@ -437,14 +437,15 @@ func (rsc *securityGlobalPolicy) ValidateConfig( policyName := make(map[string]struct{}) for i, block := range configPolicy { if !block.Name.IsUnknown() { - if _, ok := policyName[block.Name.ValueString()]; ok { + name := block.Name.ValueString() + if _, ok := policyName[name]; ok { resp.Diagnostics.AddAttributeError( path.Root("policy").AtListIndex(i).AtName("name"), tfdiag.DuplicateConfigErrSummary, - fmt.Sprintf("multiple policy blocks with the same name %q", block.Name.ValueString()), + fmt.Sprintf("multiple policy blocks with the same name %q", name), ) } - policyName[block.Name.ValueString()] = struct{}{} + policyName[name] = struct{}{} } if block.MatchApplication.IsNull() && block.MatchDynamicApplication.IsNull() { resp.Diagnostics.AddAttributeError( @@ -613,6 +614,7 @@ func (rscData *securityGlobalPolicyData) set( fmt.Errorf("multiple policy blocks with the same name %q", name) } policyName[name] = struct{}{} + setPrefixPolicy := setPrefix + name + " " for _, v := range block.MatchSourceAddress { configSet = append(configSet, setPrefixPolicy+"match source-address \""+v.ValueString()+"\"") diff --git a/internal/providerfwk/resource_security_ipsec_vpn.go b/internal/providerfwk/resource_security_ipsec_vpn.go index c0223f45..8cff07d2 100644 --- a/internal/providerfwk/resource_security_ipsec_vpn.go +++ b/internal/providerfwk/resource_security_ipsec_vpn.go @@ -629,15 +629,15 @@ func (rsc *securityIpsecVpn) ValidateConfig( if block.Name.IsUnknown() { continue } - if _, ok := names[block.Name.ValueString()]; ok { + name := block.Name.ValueString() + if _, ok := names[name]; ok { resp.Diagnostics.AddAttributeError( path.Root("traffic_selector").AtListIndex(i).AtName("name"), tfdiag.DuplicateConfigErrSummary, - fmt.Sprintf("multiple traffic_selector blocks with the same name %q", block.Name.ValueString()), + fmt.Sprintf("multiple traffic_selector blocks with the same name %q", name), ) - } else { - names[block.Name.ValueString()] = struct{}{} } + names[name] = struct{}{} } } if !config.MultiSaForwardingClass.IsNull() && !config.MultiSaForwardingClass.IsUnknown() && @@ -970,11 +970,13 @@ func (rscData *securityIpsecVpnData) set( } trafficSelectorNames := make(map[string]struct{}) for i, block := range rscData.TrafficSelector { - if _, ok := trafficSelectorNames[block.Name.ValueString()]; ok { + name := block.Name.ValueString() + if _, ok := trafficSelectorNames[name]; ok { return path.Root("traffic_selector").AtListIndex(i).AtName("name"), - fmt.Errorf("multiple traffic_selector blocks with the same name %q", block.Name.ValueString()) + fmt.Errorf("multiple traffic_selector blocks with the same name %q", name) } - trafficSelectorNames[block.Name.ValueString()] = struct{}{} + trafficSelectorNames[name] = struct{}{} + configSet = append(configSet, setPrefix+"traffic-selector \""+block.Name.ValueString()+"\" local-ip "+block.LocalIP.ValueString()) configSet = append(configSet, diff --git a/internal/providerfwk/resource_security_nat_destination.go b/internal/providerfwk/resource_security_nat_destination.go index 9facf37b..3962e599 100644 --- a/internal/providerfwk/resource_security_nat_destination.go +++ b/internal/providerfwk/resource_security_nat_destination.go @@ -581,6 +581,7 @@ func (rscData *securityNatDestinationData) set( fmt.Errorf("multiple rule blocks with the same name %q", name) } ruleName[name] = struct{}{} + if block.DestinationAddress.IsNull() && block.DestinationAddressName.IsNull() { return path.Root("rule").AtListIndex(i).AtName("destination_address"), diff --git a/internal/providerfwk/resource_security_nat_source.go b/internal/providerfwk/resource_security_nat_source.go index 5ab7eaf5..dedfb9c7 100644 --- a/internal/providerfwk/resource_security_nat_source.go +++ b/internal/providerfwk/resource_security_nat_source.go @@ -680,7 +680,6 @@ func (rscData *securityNatSourceData) set( ruleName[name] = struct{}{} setPrefixRule := setPrefix + " rule " + name + " " - if block.Match != nil { if block.Match.isEmpty() { return path.Root("rule").AtListIndex(i).AtName("match"), diff --git a/internal/providerfwk/resource_security_policy.go b/internal/providerfwk/resource_security_policy.go index 6d9c24aa..4c1debb4 100644 --- a/internal/providerfwk/resource_security_policy.go +++ b/internal/providerfwk/resource_security_policy.go @@ -474,14 +474,15 @@ func (rsc *securityPolicy) ValidateConfig( policyName := make(map[string]struct{}) for i, block := range configPolicy { if !block.Name.IsUnknown() { - if _, ok := policyName[block.Name.ValueString()]; ok { + name := block.Name.ValueString() + if _, ok := policyName[name]; ok { resp.Diagnostics.AddAttributeError( path.Root("policy").AtListIndex(i).AtName("name"), tfdiag.DuplicateConfigErrSummary, - fmt.Sprintf("multiple policy blocks with the same name %q", block.Name.ValueString()), + fmt.Sprintf("multiple policy blocks with the same name %q", name), ) } - policyName[block.Name.ValueString()] = struct{}{} + policyName[name] = struct{}{} } if block.MatchApplication.IsNull() && block.MatchDynamicApplication.IsNull() { resp.Diagnostics.AddAttributeError( @@ -803,6 +804,7 @@ func (rscData *securityPolicyData) set( fmt.Errorf("multiple policy blocks with the same name %q", name) } policyName[name] = struct{}{} + setPrefixPolicy := setPrefix + name + " " for _, v := range block.MatchSourceAddress { configSet = append(configSet, setPrefixPolicy+"match source-address \""+v.ValueString()+"\"") diff --git a/internal/providerfwk/resource_security_zone.go b/internal/providerfwk/resource_security_zone.go index 28228a30..f8d45f8b 100644 --- a/internal/providerfwk/resource_security_zone.go +++ b/internal/providerfwk/resource_security_zone.go @@ -492,15 +492,15 @@ func (rsc *securityZone) ValidateConfig( if block.Name.IsUnknown() { continue } - if _, ok := addressName[block.Name.ValueString()]; ok { + name := block.Name.ValueString() + if _, ok := addressName[name]; ok { resp.Diagnostics.AddAttributeError( path.Root("address_book"), tfdiag.DuplicateConfigErrSummary, - fmt.Sprintf("multiple addresses with the same name %q", block.Name.ValueString()), + fmt.Sprintf("multiple addresses with the same name %q", name), ) - } else { - addressName[block.Name.ValueString()] = struct{}{} } + addressName[name] = struct{}{} } } if !config.AddressBookDNS.IsNull() && !config.AddressBookDNS.IsUnknown() { @@ -523,15 +523,15 @@ func (rsc *securityZone) ValidateConfig( if block.Name.IsUnknown() { continue } - if _, ok := addressName[block.Name.ValueString()]; ok { + name := block.Name.ValueString() + if _, ok := addressName[name]; ok { resp.Diagnostics.AddAttributeError( path.Root("address_book_dns"), tfdiag.DuplicateConfigErrSummary, - fmt.Sprintf("multiple addresses with the same name %q", block.Name.ValueString()), + fmt.Sprintf("multiple addresses with the same name %q", name), ) - } else { - addressName[block.Name.ValueString()] = struct{}{} } + addressName[name] = struct{}{} } } if !config.AddressBookRange.IsNull() && !config.AddressBookRange.IsUnknown() { @@ -546,15 +546,15 @@ func (rsc *securityZone) ValidateConfig( if block.Name.IsUnknown() { continue } - if _, ok := addressName[block.Name.ValueString()]; ok { + name := block.Name.ValueString() + if _, ok := addressName[name]; ok { resp.Diagnostics.AddAttributeError( path.Root("address_book_range"), tfdiag.DuplicateConfigErrSummary, - fmt.Sprintf("multiple addresses with the same name %q", block.Name.ValueString()), + fmt.Sprintf("multiple addresses with the same name %q", name), ) - } else { - addressName[block.Name.ValueString()] = struct{}{} } + addressName[name] = struct{}{} } } if !config.AddressBookSet.IsNull() && !config.AddressBookSet.IsUnknown() { @@ -577,15 +577,15 @@ func (rsc *securityZone) ValidateConfig( if block.Name.IsUnknown() { continue } - if _, ok := addressName[block.Name.ValueString()]; ok { + name := block.Name.ValueString() + if _, ok := addressName[name]; ok { resp.Diagnostics.AddAttributeError( path.Root("address_book_set"), tfdiag.DuplicateConfigErrSummary, - fmt.Sprintf("multiple addresses or address-sets with the same name %q", block.Name.ValueString()), + fmt.Sprintf("multiple addresses or address-sets with the same name %q", name), ) - } else { - addressName[block.Name.ValueString()] = struct{}{} } + addressName[name] = struct{}{} } } if !config.AddressBookWildcard.IsNull() && !config.AddressBookWildcard.IsUnknown() { @@ -600,15 +600,15 @@ func (rsc *securityZone) ValidateConfig( if block.Name.IsUnknown() { continue } - if _, ok := addressName[block.Name.ValueString()]; ok { + name := block.Name.ValueString() + if _, ok := addressName[name]; ok { resp.Diagnostics.AddAttributeError( path.Root("address_book_wildcard"), tfdiag.DuplicateConfigErrSummary, - fmt.Sprintf("multiple addresses with the same name %q", block.Name.ValueString()), + fmt.Sprintf("multiple addresses with the same name %q", name), ) - } else { - addressName[block.Name.ValueString()] = struct{}{} } + addressName[name] = struct{}{} } } } @@ -883,6 +883,7 @@ func (rscData *securityZoneData) set( fmt.Errorf("multiple addresses with the same name %q", name) } addressName[name] = struct{}{} + configSet = append(configSet, setPrefix+"address-book address "+name+" "+block.Network.ValueString()) if v := block.Description.ValueString(); v != "" { configSet = append(configSet, setPrefix+"address-book address "+name+" description \""+v+"\"") @@ -895,6 +896,7 @@ func (rscData *securityZoneData) set( fmt.Errorf("multiple addresses with the same name %q", name) } addressName[name] = struct{}{} + setLine := setPrefix + "address-book address " + name + " dns-name " + block.FQDN.ValueString() configSet = append(configSet, setLine) if block.IPv4Only.ValueBool() { @@ -914,6 +916,7 @@ func (rscData *securityZoneData) set( fmt.Errorf("multiple addresses with the same name %q", name) } addressName[name] = struct{}{} + configSet = append(configSet, setPrefix+"address-book address "+ name+" range-address "+block.From.ValueString()+ " to "+block.To.ValueString()) @@ -928,6 +931,7 @@ func (rscData *securityZoneData) set( fmt.Errorf("multiple addresses or address-sets with the same name %q", name) } addressName[name] = struct{}{} + if len(block.Address) == 0 && len(block.AddressSet) == 0 { return path.Root("address_book_set"), @@ -950,6 +954,7 @@ func (rscData *securityZoneData) set( fmt.Errorf("multiple addresses with the same name %q", name) } addressName[name] = struct{}{} + configSet = append(configSet, setPrefix+"address-book address "+ name+" wildcard-address "+block.Network.ValueString()) if v := block.Description.ValueString(); v != "" { diff --git a/internal/providerfwk/resource_snmp_community.go b/internal/providerfwk/resource_snmp_community.go index c5936740..cfeda98e 100644 --- a/internal/providerfwk/resource_snmp_community.go +++ b/internal/providerfwk/resource_snmp_community.go @@ -483,6 +483,7 @@ func (rscData *snmpCommunityData) set( fmt.Errorf("multiple routing_instance blocks with the same name %q", name) } routingInstanceName[name] = struct{}{} + configSet = append(configSet, setPrefix+"routing-instance "+name) if v := block.ClientListName.ValueString(); v != "" { configSet = append(configSet, setPrefix+"routing-instance "+name+" client-list-name \""+v+"\"") diff --git a/internal/providerfwk/resource_snmp_v3_vacm_accessgroup.go b/internal/providerfwk/resource_snmp_v3_vacm_accessgroup.go index 418a16e3..7d1b87ee 100644 --- a/internal/providerfwk/resource_snmp_v3_vacm_accessgroup.go +++ b/internal/providerfwk/resource_snmp_v3_vacm_accessgroup.go @@ -580,6 +580,7 @@ func (rscData *snmpV3VacmAccessgroupData) set( return path.Root("default_context_prefix"), fmt.Errorf("default_context_prefix block model:%q level:%q is empty", model, level) } + setPrefixBlock := setPrefix + "default-context-prefix security-model " + model + " security-level " + level + " " if v := block.ContextMatch.ValueString(); v != "" { configSet = append(configSet, setPrefixBlock+"context-match "+v) @@ -602,6 +603,7 @@ func (rscData *snmpV3VacmAccessgroupData) set( fmt.Errorf("multiple context_prefix blocks with the same prefix %q", prefix) } contextPrefixPrefix[prefix] = struct{}{} + accessConfigModelLevel := make(map[string]struct{}) for _, blockAccessConfig := range block.AccessConfig { model := blockAccessConfig.Model.ValueString() @@ -617,6 +619,7 @@ func (rscData *snmpV3VacmAccessgroupData) set( fmt.Errorf("access_config block model:%q level:%q is empty"+ " in context_prefix block %q", model, level, prefix) } + setPrefixBlock := setPrefix + " context-prefix \"" + prefix + "\" " + "security-model " + model + " security-level " + level + " " if v := blockAccessConfig.ContextMatch.ValueString(); v != "" { diff --git a/internal/providerfwk/resource_static_route.go b/internal/providerfwk/resource_static_route.go index 87ef3e64..54af5d87 100644 --- a/internal/providerfwk/resource_static_route.go +++ b/internal/providerfwk/resource_static_route.go @@ -605,15 +605,16 @@ func (rsc *staticRoute) ValidateConfig( if block.NextHop.IsUnknown() { continue } - if _, ok := qualifiedNextHopNextHop[block.NextHop.ValueString()]; ok { + nextHop := block.NextHop.ValueString() + if _, ok := qualifiedNextHopNextHop[nextHop]; ok { resp.Diagnostics.AddAttributeError( path.Root("qualified_next_hop").AtListIndex(i).AtName("next_hop"), tfdiag.DuplicateConfigErrSummary, fmt.Sprintf("multiple qualified_next_hop blocks with the same next_hop %q", - block.NextHop.ValueString()), + nextHop), ) } - qualifiedNextHopNextHop[block.NextHop.ValueString()] = struct{}{} + qualifiedNextHopNextHop[nextHop] = struct{}{} } } } diff --git a/internal/providerfwk/resource_system.go b/internal/providerfwk/resource_system.go index 152ed146..3c7084d7 100644 --- a/internal/providerfwk/resource_system.go +++ b/internal/providerfwk/resource_system.go @@ -2363,15 +2363,16 @@ func (rsc *system) ValidateConfig( if block.Address.IsUnknown() { continue } - if _, ok := destinationRadiusServerAddress[block.Address.ValueString()]; ok { + address := block.Address.ValueString() + if _, ok := destinationRadiusServerAddress[address]; ok { resp.Diagnostics.AddAttributeError( path.Root("accounting").AtName("destination_radius_server").AtListIndex(i).AtName("address"), tfdiag.DuplicateConfigErrSummary, - fmt.Sprintf("multiple destination_radius_server blocks with the same address %q in accounting block", - block.Address.ValueString()), + fmt.Sprintf("multiple destination_radius_server blocks with the same address %q"+ + " in accounting block", address), ) } - destinationRadiusServerAddress[block.Address.ValueString()] = struct{}{} + destinationRadiusServerAddress[address] = struct{}{} } } } @@ -2397,15 +2398,16 @@ func (rsc *system) ValidateConfig( if block.Address.IsUnknown() { continue } - if _, ok := destinationTacplusServerAddress[block.Address.ValueString()]; ok { + address := block.Address.ValueString() + if _, ok := destinationTacplusServerAddress[address]; ok { resp.Diagnostics.AddAttributeError( path.Root("accounting").AtName("destination_tacplus_server").AtListIndex(i).AtName("address"), tfdiag.DuplicateConfigErrSummary, - fmt.Sprintf("multiple destination_tacplus_server blocks with the same address %q in accounting block", - block.Address.ValueString()), + fmt.Sprintf("multiple destination_tacplus_server blocks with the same address %q"+ + " in accounting block", address), ) } - destinationTacplusServerAddress[block.Address.ValueString()] = struct{}{} + destinationTacplusServerAddress[address] = struct{}{} } } } @@ -2436,9 +2438,8 @@ func (rsc *system) ValidateConfig( fmt.Sprintf("multiple archive_site blocks with the same url %q"+ " in archival_configuration block", url), ) - } else { - archiveSiteURL[url] = struct{}{} } + archiveSiteURL[url] = struct{}{} } } } diff --git a/internal/providerfwk/resource_system_syslog_file.go b/internal/providerfwk/resource_system_syslog_file.go index 8ef94a8a..d46e5946 100644 --- a/internal/providerfwk/resource_system_syslog_file.go +++ b/internal/providerfwk/resource_system_syslog_file.go @@ -515,9 +515,8 @@ func (rsc *systemSyslogFile) ValidateConfig( tfdiag.DuplicateConfigErrSummary, fmt.Sprintf("multiple sites blocks with the same url %q in archive block", url), ) - } else { - sitesURL[url] = struct{}{} } + sitesURL[url] = struct{}{} } } } diff --git a/internal/providerfwk/resource_virtual_chassis.go b/internal/providerfwk/resource_virtual_chassis.go index d0213376..c4085f49 100644 --- a/internal/providerfwk/resource_virtual_chassis.go +++ b/internal/providerfwk/resource_virtual_chassis.go @@ -427,25 +427,25 @@ func (rsc *virtualChassis) ValidateConfig( continue } - if _, ok := aliasSerialNumber[block.SerialNumber.ValueString()]; ok { + serialNumber := block.SerialNumber.ValueString() + if _, ok := aliasSerialNumber[serialNumber]; ok { resp.Diagnostics.AddAttributeError( path.Root("alias"), tfdiag.DuplicateConfigErrSummary, - fmt.Sprintf("multiple alias blocks with the same serial_number %q", - block.SerialNumber.ValueString()), + fmt.Sprintf("multiple alias blocks with the same serial_number %q", serialNumber), ) } - aliasSerialNumber[block.AliasName.ValueString()] = struct{}{} + aliasSerialNumber[serialNumber] = struct{}{} - if _, ok := aliasAliasName[block.AliasName.ValueString()]; ok { + aliasName := block.AliasName.ValueString() + if _, ok := aliasAliasName[aliasName]; ok { resp.Diagnostics.AddAttributeError( path.Root("alias"), tfdiag.DuplicateConfigErrSummary, - fmt.Sprintf("multiple alias blocks with the same alias_name %q", - block.AliasName.ValueString()), + fmt.Sprintf("multiple alias blocks with the same alias_name %q", aliasName), ) } - aliasAliasName[block.AliasName.ValueString()] = struct{}{} + aliasAliasName[aliasName] = struct{}{} } } if !config.Member.IsNull() && !config.Member.IsUnknown() { @@ -460,15 +460,15 @@ func (rsc *virtualChassis) ValidateConfig( memberID := make(map[int64]struct{}) for i, block := range configMember { if !block.ID.IsUnknown() { - if _, ok := memberID[block.ID.ValueInt64()]; ok { + id := block.ID.ValueInt64() + if _, ok := memberID[id]; ok { resp.Diagnostics.AddAttributeError( path.Root("member").AtListIndex(i).AtName("id"), tfdiag.DuplicateConfigErrSummary, - fmt.Sprintf("multiple member blocks with the same id %d", - block.ID.ValueInt64()), + fmt.Sprintf("multiple member blocks with the same id %d", id), ) } - memberID[block.ID.ValueInt64()] = struct{}{} + memberID[id] = struct{}{} } if block.isEmpty() { resp.Diagnostics.AddAttributeError( @@ -639,14 +639,13 @@ func (rscData *virtualChassisData) set( aliasAliasName := make(map[string]struct{}) for _, block := range rscData.Alias { serialNumber := block.SerialNumber.ValueString() - aliasName := block.AliasName.ValueString() - if _, ok := aliasSerialNumber[serialNumber]; ok { return path.Root("alias"), fmt.Errorf("multiple alias blocks with the same serial_number %q", serialNumber) } aliasSerialNumber[serialNumber] = struct{}{} + aliasName := block.AliasName.ValueString() if _, ok := aliasAliasName[aliasName]; ok { return path.Root("alias"), fmt.Errorf("multiple alias blocks with the same alias_name %q", aliasName) From 8b56470b1dc56d6bd1507e11f19de4abec285415 Mon Sep 17 00:00:00 2001 From: Jeremy Muriel Date: Tue, 9 Apr 2024 09:18:52 +0200 Subject: [PATCH 13/25] r/evpn: add no_core_isolation argument Fix #644 --- .changes/issue-644.md | 8 +++++++ docs/resources/evpn.md | 3 +++ internal/providerfwk/resource_evpn.go | 24 +++++++++++++++++++ .../TestAccResourceEvpn_basic/1/main.tf | 3 ++- 4 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 .changes/issue-644.md diff --git a/.changes/issue-644.md b/.changes/issue-644.md new file mode 100644 index 00000000..5cc537cc --- /dev/null +++ b/.changes/issue-644.md @@ -0,0 +1,8 @@ + +FEATURES: + +ENHANCEMENTS: + +* **resource/junos_evpn**: add `no_core_isolation` argument (Fix [#644](https://github.com/jeremmfr/terraform-provider-junos/issues/644)) + +BUG FIXES: diff --git a/docs/resources/evpn.md b/docs/resources/evpn.md index 640cd771..8d5c8612 100644 --- a/docs/resources/evpn.md +++ b/docs/resources/evpn.md @@ -51,6 +51,9 @@ The following arguments are supported: Time window for detection of duplicate MACs (5..600 seconds). - **multicast_mode** (Optional, String) Multicast mode for EVPN. +- **no_core_isolation** (Optional, Boolean) + Disable EVPN Core isolation. + `routing_instance` need to be `default`. - **switch_or_ri_options** (Optional, Block, Forces new resource) Declare `switch-options` or `routing-instance` configuration. Need to be set if `routing_instance` = `default` or `routing_instance_evpn` = true. diff --git a/internal/providerfwk/resource_evpn.go b/internal/providerfwk/resource_evpn.go index 397f4ac2..387bdddb 100644 --- a/internal/providerfwk/resource_evpn.go +++ b/internal/providerfwk/resource_evpn.go @@ -129,6 +129,13 @@ func (rsc *evpn) Schema( stringvalidator.OneOf("ingress-replication"), }, }, + "no_core_isolation": schema.BoolAttribute{ + Optional: true, + Description: "Disable EVPN Core isolation.", + Validators: []validator.Bool{ + tfvalidator.BoolTrue(), + }, + }, "routing_instance_evpn": schema.BoolAttribute{ Optional: true, Description: "Configure routing instance is an evpn instance-type.", @@ -257,6 +264,7 @@ type evpnData struct { Encapsulation types.String `tfsdk:"encapsulation"` DefaultGateway types.String `tfsdk:"default_gateway"` MulticastMode types.String `tfsdk:"multicast_mode"` + NoCoreIsolation types.Bool `tfsdk:"no_core_isolation"` RoutingInstanceEvpn types.Bool `tfsdk:"routing_instance_evpn"` DuplicateMacDetection *evpnBlockDuplicateMACDetection `tfsdk:"duplicate_mac_detection"` SwitchOrRIOptions *evpnBlockSwitchOrRIOptions `tfsdk:"switch_or_ri_options"` @@ -268,6 +276,7 @@ type evpnConfig struct { Encapsulation types.String `tfsdk:"encapsulation"` DefaultGateway types.String `tfsdk:"default_gateway"` MulticastMode types.String `tfsdk:"multicast_mode"` + NoCoreIsolation types.Bool `tfsdk:"no_core_isolation"` RoutingInstanceEvpn types.Bool `tfsdk:"routing_instance_evpn"` DuplicateMacDetection *evpnBlockDuplicateMACDetection `tfsdk:"duplicate_mac_detection"` SwitchOrRIOptions *evpnBlockSwitchOrRIOptionsConfig `tfsdk:"switch_or_ri_options"` @@ -336,6 +345,15 @@ func (rsc *evpn) ValidateConfig( ) } } + if !config.RoutingInstance.IsNull() && !config.RoutingInstance.IsUnknown() && + config.RoutingInstance.ValueString() != junos.DefaultW && + !config.NoCoreIsolation.IsNull() && !config.NoCoreIsolation.IsUnknown() { + resp.Diagnostics.AddAttributeError( + path.Root("no_core_isolation"), + tfdiag.ConflictConfigErrSummary, + fmt.Sprintf("no_core_isolation cannot be configured when routing_instance != %q", junos.DefaultW), + ) + } if config.DuplicateMacDetection != nil { if config.DuplicateMacDetection.isEmpty() { resp.Diagnostics.AddAttributeError( @@ -637,6 +655,9 @@ func (rscData *evpnData) set( if v := rscData.MulticastMode.ValueString(); v != "" { configSet = append(configSet, setPrefix+"multicast-mode "+v) } + if rscData.NoCoreIsolation.ValueBool() { + configSet = append(configSet, setPrefix+"no-core-isolation") + } if rscData.SwitchOrRIOptions != nil { configSet = append(configSet, setSwitchRIPrefix+"route-distinguisher "+rscData.SwitchOrRIOptions.RouteDistinguisher.ValueString()) @@ -722,6 +743,8 @@ func (rscData *evpnData) read( rscData.Encapsulation = types.StringValue(itemTrim) case balt.CutPrefixInString(&itemTrim, "multicast-mode "): rscData.MulticastMode = types.StringValue(itemTrim) + case itemTrim == "no-core-isolation": + rscData.NoCoreIsolation = types.BoolValue(true) } } } @@ -790,6 +813,7 @@ func (rscData *evpnData) delOpts( delPrefix + "duplicate-mac-detection", delPrefix + "encapsulation", delPrefix + "multicast-mode", + delPrefix + "no-core-isolation", } if rscData.RoutingInstanceEvpn.ValueBool() { diff --git a/internal/providerfwk/testdata/TestAccResourceEvpn_basic/1/main.tf b/internal/providerfwk/testdata/TestAccResourceEvpn_basic/1/main.tf index 10db8e49..cd94efec 100644 --- a/internal/providerfwk/testdata/TestAccResourceEvpn_basic/1/main.tf +++ b/internal/providerfwk/testdata/TestAccResourceEvpn_basic/1/main.tf @@ -41,7 +41,8 @@ resource "junos_evpn" "testacc_evpn_default" { depends_on = [ junos_switch_options.testacc_evpn, ] - encapsulation = "vxlan" + encapsulation = "vxlan" + no_core_isolation = true switch_or_ri_options { route_distinguisher = "20:1" vrf_target = "target:20:2" From d87d77b41ca48f17298e61992a54e431bc7cccd0 Mon Sep 17 00:00:00 2001 From: Jeremy Muriel Date: Fri, 12 Apr 2024 20:26:56 +0200 Subject: [PATCH 14/25] r/vlan: use new provider via framework - community_vlans argument is now a Set of String to accept VLAN name in addition to VLAN id - isolated_vlan argument is now a String to accept VLAN name in addition to VLAN id - vlan_id argument is now a String to accept `all` or `none` in addition to VLAN id --- .changes/issue-646.md | 22 + docs/resources/vlan.md | 36 +- internal/providerfwk/provider.go | 1 + internal/providerfwk/resource_vlan.go | 714 ++++++++++++++++++ internal/providerfwk/resource_vlan_test.go | 61 ++ .../TestAccResourceVlan_basic/1/main.tf | 29 + .../TestAccResourceVlan_basic/2/main.tf | 6 + .../TestAccResourceVlan_basic/4/main.tf | 32 + .../TestAccResourceVlan_basic/5/main.tf | 67 ++ .../1/main.tf | 54 ++ .../1/provider.tf | 10 + .../2/main.tf | 1 + internal/providerfwk/upgradestate_vlan.go | 163 ++++ .../providerfwk/upgradestate_vlan_test.go | 29 + internal/providersdk/provider.go | 2 - internal/providersdk/resource_vlan.go | 605 --------------- internal/providersdk/resource_vlan_test.go | 109 --- 17 files changed, 1207 insertions(+), 734 deletions(-) create mode 100644 .changes/issue-646.md create mode 100644 internal/providerfwk/resource_vlan.go create mode 100644 internal/providerfwk/resource_vlan_test.go create mode 100644 internal/providerfwk/testdata/TestAccResourceVlan_basic/1/main.tf create mode 100644 internal/providerfwk/testdata/TestAccResourceVlan_basic/2/main.tf create mode 100644 internal/providerfwk/testdata/TestAccResourceVlan_basic/4/main.tf create mode 100644 internal/providerfwk/testdata/TestAccResourceVlan_basic/5/main.tf create mode 100644 internal/providerfwk/testdata/TestAccUpgradeStateResourceVlan_V0toV1_basic/1/main.tf create mode 100644 internal/providerfwk/testdata/TestAccUpgradeStateResourceVlan_V0toV1_basic/1/provider.tf create mode 120000 internal/providerfwk/testdata/TestAccUpgradeStateResourceVlan_V0toV1_basic/2/main.tf create mode 100644 internal/providerfwk/upgradestate_vlan.go create mode 100644 internal/providerfwk/upgradestate_vlan_test.go delete mode 100644 internal/providersdk/resource_vlan.go delete mode 100644 internal/providersdk/resource_vlan_test.go diff --git a/.changes/issue-646.md b/.changes/issue-646.md new file mode 100644 index 00000000..9924e4e0 --- /dev/null +++ b/.changes/issue-646.md @@ -0,0 +1,22 @@ + +FEATURES: + +ENHANCEMENTS: + +* **resource/junos_vlan**: + * resource now use new [terraform-plugin-framework](https://github.com/hashicorp/terraform-plugin-framework) + some of config errors are now sent during Plan instead of during Apply + optional boolean attributes doesn't accept value *false* + optional string attributes doesn't accept *empty* value + the resource schema has been upgraded to have one-blocks in single mode instead of list + * `community_vlans` argument is now a Set of String (instead of Set of Number) to accept VLAN name in addition to VLAN id + data in the state has been updated for the new format + Number in config is automatically converted to String by Terraform + * `isolated_vlan` argument is now a String (instead of Number) to accept VLAN name in addition to VLAN id + data in the state has been updated for the new format + Number in config is automatically converted to String by Terraform + * `vlan_id` argument is now a String (instead of Number) to accept `all` or `none` in addition to VLAN id + data in the state has been updated for the new format + Number in config is automatically converted to String by Terraform + +BUG FIXES: diff --git a/docs/resources/vlan.md b/docs/resources/vlan.md index 468de5d2..3e46bc3a 100644 --- a/docs/resources/vlan.md +++ b/docs/resources/vlan.md @@ -22,36 +22,36 @@ resource "junos_vlan" "blue" { The following arguments are supported: - **name** (Required, String, Forces new resource) - The name of vlan. -- **community_vlans** (Optional, Set of Number) - List of ID community vlan for primary vlan (when Junos device supports it). + The name of VLAN. +- **community_vlans** (Optional, Set of String) + List of VLAN id or name of community vlans for primary vlan. - **description** (Optional, String) - A description for vlan. + Text description of VLAN. - **forward_filter_input** (Optional, String) - Input filter to apply for forwarded packets (when Junos device supports it). + Input filter to apply for forwarded packets. - **forward_filter_output** (Optional, String) - Output filter to apply for forwarded packets (when Junos device supports it). + Output filter to apply for forwarded packets. - **forward_flood_input** (Optional, String) - Input filter to apply for ethernet switching flood packets (when Junos device supports it). + Input filter to apply for ethernet switching flood packets. +- **isolated_vlan** (Optional, String) + VLAN id or name of isolated vlan for primary vlan. - **l3_interface** (Optional, String) - L3 interface name for this vlans. + L3 interface name for this VLAN. Must be start with `irb.` or `vlan.`. -- **isolated-vlan** (Optional, Number) - Declare ID isolated vlan for primary vlan (when Junos device supports it). - **private_vlan** (Optional, String) - Type of secondary vlan for private vlan (when Junos device supports it). + Type of secondary VLAN for private vlan. Must be `community` or `isolated`. - **service_id** (Optional, Number) - Service id (when Junos device supports it). -- **vlan_id** (Optional, Number) - 802.1q VLAN identifier. + Service id. +- **vlan_id** (Optional, String) + 802.1q VLAN id or `all` or `none`. Conflict with `vlan_id_list`. - **vlan_id_list** (Optional, Set of String) - List of vlan ID. - Can be an ID or range (exemple: 10-20). + List of 802.1q VLAN id. + Can be a VLAN id or range of VLAN id (example: 10-20). Conflict with `vlan_id`. - **vxlan** (Optional, Block) - Declare vxlan configuration (when Junos device supports it). + Declare vxlan configuration. - **vni** (Required, Number) VXLAN identifier (0..16777214). - **encapsulate_inner_vlan** (Optional, Boolean) @@ -59,7 +59,7 @@ The following arguments are supported: - **ingress_node_replication** (Optional, Boolean) Enable ingress node replication. - **multicast_group** (Optional, String) - CIDR for Multicast group registered for VXLAN segment. + Multicast group registered for VXLAN segment. - **ovsdb_managed** (Optional, Boolean) Bridge-domain is managed remotely via VXLAN OVSDB Controller. - **vni_extend_evpn** (Optional, Boolean) diff --git a/internal/providerfwk/provider.go b/internal/providerfwk/provider.go index ff05f24e..6de89589 100644 --- a/internal/providerfwk/provider.go +++ b/internal/providerfwk/provider.go @@ -299,6 +299,7 @@ func (p *junosProvider) Resources(_ context.Context) []func() resource.Resource newSystemSyslogUserResource, newSystemTacplusServerResource, newVirtualChassisResource, + newVlanResource, } } diff --git a/internal/providerfwk/resource_vlan.go b/internal/providerfwk/resource_vlan.go new file mode 100644 index 00000000..a5b649c1 --- /dev/null +++ b/internal/providerfwk/resource_vlan.go @@ -0,0 +1,714 @@ +package providerfwk + +import ( + "context" + "regexp" + "strings" + + "github.com/jeremmfr/terraform-provider-junos/internal/junos" + "github.com/jeremmfr/terraform-provider-junos/internal/tfdata" + "github.com/jeremmfr/terraform-provider-junos/internal/tfdiag" + "github.com/jeremmfr/terraform-provider-junos/internal/tfplanmodifier" + "github.com/jeremmfr/terraform-provider-junos/internal/tfvalidator" + "github.com/jeremmfr/terraform-provider-junos/internal/utils" + + "github.com/hashicorp/terraform-plugin-framework-validators/int64validator" + "github.com/hashicorp/terraform-plugin-framework-validators/setvalidator" + "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" + balt "github.com/jeremmfr/go-utils/basicalter" +) + +// Ensure the implementation satisfies the expected interfaces. +var ( + _ resource.Resource = &vlan{} + _ resource.ResourceWithConfigure = &vlan{} + _ resource.ResourceWithValidateConfig = &vlan{} + _ resource.ResourceWithImportState = &vlan{} + _ resource.ResourceWithUpgradeState = &vlan{} +) + +type vlan struct { + client *junos.Client +} + +func newVlanResource() resource.Resource { + return &vlan{} +} + +func (rsc *vlan) typeName() string { + return providerName + "_vlan" +} + +func (rsc *vlan) junosName() string { + return "vlans" +} + +func (rsc *vlan) junosClient() *junos.Client { + return rsc.client +} + +func (rsc *vlan) Metadata( + _ context.Context, _ resource.MetadataRequest, resp *resource.MetadataResponse, +) { + resp.TypeName = rsc.typeName() +} + +func (rsc *vlan) Configure( + ctx context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse, +) { + // Prevent panic if the provider has not been configured. + if req.ProviderData == nil { + return + } + client, ok := req.ProviderData.(*junos.Client) + if !ok { + unexpectedResourceConfigureType(ctx, req, resp) + + return + } + rsc.client = client +} + +func (rsc *vlan) Schema( + _ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse, +) { + resp.Schema = schema.Schema{ + Version: 1, + Description: defaultResourceSchemaDescription(rsc), + Attributes: map[string]schema.Attribute{ + "id": schema.StringAttribute{ + Computed: true, + Description: "An identifier for the resource with format ``.", + PlanModifiers: []planmodifier.String{ + stringplanmodifier.UseStateForUnknown(), + }, + }, + "name": schema.StringAttribute{ + Required: true, + Description: "The name of VLAN.", + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + }, + Validators: []validator.String{ + stringvalidator.LengthBetween(2, 64), + tfvalidator.StringFormat(tfvalidator.DefaultFormat), + }, + }, + "community_vlans": schema.SetAttribute{ + ElementType: types.StringType, + Optional: true, + Description: "List of VLAN id or name of community vlans for primary vlan.", + Validators: []validator.Set{ + setvalidator.SizeAtLeast(1), + setvalidator.ValueStringsAre( + stringvalidator.LengthBetween(1, 64), + tfvalidator.StringFormat(tfvalidator.DefaultFormat), + ), + }, + }, + "description": schema.StringAttribute{ + Optional: true, + Description: "Text description of VLAN.", + Validators: []validator.String{ + stringvalidator.LengthBetween(1, 900), + tfvalidator.StringDoubleQuoteExclusion(), + }, + }, + "forward_filter_input": schema.StringAttribute{ + Optional: true, + Description: "Input filter to apply for forwarded packets.", + Validators: []validator.String{ + stringvalidator.LengthBetween(1, 63), + tfvalidator.StringDoubleQuoteExclusion(), + }, + }, + "forward_filter_output": schema.StringAttribute{ + Optional: true, + Description: "Output filter to apply for forwarded packets.", + Validators: []validator.String{ + stringvalidator.LengthBetween(1, 63), + tfvalidator.StringDoubleQuoteExclusion(), + }, + }, + "forward_flood_input": schema.StringAttribute{ + Optional: true, + Description: "Input filter to apply for ethernet switching flood packets.", + Validators: []validator.String{ + stringvalidator.LengthBetween(1, 63), + tfvalidator.StringDoubleQuoteExclusion(), + }, + }, + "isolated_vlan": schema.StringAttribute{ + Optional: true, + Description: "VLAN id or name of isolated vlan for primary vlan.", + Validators: []validator.String{ + stringvalidator.LengthBetween(1, 64), + tfvalidator.StringFormat(tfvalidator.DefaultFormat), + }, + }, + "l3_interface": schema.StringAttribute{ + Optional: true, + Description: "L3 interface name for this VLAN.", + Validators: []validator.String{ + tfvalidator.StringFormat(tfvalidator.InterfaceFormat), + stringvalidator.RegexMatches(regexp.MustCompile( + `^(irb|vlan)\.`), + "must start with 'irb.' or 'vlan.'"), + }, + }, + "private_vlan": schema.StringAttribute{ + Optional: true, + Description: "Type of secondary VLAN for private vlan.", + Validators: []validator.String{ + stringvalidator.OneOf("community", "isolated"), + }, + }, + "service_id": schema.Int64Attribute{ + Optional: true, + Description: "Service id.", + Validators: []validator.Int64{ + int64validator.Between(1, 65535), + }, + }, + "vlan_id": schema.StringAttribute{ + Optional: true, + Description: "802.1q VLAN id or `all` or `none`.", + Validators: []validator.String{ + stringvalidator.RegexMatches(regexp.MustCompile( + `^(409[0-4]|(40[0-8]|[1-3]\d\d|[1-9]\d|[1-9])\d|[1-9]|all|none)$`), + "must be a VLAN id (1..4094) or all or none"), + }, + }, + "vlan_id_list": schema.SetAttribute{ + ElementType: types.StringType, + Optional: true, + Description: "List of 802.1q VLAN id.", + Validators: []validator.Set{ + setvalidator.SizeAtLeast(1), + setvalidator.ValueStringsAre( + stringvalidator.RegexMatches(regexp.MustCompile( + `^(409[0-4]|(40[0-8]|[1-3]\d\d|[1-9]\d|[1-9])\d|[1-9])`+ + `(-(409[0-4]|(40[0-8]|[1-3]\d\d|[1-9]\d|[1-9])\d|[1-9]))?$`), + "must be a VLAN id (1..4094) or a range of VLAN id (1..4094)-(1..4094)"), + ), + }, + }, + }, + Blocks: map[string]schema.Block{ + "vxlan": schema.SingleNestedBlock{ + Description: "Declare vxlan configuration.", + Attributes: map[string]schema.Attribute{ + "vni": schema.Int64Attribute{ + Required: false, // true when SingleNestedBlock is specified + Optional: true, + Description: "VXLAN identifier.", + Validators: []validator.Int64{ + int64validator.Between(0, 16777214), + }, + }, + "vni_extend_evpn": schema.BoolAttribute{ + Optional: true, + Description: "Extend VNI to EVPN.", + Validators: []validator.Bool{ + tfvalidator.BoolTrue(), + }, + }, + "encapsulate_inner_vlan": schema.BoolAttribute{ + Optional: true, + Description: "Retain inner VLAN in the packet.", + Validators: []validator.Bool{ + tfvalidator.BoolTrue(), + }, + }, + "ingress_node_replication": schema.BoolAttribute{ + Optional: true, + Description: "Enable ingress node replication.", + Validators: []validator.Bool{ + tfvalidator.BoolTrue(), + }, + }, + "multicast_group": schema.StringAttribute{ + Optional: true, + Description: "Multicast group registered for VXLAN segment.", + Validators: []validator.String{ + tfvalidator.StringIPAddress().IPv4Only(), + }, + }, + "ovsdb_managed": schema.BoolAttribute{ + Optional: true, + Description: "Bridge-domain is managed remotely via VXLAN OVSDB Controller.", + Validators: []validator.Bool{ + tfvalidator.BoolTrue(), + }, + }, + "unreachable_vtep_aging_timer": schema.Int64Attribute{ + Optional: true, + Description: "Unreachable VXLAN tunnel endpoint removal timer (seconds).", + Validators: []validator.Int64{ + int64validator.Between(300, 1800), + }, + }, + }, + PlanModifiers: []planmodifier.Object{ + tfplanmodifier.BlockRemoveNull(), + }, + }, + }, + } +} + +type vlanData struct { + ID types.String `tfsdk:"id"` + Name types.String `tfsdk:"name"` + CommunityVlans []types.String `tfsdk:"community_vlans"` + Description types.String `tfsdk:"description"` + ForwardFilterInput types.String `tfsdk:"forward_filter_input"` + ForwardFilterOutput types.String `tfsdk:"forward_filter_output"` + ForwardFloodInput types.String `tfsdk:"forward_flood_input"` + IsolatedVlan types.String `tfsdk:"isolated_vlan"` + L3Interface types.String `tfsdk:"l3_interface"` + PrivateVlan types.String `tfsdk:"private_vlan"` + ServiceID types.Int64 `tfsdk:"service_id"` + VlanID types.String `tfsdk:"vlan_id"` + VlanIDList []types.String `tfsdk:"vlan_id_list"` + Vxlan *vlanBlockVxlan `tfsdk:"vxlan"` +} + +type vlanConfig struct { + ID types.String `tfsdk:"id"` + Name types.String `tfsdk:"name"` + CommunityVlans types.Set `tfsdk:"community_vlans"` + Description types.String `tfsdk:"description"` + ForwardFilterInput types.String `tfsdk:"forward_filter_input"` + ForwardFilterOutput types.String `tfsdk:"forward_filter_output"` + ForwardFloodInput types.String `tfsdk:"forward_flood_input"` + IsolatedVlan types.String `tfsdk:"isolated_vlan"` + L3Interface types.String `tfsdk:"l3_interface"` + PrivateVlan types.String `tfsdk:"private_vlan"` + ServiceID types.Int64 `tfsdk:"service_id"` + VlanID types.String `tfsdk:"vlan_id"` + VlanIDList types.Set `tfsdk:"vlan_id_list"` + Vxlan *vlanBlockVxlan `tfsdk:"vxlan"` +} + +func (rscConfig *vlanConfig) isEmpty() bool { + return tfdata.CheckBlockIsEmpty(rscConfig, "ID", "Name") +} + +type vlanBlockVxlan struct { + Vni types.Int64 `tfsdk:"vni"` + VniExtendEvpn types.Bool `tfsdk:"vni_extend_evpn"` + EncapsulateInnerVlan types.Bool `tfsdk:"encapsulate_inner_vlan"` + IngressNodeReplication types.Bool `tfsdk:"ingress_node_replication"` + MulticastGroup types.String `tfsdk:"multicast_group"` + OvsdbManaged types.Bool `tfsdk:"ovsdb_managed"` + UnreachableVtepAgingTimer types.Int64 `tfsdk:"unreachable_vtep_aging_timer"` +} + +func (rsc *vlan) ValidateConfig( + ctx context.Context, req resource.ValidateConfigRequest, resp *resource.ValidateConfigResponse, +) { + var config vlanConfig + resp.Diagnostics.Append(req.Config.Get(ctx, &config)...) + if resp.Diagnostics.HasError() { + return + } + + if config.isEmpty() { + resp.Diagnostics.AddAttributeError( + path.Root("name"), + tfdiag.MissingConfigErrSummary, + "At least one of arguments need to be set (in addition to `name`)", + ) + } + + if !config.VlanID.IsNull() && !config.VlanID.IsUnknown() && + !config.VlanIDList.IsNull() && !config.VlanIDList.IsUnknown() { + resp.Diagnostics.AddAttributeError( + path.Root("vlan_id"), + tfdiag.ConflictConfigErrSummary, + "vlan_id and vlan_id_list cannot be configured together", + ) + } + if config.Vxlan != nil { + if config.Vxlan.Vni.IsNull() { + resp.Diagnostics.AddAttributeError( + path.Root("vxlan").AtName("vni"), + tfdiag.MissingConfigErrSummary, + "vni must be specified in vxlan block", + ) + } + if !config.Vxlan.IngressNodeReplication.IsNull() && !config.Vxlan.IngressNodeReplication.IsUnknown() && + !config.Vxlan.MulticastGroup.IsNull() && !config.Vxlan.MulticastGroup.IsUnknown() { + resp.Diagnostics.AddAttributeError( + path.Root("ingress_node_replication"), + tfdiag.ConflictConfigErrSummary, + "ingress_node_replication and multicast_group cannot be configured together", + ) + } + if !config.Vxlan.IngressNodeReplication.IsNull() && !config.Vxlan.IngressNodeReplication.IsUnknown() && + !config.Vxlan.OvsdbManaged.IsNull() && !config.Vxlan.OvsdbManaged.IsUnknown() { + resp.Diagnostics.AddAttributeError( + path.Root("ingress_node_replication"), + tfdiag.ConflictConfigErrSummary, + "ingress_node_replication and ovsdb_managed cannot be configured together", + ) + } + if !config.Vxlan.MulticastGroup.IsNull() && !config.Vxlan.MulticastGroup.IsUnknown() && + !config.Vxlan.OvsdbManaged.IsNull() && !config.Vxlan.OvsdbManaged.IsUnknown() { + resp.Diagnostics.AddAttributeError( + path.Root("multicast_group"), + tfdiag.ConflictConfigErrSummary, + "multicast_group and ovsdb_managed cannot be configured together", + ) + } + } +} + +func (rsc *vlan) Create( + ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse, +) { + var plan vlanData + resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) + if resp.Diagnostics.HasError() { + return + } + if plan.Name.ValueString() == "" { + resp.Diagnostics.AddAttributeError( + path.Root("name"), + "Empty Name", + defaultResourceCouldNotCreateWithEmptyMessage(rsc, "name"), + ) + + return + } + + defaultResourceCreate( + ctx, + rsc, + func(fnCtx context.Context, junSess *junos.Session) bool { + vlanExists, err := checkVlanExists(fnCtx, plan.Name.ValueString(), junSess) + if err != nil { + resp.Diagnostics.AddError(tfdiag.PreCheckErrSummary, err.Error()) + + return false + } + if vlanExists { + resp.Diagnostics.AddError( + tfdiag.DuplicateConfigErrSummary, + defaultResourceAlreadyExistsMessage(rsc, plan.Name), + ) + + return false + } + + return true + }, + func(fnCtx context.Context, junSess *junos.Session) bool { + vlanExists, err := checkVlanExists(fnCtx, plan.Name.ValueString(), junSess) + if err != nil { + resp.Diagnostics.AddError(tfdiag.PostCheckErrSummary, err.Error()) + + return false + } + if !vlanExists { + resp.Diagnostics.AddError( + tfdiag.NotFoundErrSummary, + defaultResourceDoesNotExistsAfterCommitMessage(rsc, plan.Name), + ) + + return false + } + + return true + }, + &plan, + resp, + ) +} + +func (rsc *vlan) Read( + ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse, +) { + var state, data vlanData + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + + var _ resourceDataReadFrom1String = &data + defaultResourceRead( + ctx, + rsc, + []string{ + state.Name.ValueString(), + }, + &data, + nil, + resp, + ) +} + +func (rsc *vlan) Update( + ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse, +) { + var plan, state vlanData + resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + + defaultResourceUpdate( + ctx, + rsc, + &state, + &plan, + resp, + ) +} + +func (rsc *vlan) Delete( + ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse, +) { + var state vlanData + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + + defaultResourceDelete( + ctx, + rsc, + &state, + resp, + ) +} + +func (rsc *vlan) ImportState( + ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse, +) { + var data vlanData + + var _ resourceDataReadFrom1String = &data + defaultResourceImportState( + ctx, + rsc, + &data, + req, + resp, + defaultResourceImportDontFindIDStrMessage(rsc, req.ID, "name"), + ) +} + +func checkVlanExists( + _ context.Context, name string, junSess *junos.Session, +) ( + bool, error, +) { + showConfig, err := junSess.Command(junos.CmdShowConfig + + "vlans " + name + junos.PipeDisplaySet) + if err != nil { + return false, err + } + if showConfig == junos.EmptyW { + return false, nil + } + + return true, nil +} + +func (rscData *vlanData) fillID() { + rscData.ID = types.StringValue(rscData.Name.ValueString()) +} + +func (rscData *vlanData) nullID() bool { + return rscData.ID.IsNull() +} + +func (rscData *vlanData) set( + _ context.Context, junSess *junos.Session, +) ( + path.Path, error, +) { + configSet := make([]string, 0) + setPrefix := "set vlans " + rscData.Name.ValueString() + " " + + for _, v := range rscData.CommunityVlans { + configSet = append(configSet, setPrefix+"community-vlans "+v.ValueString()) + } + if v := rscData.Description.ValueString(); v != "" { + configSet = append(configSet, setPrefix+"description \""+v+"\"") + } + if v := rscData.ForwardFilterInput.ValueString(); v != "" { + configSet = append(configSet, setPrefix+"forwarding-options filter input \""+v+"\"") + } + if v := rscData.ForwardFilterOutput.ValueString(); v != "" { + configSet = append(configSet, setPrefix+"forwarding-options filter output \""+v+"\"") + } + if v := rscData.ForwardFloodInput.ValueString(); v != "" { + configSet = append(configSet, setPrefix+"forwarding-options flood input \""+v+"\"") + } + if v := rscData.IsolatedVlan.ValueString(); v != "" { + configSet = append(configSet, setPrefix+"isolated-vlan "+v) + } + if v := rscData.L3Interface.ValueString(); v != "" { + configSet = append(configSet, setPrefix+"l3-interface "+v) + } + if v := rscData.PrivateVlan.ValueString(); v != "" { + configSet = append(configSet, setPrefix+"private-vlan "+v) + } + if !rscData.ServiceID.IsNull() { + configSet = append(configSet, setPrefix+"service-id "+ + utils.ConvI64toa(rscData.ServiceID.ValueInt64())) + } + if v := rscData.VlanID.ValueString(); v != "" { + configSet = append(configSet, setPrefix+"vlan-id "+v) + } + for _, v := range rscData.VlanIDList { + configSet = append(configSet, setPrefix+"vlan-id-list "+v.ValueString()) + } + if rscData.Vxlan != nil { + configSet = append(configSet, setPrefix+"vxlan vni "+ + utils.ConvI64toa(rscData.Vxlan.Vni.ValueInt64())) + + if rscData.Vxlan.VniExtendEvpn.ValueBool() { + configSet = append(configSet, "set protocols evpn extended-vni-list "+ + utils.ConvI64toa(rscData.Vxlan.Vni.ValueInt64())) + } + if rscData.Vxlan.EncapsulateInnerVlan.ValueBool() { + configSet = append(configSet, setPrefix+"vxlan encapsulate-inner-vlan") + } + if rscData.Vxlan.IngressNodeReplication.ValueBool() { + configSet = append(configSet, setPrefix+"vxlan ingress-node-replication") + } + if v := rscData.Vxlan.MulticastGroup.ValueString(); v != "" { + configSet = append(configSet, setPrefix+"vxlan multicast-group "+v) + } + if rscData.Vxlan.OvsdbManaged.ValueBool() { + configSet = append(configSet, setPrefix+"vxlan ovsdb-managed") + } + if !rscData.Vxlan.UnreachableVtepAgingTimer.IsNull() { + configSet = append(configSet, setPrefix+"vxlan unreachable-vtep-aging-timer "+ + utils.ConvI64toa(rscData.Vxlan.UnreachableVtepAgingTimer.ValueInt64())) + } + } + + return path.Empty(), junSess.ConfigSet(configSet) +} + +func (rscData *vlanData) read( + _ context.Context, name string, junSess *junos.Session, +) ( + err error, +) { + showConfig, err := junSess.Command(junos.CmdShowConfig + + "vlans " + name + junos.PipeDisplaySetRelative) + if err != nil { + return err + } + if showConfig != junos.EmptyW { + rscData.Name = types.StringValue(name) + rscData.fillID() + for _, item := range strings.Split(showConfig, "\n") { + if strings.Contains(item, junos.XMLStartTagConfigOut) { + continue + } + if strings.Contains(item, junos.XMLEndTagConfigOut) { + break + } + itemTrim := strings.TrimPrefix(item, junos.SetLS) + switch { + case balt.CutPrefixInString(&itemTrim, "community-vlans "): + rscData.CommunityVlans = append(rscData.CommunityVlans, types.StringValue(itemTrim)) + case balt.CutPrefixInString(&itemTrim, "description "): + rscData.Description = types.StringValue(strings.Trim(itemTrim, "\"")) + case balt.CutPrefixInString(&itemTrim, "forwarding-options filter input "): + rscData.ForwardFilterInput = types.StringValue(strings.Trim(itemTrim, "\"")) + case balt.CutPrefixInString(&itemTrim, "forwarding-options filter output "): + rscData.ForwardFilterOutput = types.StringValue(strings.Trim(itemTrim, "\"")) + case balt.CutPrefixInString(&itemTrim, "forwarding-options flood input "): + rscData.ForwardFloodInput = types.StringValue(strings.Trim(itemTrim, "\"")) + case balt.CutPrefixInString(&itemTrim, "isolated-vlan "): + rscData.IsolatedVlan = types.StringValue(itemTrim) + case balt.CutPrefixInString(&itemTrim, "l3-interface "): + rscData.L3Interface = types.StringValue(itemTrim) + case balt.CutPrefixInString(&itemTrim, "private-vlan "): + rscData.PrivateVlan = types.StringValue(itemTrim) + case balt.CutPrefixInString(&itemTrim, "service-id "): + rscData.ServiceID, err = tfdata.ConvAtoi64Value(itemTrim) + if err != nil { + return err + } + case balt.CutPrefixInString(&itemTrim, "vlan-id "): + rscData.VlanID = types.StringValue(itemTrim) + case balt.CutPrefixInString(&itemTrim, "vlan-id-list "): + rscData.VlanIDList = append(rscData.VlanIDList, types.StringValue(itemTrim)) + case balt.CutPrefixInString(&itemTrim, "vxlan "): + if rscData.Vxlan == nil { + rscData.Vxlan = &vlanBlockVxlan{} + } + switch { + case balt.CutPrefixInString(&itemTrim, "vni "): + rscData.Vxlan.Vni, err = tfdata.ConvAtoi64Value(itemTrim) + if err != nil { + return err + } + showConfigEvpn, err := junSess.Command(junos.CmdShowConfig + "protocols evpn" + junos.PipeDisplaySetRelative) + if err != nil { + return err + } + if showConfigEvpn != junos.EmptyW { + for _, itemEvpn := range strings.Split(showConfigEvpn, "\n") { + if strings.Contains(itemEvpn, junos.XMLStartTagConfigOut) { + continue + } + if strings.Contains(itemEvpn, junos.XMLEndTagConfigOut) { + break + } + if itemEvpn == junos.SetLS+"extended-vni-list "+itemTrim { + rscData.Vxlan.VniExtendEvpn = types.BoolValue(true) + } + } + } + case itemTrim == "encapsulate-inner-vlan": + rscData.Vxlan.EncapsulateInnerVlan = types.BoolValue(true) + case itemTrim == "ingress-node-replication": + rscData.Vxlan.IngressNodeReplication = types.BoolValue(true) + case balt.CutPrefixInString(&itemTrim, "multicast-group "): + rscData.Vxlan.MulticastGroup = types.StringValue(itemTrim) + case itemTrim == "ovsdb-managed": + rscData.Vxlan.OvsdbManaged = types.BoolValue(true) + case balt.CutPrefixInString(&itemTrim, "unreachable-vtep-aging-timer "): + rscData.Vxlan.UnreachableVtepAgingTimer, err = tfdata.ConvAtoi64Value(itemTrim) + if err != nil { + return err + } + } + } + } + } + + return nil +} + +func (rscData *vlanData) del( + _ context.Context, junSess *junos.Session, +) error { + configSet := []string{ + "delete vlans " + rscData.Name.ValueString(), + } + if rscData.Vxlan != nil && rscData.Vxlan.VniExtendEvpn.ValueBool() { + configSet = append(configSet, "delete protocols evpn extended-vni-list "+ + utils.ConvI64toa(rscData.Vxlan.Vni.ValueInt64())) + } + + return junSess.ConfigSet(configSet) +} diff --git a/internal/providerfwk/resource_vlan_test.go b/internal/providerfwk/resource_vlan_test.go new file mode 100644 index 00000000..70a22baa --- /dev/null +++ b/internal/providerfwk/resource_vlan_test.go @@ -0,0 +1,61 @@ +package providerfwk_test + +import ( + "os" + "testing" + + "github.com/hashicorp/terraform-plugin-testing/config" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" +) + +func TestAccResourceVlan_basic(t *testing.T) { + if os.Getenv("TESTACC_SWITCH") != "" { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProtoV5ProviderFactories: testAccProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + ConfigDirectory: config.TestStepDirectory(), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("junos_vlan.testacc_vlansw", + "description", "testacc_vlansw"), + resource.TestCheckResourceAttr("junos_vlan.testacc_vlansw", + "vlan_id", "1000"), + resource.TestCheckResourceAttr("junos_vlan.testacc_vlansw", + "service_id", "1000"), + resource.TestCheckResourceAttr("junos_vlan.testacc_vlansw", + "l3_interface", "irb.1000"), + resource.TestCheckResourceAttr("junos_vlan.testacc_vlansw", + "forward_filter_input", "testacc_vlansw"), + resource.TestCheckResourceAttr("junos_vlan.testacc_vlansw", + "forward_filter_output", "testacc_vlansw"), + resource.TestCheckResourceAttr("junos_vlan.testacc_vlansw", + "forward_flood_input", "testacc_vlansw"), + ), + }, + { + ConfigDirectory: config.TestStepDirectory(), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("junos_vlan.testacc_vlansw", + "vlan_id_list.#", "1"), + resource.TestCheckResourceAttr("junos_vlan.testacc_vlansw", + "vlan_id_list.0", "1001-1002"), + resource.TestCheckResourceAttr("junos_vlan.testacc_vlansw", + "private_vlan", "community"), + ), + }, + { + ResourceName: "junos_vlan.testacc_vlansw", + ImportState: true, + ImportStateVerify: true, + }, + { + ConfigDirectory: config.TestStepDirectory(), + }, + { + ConfigDirectory: config.TestStepDirectory(), + }, + }, + }) + } +} diff --git a/internal/providerfwk/testdata/TestAccResourceVlan_basic/1/main.tf b/internal/providerfwk/testdata/TestAccResourceVlan_basic/1/main.tf new file mode 100644 index 00000000..987e351e --- /dev/null +++ b/internal/providerfwk/testdata/TestAccResourceVlan_basic/1/main.tf @@ -0,0 +1,29 @@ +resource "junos_firewall_filter" "testacc_vlansw" { + lifecycle { + create_before_destroy = true + } + name = "testacc_vlansw" + family = "ethernet-switching" + term { + name = "testacc_vlansw_term1" + then { + action = "accept" + } + } +} +resource "junos_interface_logical" "testacc_vlansw" { + lifecycle { + create_before_destroy = true + } + name = "irb.1000" +} +resource "junos_vlan" "testacc_vlansw" { + name = "testacc_vlansw" + description = "testacc_vlansw" + vlan_id = 1000 + service_id = 1000 + l3_interface = junos_interface_logical.testacc_vlansw.name + forward_filter_input = junos_firewall_filter.testacc_vlansw.name + forward_filter_output = junos_firewall_filter.testacc_vlansw.name + forward_flood_input = junos_firewall_filter.testacc_vlansw.name +} diff --git a/internal/providerfwk/testdata/TestAccResourceVlan_basic/2/main.tf b/internal/providerfwk/testdata/TestAccResourceVlan_basic/2/main.tf new file mode 100644 index 00000000..b265783b --- /dev/null +++ b/internal/providerfwk/testdata/TestAccResourceVlan_basic/2/main.tf @@ -0,0 +1,6 @@ +resource "junos_vlan" "testacc_vlansw" { + name = "testacc_vlansw" + description = "testacc_vlansw" + vlan_id_list = ["1001-1002"] + private_vlan = "community" +} diff --git a/internal/providerfwk/testdata/TestAccResourceVlan_basic/4/main.tf b/internal/providerfwk/testdata/TestAccResourceVlan_basic/4/main.tf new file mode 100644 index 00000000..755791ef --- /dev/null +++ b/internal/providerfwk/testdata/TestAccResourceVlan_basic/4/main.tf @@ -0,0 +1,32 @@ +resource "junos_vlan" "testacc_community" { + name = "testacc_community" + vlan_id = 20 + private_vlan = "community" +} + +resource "junos_vlan" "testacc_community-one" { + name = "testacc_community-one" + vlan_id = 30 + private_vlan = "community" +} + +resource "junos_vlan" "testacc_isolated" { + name = "testacc_isolated" + vlan_id = 200 + private_vlan = "isolated" +} + +resource "junos_vlan" "testacc_pvlan" { + name = "testacc_pvlan" + vlan_id = "2000" + isolated_vlan = junos_vlan.testacc_isolated.name + community_vlans = [ + junos_vlan.testacc_community.name, + junos_vlan.testacc_community-one.name, + ] +} + +resource "junos_vlan" "testacc_none" { + name = "testacc_none" + vlan_id = "none" +} diff --git a/internal/providerfwk/testdata/TestAccResourceVlan_basic/5/main.tf b/internal/providerfwk/testdata/TestAccResourceVlan_basic/5/main.tf new file mode 100644 index 00000000..60da8558 --- /dev/null +++ b/internal/providerfwk/testdata/TestAccResourceVlan_basic/5/main.tf @@ -0,0 +1,67 @@ + +resource "junos_routing_options" "testacc_vlan_vxlan" { + clean_on_destroy = true + router_id = "192.0.2.18" +} +resource "junos_interface_logical" "testacc_vlan_vxlan" { + depends_on = [ + junos_routing_options.testacc_vlan_vxlan, + ] + name = "lo0.0" + description = "testacc_vlan_vxlan" + family_inet { + address { + cidr_ip = "192.0.2.18/32" + } + } +} +resource "junos_policyoptions_community" "testacc_vlan_vxlan" { + lifecycle { + create_before_destroy = true + } + name = "testacc_vlan_vxlan" + members = ["target:65000:100"] +} +resource "junos_policyoptions_policy_statement" "testacc_vlan_vxlan" { + lifecycle { + create_before_destroy = true + } + name = "testacc_vlan_vxlan" + from { + bgp_community = [junos_policyoptions_community.testacc_vlan_vxlan.name] + } + then { + action = "accept" + } +} +resource "junos_switch_options" "testacc_vlan_vxlan" { + clean_on_destroy = true + vtep_source_interface = junos_interface_logical.testacc_vlan_vxlan.name +} +resource "junos_evpn" "testacc_vlan_vxlan" { + depends_on = [ + junos_switch_options.testacc_vlan_vxlan, + ] + encapsulation = "vxlan" + switch_or_ri_options { + route_distinguisher = "20:1" + vrf_target = "target:20:2" + vrf_import = [junos_policyoptions_policy_statement.testacc_vlan_vxlan.name] + vrf_export = [junos_policyoptions_policy_statement.testacc_vlan_vxlan.name] + } +} + +resource "junos_vlan" "testacc_vlan_vxlan" { + depends_on = [ + junos_evpn.testacc_vlan_vxlan, + ] + name = "testacc_vlan_vxlan" + vlan_id = 1020 + vxlan { + vni = 102010 + vni_extend_evpn = true + encapsulate_inner_vlan = true + ingress_node_replication = true + unreachable_vtep_aging_timer = 900 + } +} diff --git a/internal/providerfwk/testdata/TestAccUpgradeStateResourceVlan_V0toV1_basic/1/main.tf b/internal/providerfwk/testdata/TestAccUpgradeStateResourceVlan_V0toV1_basic/1/main.tf new file mode 100644 index 00000000..8a55637b --- /dev/null +++ b/internal/providerfwk/testdata/TestAccUpgradeStateResourceVlan_V0toV1_basic/1/main.tf @@ -0,0 +1,54 @@ +resource "junos_vlan" "testacc_community" { + name = "testacc_community" + vlan_id = 20 + private_vlan = "community" +} +resource "junos_vlan" "testacc_community-one" { + name = "testacc_community-one" + vlan_id = 30 + private_vlan = "community" +} +resource "junos_vlan" "testacc_isolated" { + name = "testacc_isolated" + vlan_id = 200 + private_vlan = "isolated" +} +resource "junos_vlan" "testacc_pvlan" { + name = "testacc_pvlan" + vlan_id = 2000 + isolated_vlan = junos_vlan.testacc_isolated.vlan_id + community_vlans = [ + junos_vlan.testacc_community.vlan_id, + junos_vlan.testacc_community-one.vlan_id, + ] +} + +resource "junos_firewall_filter" "testacc_vlansw" { + lifecycle { + create_before_destroy = true + } + name = "testacc_vlansw" + family = "ethernet-switching" + term { + name = "testacc_vlansw_term1" + then { + action = "accept" + } + } +} +resource "junos_interface_logical" "testacc_vlansw" { + lifecycle { + create_before_destroy = true + } + name = "irb.1000" +} +resource "junos_vlan" "testacc_vlansw" { + name = "testacc_vlansw" + description = "testacc_vlansw" + vlan_id = 1000 + service_id = 1000 + l3_interface = junos_interface_logical.testacc_vlansw.name + forward_filter_input = junos_firewall_filter.testacc_vlansw.name + forward_filter_output = junos_firewall_filter.testacc_vlansw.name + forward_flood_input = junos_firewall_filter.testacc_vlansw.name +} diff --git a/internal/providerfwk/testdata/TestAccUpgradeStateResourceVlan_V0toV1_basic/1/provider.tf b/internal/providerfwk/testdata/TestAccUpgradeStateResourceVlan_V0toV1_basic/1/provider.tf new file mode 100644 index 00000000..713fa309 --- /dev/null +++ b/internal/providerfwk/testdata/TestAccUpgradeStateResourceVlan_V0toV1_basic/1/provider.tf @@ -0,0 +1,10 @@ +terraform { + required_providers { + junos = { + source = "registry.terraform.io/jeremmfr/junos" + version = "1.33.0" + } + } +} + +provider "junos" {} diff --git a/internal/providerfwk/testdata/TestAccUpgradeStateResourceVlan_V0toV1_basic/2/main.tf b/internal/providerfwk/testdata/TestAccUpgradeStateResourceVlan_V0toV1_basic/2/main.tf new file mode 120000 index 00000000..7a6c4026 --- /dev/null +++ b/internal/providerfwk/testdata/TestAccUpgradeStateResourceVlan_V0toV1_basic/2/main.tf @@ -0,0 +1 @@ +../1/main.tf \ No newline at end of file diff --git a/internal/providerfwk/upgradestate_vlan.go b/internal/providerfwk/upgradestate_vlan.go new file mode 100644 index 00000000..1d0084f3 --- /dev/null +++ b/internal/providerfwk/upgradestate_vlan.go @@ -0,0 +1,163 @@ +package providerfwk + +import ( + "context" + + "github.com/jeremmfr/terraform-provider-junos/internal/utils" + + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/types" +) + +func (rsc *vlan) UpgradeState(_ context.Context) map[int64]resource.StateUpgrader { + return map[int64]resource.StateUpgrader{ + 0: { + PriorSchema: &schema.Schema{ + Attributes: map[string]schema.Attribute{ + "id": schema.StringAttribute{ + Computed: true, + }, + "name": schema.StringAttribute{ + Required: true, + }, + "community_vlans": schema.SetAttribute{ + ElementType: types.Int64Type, + Optional: true, + }, + "description": schema.StringAttribute{ + Optional: true, + }, + "forward_filter_input": schema.StringAttribute{ + Optional: true, + }, + "forward_filter_output": schema.StringAttribute{ + Optional: true, + }, + "forward_flood_input": schema.StringAttribute{ + Optional: true, + }, + "isolated_vlan": schema.Int64Attribute{ + Optional: true, + }, + "l3_interface": schema.StringAttribute{ + Optional: true, + }, + "private_vlan": schema.StringAttribute{ + Optional: true, + }, + "service_id": schema.Int64Attribute{ + Optional: true, + }, + "vlan_id": schema.Int64Attribute{ + Optional: true, + }, + "vlan_id_list": schema.SetAttribute{ + ElementType: types.StringType, + Optional: true, + }, + }, + Blocks: map[string]schema.Block{ + "vxlan": schema.ListNestedBlock{ + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "vni": schema.Int64Attribute{ + Required: true, + }, + "vni_extend_evpn": schema.BoolAttribute{ + Optional: true, + }, + "encapsulate_inner_vlan": schema.BoolAttribute{ + Optional: true, + }, + "ingress_node_replication": schema.BoolAttribute{ + Optional: true, + }, + "multicast_group": schema.StringAttribute{ + Optional: true, + }, + "ovsdb_managed": schema.BoolAttribute{ + Optional: true, + }, + "unreachable_vtep_aging_timer": schema.Int64Attribute{ + Optional: true, + }, + }, + }, + }, + }, + }, + StateUpgrader: upgradeVlanV0toV1, + }, + } +} + +func upgradeVlanV0toV1( + ctx context.Context, req resource.UpgradeStateRequest, resp *resource.UpgradeStateResponse, +) { + type modelV0 struct { + ID types.String `tfsdk:"id"` + Name types.String `tfsdk:"name"` + CommunityVlans []types.Int64 `tfsdk:"community_vlans"` + Description types.String `tfsdk:"description"` + ForwardFilterInput types.String `tfsdk:"forward_filter_input"` + ForwardFilterOutput types.String `tfsdk:"forward_filter_output"` + ForwardFloodInput types.String `tfsdk:"forward_flood_input"` + IsolatedVlan types.Int64 `tfsdk:"isolated_vlan"` + L3Interface types.String `tfsdk:"l3_interface"` + PrivateVlan types.String `tfsdk:"private_vlan"` + ServiceID types.Int64 `tfsdk:"service_id"` + VlanID types.Int64 `tfsdk:"vlan_id"` + VlanIDList []types.String `tfsdk:"vlan_id_list"` + Vxlan []struct { + Vni types.Int64 `tfsdk:"vni"` + VniExtendEvpn types.Bool `tfsdk:"vni_extend_evpn"` + EncapsulateInnerVlan types.Bool `tfsdk:"encapsulate_inner_vlan"` + IngressNodeReplication types.Bool `tfsdk:"ingress_node_replication"` + MulticastGroup types.String `tfsdk:"multicast_group"` + OvsdbManaged types.Bool `tfsdk:"ovsdb_managed"` + UnreachableVtepAgingTimer types.Int64 `tfsdk:"unreachable_vtep_aging_timer"` + } `tfsdk:"vxlan"` + } + + var dataV0 modelV0 + resp.Diagnostics.Append(req.State.Get(ctx, &dataV0)...) + if resp.Diagnostics.HasError() { + return + } + + var dataV1 vlanData + dataV1.ID = dataV0.ID + dataV1.Name = dataV0.Name + dataV1.CommunityVlans = make([]types.String, len(dataV0.CommunityVlans)) + for i, v := range dataV0.CommunityVlans { + dataV1.CommunityVlans[i] = types.StringValue(utils.ConvI64toa(v.ValueInt64())) + } + dataV1.Description = dataV0.Description + dataV1.ForwardFilterInput = dataV0.ForwardFilterInput + dataV1.ForwardFilterOutput = dataV0.ForwardFilterOutput + dataV1.ForwardFloodInput = dataV0.ForwardFloodInput + if dataV0.IsolatedVlan.ValueInt64() != 0 { + dataV1.IsolatedVlan = types.StringValue(utils.ConvI64toa(dataV0.IsolatedVlan.ValueInt64())) + } + dataV1.L3Interface = dataV0.L3Interface + dataV1.PrivateVlan = dataV0.PrivateVlan + dataV1.ServiceID = dataV0.ServiceID + if dataV0.VlanID.ValueInt64() != 0 { + dataV1.VlanID = types.StringValue(utils.ConvI64toa(dataV0.VlanID.ValueInt64())) + } + dataV1.VlanIDList = dataV0.VlanIDList + if len(dataV0.Vxlan) > 0 { + dataV1.Vxlan = &vlanBlockVxlan{ + Vni: dataV0.Vxlan[0].Vni, + VniExtendEvpn: dataV0.Vxlan[0].VniExtendEvpn, + EncapsulateInnerVlan: dataV0.Vxlan[0].EncapsulateInnerVlan, + IngressNodeReplication: dataV0.Vxlan[0].IngressNodeReplication, + MulticastGroup: dataV0.Vxlan[0].MulticastGroup, + OvsdbManaged: dataV0.Vxlan[0].OvsdbManaged, + UnreachableVtepAgingTimer: dataV0.Vxlan[0].UnreachableVtepAgingTimer, + } + } + + resp.Diagnostics.Append(resp.State.Set(ctx, dataV1)...) +} diff --git a/internal/providerfwk/upgradestate_vlan_test.go b/internal/providerfwk/upgradestate_vlan_test.go new file mode 100644 index 00000000..6cfccb18 --- /dev/null +++ b/internal/providerfwk/upgradestate_vlan_test.go @@ -0,0 +1,29 @@ +package providerfwk_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/config" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/plancheck" +) + +// export TESTACC_INTERFACE= for choose interface available else it's ge-0/0/3. +func TestAccUpgradeStateResourceVlan_V0toV1_basic(t *testing.T) { + resource.Test(t, resource.TestCase{ + Steps: []resource.TestStep{ + { + ConfigDirectory: config.TestStepDirectory(), + }, + { + ProtoV5ProviderFactories: testAccProtoV5ProviderFactories, + ConfigDirectory: config.TestStepDirectory(), + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectEmptyPlan(), + }, + }, + }, + }, + }) +} diff --git a/internal/providersdk/provider.go b/internal/providersdk/provider.go index c4694e0a..85553727 100644 --- a/internal/providersdk/provider.go +++ b/internal/providersdk/provider.go @@ -229,8 +229,6 @@ func Provider() *schema.Provider { "junos_system_root_authentication": resourceSystemRootAuthentication(), "junos_system_services_dhcp_localserver_group": resourceSystemServicesDhcpLocalServerGroup(), - "junos_vlan": resourceVlan(), - "junos_vstp": resourceVstp(), "junos_vstp_interface": resourceVstpInterface(), "junos_vstp_vlan": resourceVstpVlan(), diff --git a/internal/providersdk/resource_vlan.go b/internal/providersdk/resource_vlan.go deleted file mode 100644 index f521f2c0..00000000 --- a/internal/providersdk/resource_vlan.go +++ /dev/null @@ -1,605 +0,0 @@ -package providersdk - -import ( - "context" - "fmt" - "strconv" - "strings" - - "github.com/jeremmfr/terraform-provider-junos/internal/junos" - - "github.com/hashicorp/terraform-plugin-sdk/v2/diag" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" - balt "github.com/jeremmfr/go-utils/basicalter" - bchk "github.com/jeremmfr/go-utils/basiccheck" -) - -type vlanOptions struct { - isolatedVlan int - serviceID int - vlanID int - name string - description string - forwardFilterInput string - forwardFilterOutput string - forwardFloodInput string - l3Interface string - privateVlan string - communityVlans []int - vlanIDList []string - vxlan []map[string]interface{} -} - -func resourceVlan() *schema.Resource { - return &schema.Resource{ - CreateWithoutTimeout: resourceVlanCreate, - ReadWithoutTimeout: resourceVlanRead, - UpdateWithoutTimeout: resourceVlanUpdate, - DeleteWithoutTimeout: resourceVlanDelete, - Importer: &schema.ResourceImporter{ - StateContext: resourceVlanImport, - }, - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - ForceNew: true, - Required: true, - ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, formatDefault), - }, - "community_vlans": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeInt}, - }, - "description": { - Type: schema.TypeString, - Optional: true, - }, - "forward_filter_input": { - Type: schema.TypeString, - Optional: true, - ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, formatDefault), - }, - "forward_filter_output": { - Type: schema.TypeString, - Optional: true, - ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, formatDefault), - }, - "forward_flood_input": { - Type: schema.TypeString, - Optional: true, - ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, formatDefault), - }, - "isolated_vlan": { - Type: schema.TypeInt, - Optional: true, - ValidateFunc: validation.IntBetween(1, 65535), - }, - "l3_interface": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) { - value := v.(string) - if !bchk.StringHasOneOfPrefixes(value, []string{"irb.", "vlan."}) { - errors = append(errors, fmt.Errorf( - "%q for %q is not start with 'irb.' or 'vlan.'", value, k)) - } - - return - }, - }, - "private_vlan": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: validation.StringInSlice([]string{"community", "isolated"}, false), - }, - "service_id": { - Type: schema.TypeInt, - Optional: true, - ValidateFunc: validation.IntBetween(1, 65535), - }, - "vlan_id": { - Type: schema.TypeInt, - Optional: true, - ValidateFunc: validation.IntBetween(1, 4094), - ConflictsWith: []string{"vlan_id_list"}, - }, - "vlan_id_list": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - ConflictsWith: []string{"vlan_id"}, - }, - "vxlan": { - Type: schema.TypeList, - Optional: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "vni": { - Type: schema.TypeInt, - Required: true, - ValidateFunc: validation.IntBetween(0, 16777214), - }, - "vni_extend_evpn": { - Type: schema.TypeBool, - Optional: true, - }, - "encapsulate_inner_vlan": { - Type: schema.TypeBool, - Optional: true, - }, - "ingress_node_replication": { - Type: schema.TypeBool, - Optional: true, - }, - "multicast_group": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: validation.IsIPAddress, - }, - "ovsdb_managed": { - Type: schema.TypeBool, - Optional: true, - }, - "unreachable_vtep_aging_timer": { - Type: schema.TypeInt, - Optional: true, - ValidateFunc: validation.IntBetween(300, 1800), - }, - }, - }, - }, - }, - } -} - -func resourceVlanCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { - clt := m.(*junos.Client) - if clt.FakeCreateSetFile() { - junSess := clt.NewSessionWithoutNetconf(ctx) - if err := setVlan(d, junSess); err != nil { - return diag.FromErr(err) - } - d.SetId(d.Get("name").(string)) - - return nil - } - junSess, err := clt.StartNewSession(ctx) - if err != nil { - return diag.FromErr(err) - } - defer junSess.Close() - if err := junSess.ConfigLock(ctx); err != nil { - return diag.FromErr(err) - } - var diagWarns diag.Diagnostics - vlanExists, err := checkVlansExists(d.Get("name").(string), junSess) - if err != nil { - appendDiagWarns(&diagWarns, junSess.ConfigClear()) - - return append(diagWarns, diag.FromErr(err)...) - } - if vlanExists { - appendDiagWarns(&diagWarns, junSess.ConfigClear()) - - return append(diagWarns, diag.FromErr(fmt.Errorf("vlan %v already exists", d.Get("name").(string)))...) - } - - if err := setVlan(d, junSess); err != nil { - appendDiagWarns(&diagWarns, junSess.ConfigClear()) - - return append(diagWarns, diag.FromErr(err)...) - } - warns, err := junSess.CommitConf(ctx, "create resource junos_vlan") - appendDiagWarns(&diagWarns, warns) - if err != nil { - appendDiagWarns(&diagWarns, junSess.ConfigClear()) - - return append(diagWarns, diag.FromErr(err)...) - } - vlanExists, err = checkVlansExists(d.Get("name").(string), junSess) - if err != nil { - return append(diagWarns, diag.FromErr(err)...) - } - if vlanExists { - d.SetId(d.Get("name").(string)) - } else { - return append(diagWarns, - diag.FromErr(fmt.Errorf("vlan %v not exists after commit => check your config", d.Get("name").(string)))...) - } - - return append(diagWarns, resourceVlanReadWJunSess(d, junSess)...) -} - -func resourceVlanRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { - clt := m.(*junos.Client) - junSess, err := clt.StartNewSession(ctx) - if err != nil { - return diag.FromErr(err) - } - defer junSess.Close() - - return resourceVlanReadWJunSess(d, junSess) -} - -func resourceVlanReadWJunSess(d *schema.ResourceData, junSess *junos.Session) diag.Diagnostics { - junos.MutexLock() - vlanOptions, err := readVlan(d.Get("name").(string), junSess) - junos.MutexUnlock() - if err != nil { - return diag.FromErr(err) - } - if vlanOptions.name == "" { - d.SetId("") - } else { - fillVlanData(d, vlanOptions) - } - - return nil -} - -func resourceVlanUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { - d.Partial(true) - clt := m.(*junos.Client) - if clt.FakeUpdateAlso() { - junSess := clt.NewSessionWithoutNetconf(ctx) - if d.HasChange("vxlan") { - oldVxlan, _ := d.GetChange("vxlan") - if err := delVlan(d.Get("name").(string), oldVxlan.([]interface{}), junSess); err != nil { - return diag.FromErr(err) - } - } else if err := delVlan(d.Get("name").(string), d.Get("vxlan").([]interface{}), junSess); err != nil { - return diag.FromErr(err) - } - if err := setVlan(d, junSess); err != nil { - return diag.FromErr(err) - } - d.Partial(false) - - return nil - } - junSess, err := clt.StartNewSession(ctx) - if err != nil { - return diag.FromErr(err) - } - defer junSess.Close() - if err := junSess.ConfigLock(ctx); err != nil { - return diag.FromErr(err) - } - var diagWarns diag.Diagnostics - if d.HasChange("vxlan") { - oldVxlan, _ := d.GetChange("vxlan") - if err := delVlan(d.Get("name").(string), oldVxlan.([]interface{}), junSess); err != nil { - appendDiagWarns(&diagWarns, junSess.ConfigClear()) - - return append(diagWarns, diag.FromErr(err)...) - } - } else if err := delVlan(d.Get("name").(string), d.Get("vxlan").([]interface{}), junSess); err != nil { - appendDiagWarns(&diagWarns, junSess.ConfigClear()) - - return append(diagWarns, diag.FromErr(err)...) - } - if err := setVlan(d, junSess); err != nil { - appendDiagWarns(&diagWarns, junSess.ConfigClear()) - - return append(diagWarns, diag.FromErr(err)...) - } - warns, err := junSess.CommitConf(ctx, "update resource junos_vlan") - appendDiagWarns(&diagWarns, warns) - if err != nil { - appendDiagWarns(&diagWarns, junSess.ConfigClear()) - - return append(diagWarns, diag.FromErr(err)...) - } - d.Partial(false) - - return append(diagWarns, resourceVlanReadWJunSess(d, junSess)...) -} - -func resourceVlanDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { - clt := m.(*junos.Client) - if clt.FakeDeleteAlso() { - junSess := clt.NewSessionWithoutNetconf(ctx) - if err := delVlan(d.Get("name").(string), d.Get("vxlan").([]interface{}), junSess); err != nil { - return diag.FromErr(err) - } - - return nil - } - junSess, err := clt.StartNewSession(ctx) - if err != nil { - return diag.FromErr(err) - } - defer junSess.Close() - if err := junSess.ConfigLock(ctx); err != nil { - return diag.FromErr(err) - } - var diagWarns diag.Diagnostics - if err := delVlan(d.Get("name").(string), d.Get("vxlan").([]interface{}), junSess); err != nil { - appendDiagWarns(&diagWarns, junSess.ConfigClear()) - - return append(diagWarns, diag.FromErr(err)...) - } - warns, err := junSess.CommitConf(ctx, "delete resource junos_vlan") - appendDiagWarns(&diagWarns, warns) - if err != nil { - appendDiagWarns(&diagWarns, junSess.ConfigClear()) - - return append(diagWarns, diag.FromErr(err)...) - } - - return diagWarns -} - -func resourceVlanImport(ctx context.Context, d *schema.ResourceData, m interface{}, -) ([]*schema.ResourceData, error) { - clt := m.(*junos.Client) - junSess, err := clt.StartNewSession(ctx) - if err != nil { - return nil, err - } - defer junSess.Close() - result := make([]*schema.ResourceData, 1) - vlanExists, err := checkVlansExists(d.Id(), junSess) - if err != nil { - return nil, err - } - if !vlanExists { - return nil, fmt.Errorf("don't find vlan with id '%v' (id must be )", d.Id()) - } - vlanOptions, err := readVlan(d.Id(), junSess) - if err != nil { - return nil, err - } - fillVlanData(d, vlanOptions) - - result[0] = d - - return result, nil -} - -func checkVlansExists(vlan string, junSess *junos.Session) (bool, error) { - showConfig, err := junSess.Command(junos.CmdShowConfig + "vlans " + vlan + junos.PipeDisplaySet) - if err != nil { - return false, err - } - if showConfig == junos.EmptyW { - return false, nil - } - - return true, nil -} - -func setVlan(d *schema.ResourceData, junSess *junos.Session) error { - configSet := make([]string, 0) - - setPrefix := "set vlans " + d.Get("name").(string) + " " - for _, v := range d.Get("community_vlans").(*schema.Set).List() { - configSet = append(configSet, setPrefix+"community-vlans "+strconv.Itoa(v.(int))) - } - if d.Get("description").(string) != "" { - configSet = append(configSet, setPrefix+"description \""+d.Get("description").(string)+"\"") - } - if d.Get("forward_filter_input").(string) != "" { - configSet = append(configSet, setPrefix+ - "forwarding-options filter input "+d.Get("forward_filter_input").(string)) - } - if d.Get("forward_filter_output").(string) != "" { - configSet = append(configSet, setPrefix+ - "forwarding-options filter output "+d.Get("forward_filter_output").(string)) - } - if d.Get("forward_flood_input").(string) != "" { - configSet = append(configSet, setPrefix+ - "forwarding-options flood input "+d.Get("forward_flood_input").(string)) - } - if d.Get("isolated_vlan").(int) != 0 { - configSet = append(configSet, setPrefix+"isolated-vlan "+strconv.Itoa(d.Get("isolated_vlan").(int))) - } - if d.Get("l3_interface").(string) != "" { - configSet = append(configSet, setPrefix+"l3-interface "+d.Get("l3_interface").(string)) - } - if d.Get("private_vlan").(string) != "" { - configSet = append(configSet, setPrefix+"private-vlan "+d.Get("private_vlan").(string)) - } - if d.Get("service_id").(int) != 0 { - configSet = append(configSet, setPrefix+"service-id "+strconv.Itoa(d.Get("service_id").(int))) - } - if d.Get("vlan_id").(int) != 0 { - configSet = append(configSet, setPrefix+"vlan-id "+strconv.Itoa(d.Get("vlan_id").(int))) - } - for _, v := range sortSetOfString(d.Get("vlan_id_list").(*schema.Set).List()) { - configSet = append(configSet, setPrefix+"vlan-id-list "+v) - } - for _, v := range d.Get("vxlan").([]interface{}) { - vxlan := v.(map[string]interface{}) - configSet = append(configSet, setPrefix+"vxlan vni "+strconv.Itoa(vxlan["vni"].(int))) - - if vxlan["vni_extend_evpn"].(bool) { - configSet = append(configSet, "set protocols evpn extended-vni-list "+strconv.Itoa(vxlan["vni"].(int))) - } - if vxlan["encapsulate_inner_vlan"].(bool) { - configSet = append(configSet, setPrefix+"vxlan encapsulate-inner-vlan") - } - if vxlan["ingress_node_replication"].(bool) { - configSet = append(configSet, setPrefix+"vxlan ingress-node-replication") - } - if vxlan["multicast_group"].(string) != "" { - configSet = append(configSet, setPrefix+"vxlan multicast-group "+vxlan["multicast_group"].(string)) - } - if vxlan["ovsdb_managed"].(bool) { - configSet = append(configSet, setPrefix+"vxlan ovsdb-managed") - } - if vxlan["unreachable_vtep_aging_timer"].(int) != 0 { - configSet = append(configSet, setPrefix+ - "vxlan unreachable-vtep-aging-timer "+strconv.Itoa(vxlan["unreachable_vtep_aging_timer"].(int))) - } - } - - return junSess.ConfigSet(configSet) -} - -func readVlan(vlan string, junSess *junos.Session, -) (confRead vlanOptions, err error) { - showConfig, err := junSess.Command(junos.CmdShowConfig + "vlans " + vlan + junos.PipeDisplaySetRelative) - if err != nil { - return confRead, err - } - if showConfig != junos.EmptyW { - confRead.name = vlan - for _, item := range strings.Split(showConfig, "\n") { - if strings.Contains(item, junos.XMLStartTagConfigOut) { - continue - } - if strings.Contains(item, junos.XMLEndTagConfigOut) { - break - } - itemTrim := strings.TrimPrefix(item, junos.SetLS) - switch { - case balt.CutPrefixInString(&itemTrim, "community-vlans "): - commVlan, err := strconv.Atoi(itemTrim) - if err != nil { - return confRead, fmt.Errorf(failedConvAtoiError, itemTrim, err) - } - confRead.communityVlans = append(confRead.communityVlans, commVlan) - case balt.CutPrefixInString(&itemTrim, "description "): - confRead.description = strings.Trim(itemTrim, "\"") - case balt.CutPrefixInString(&itemTrim, "forwarding-options filter input "): - confRead.forwardFilterInput = itemTrim - case balt.CutPrefixInString(&itemTrim, "forwarding-options filter output "): - confRead.forwardFilterOutput = itemTrim - case balt.CutPrefixInString(&itemTrim, "forwarding-options flood input "): - confRead.forwardFloodInput = itemTrim - case balt.CutPrefixInString(&itemTrim, "isolated-vlan "): - confRead.isolatedVlan, err = strconv.Atoi(itemTrim) - if err != nil { - return confRead, fmt.Errorf(failedConvAtoiError, itemTrim, err) - } - case balt.CutPrefixInString(&itemTrim, "l3-interface "): - confRead.l3Interface = itemTrim - case balt.CutPrefixInString(&itemTrim, "private-vlan "): - confRead.privateVlan = itemTrim - case balt.CutPrefixInString(&itemTrim, "service-id "): - confRead.serviceID, err = strconv.Atoi(itemTrim) - if err != nil { - return confRead, fmt.Errorf(failedConvAtoiError, itemTrim, err) - } - case balt.CutPrefixInString(&itemTrim, "vlan-id "): - confRead.vlanID, err = strconv.Atoi(itemTrim) - if err != nil { - return confRead, fmt.Errorf(failedConvAtoiError, itemTrim, err) - } - case balt.CutPrefixInString(&itemTrim, "vlan-id-list "): - confRead.vlanIDList = append(confRead.vlanIDList, itemTrim) - case balt.CutPrefixInString(&itemTrim, "vxlan "): - if len(confRead.vxlan) == 0 { - confRead.vxlan = append(confRead.vxlan, map[string]interface{}{ - "vni": -1, - "vni_extend_evpn": false, - "encapsulate_inner_vlan": false, - "ingress_node_replication": false, - "multicast_group": "", - "ovsdb_managed": false, - "unreachable_vtep_aging_timer": 0, - }) - } - vxlan := confRead.vxlan[0] - switch { - case balt.CutPrefixInString(&itemTrim, "vni "): - vxlan["vni"], err = strconv.Atoi(itemTrim) - if err != nil { - return confRead, fmt.Errorf(failedConvAtoiError, itemTrim, err) - } - showConfigEvpn, err := junSess.Command(junos.CmdShowConfig + "protocols evpn" + junos.PipeDisplaySetRelative) - if err != nil { - return confRead, err - } - if showConfigEvpn != junos.EmptyW { - for _, itemEvpn := range strings.Split(showConfigEvpn, "\n") { - if strings.Contains(itemEvpn, junos.XMLStartTagConfigOut) { - continue - } - if strings.Contains(itemEvpn, junos.XMLEndTagConfigOut) { - break - } - if strings.HasPrefix(itemEvpn, junos.SetLS+"extended-vni-list "+strconv.Itoa(vxlan["vni"].(int))) { - vxlan["vni_extend_evpn"] = true - } - } - } - case itemTrim == "encapsulate-inner-vlan": - vxlan["encapsulate_inner_vlan"] = true - case itemTrim == "ingress-node-replication": - vxlan["ingress_node_replication"] = true - case balt.CutPrefixInString(&itemTrim, "multicast-group "): - vxlan["multicast_group"] = itemTrim - case itemTrim == "ovsdb-managed": - vxlan["ovsdb_managed"] = true - case balt.CutPrefixInString(&itemTrim, "unreachable-vtep-aging-timer "): - vxlan["unreachable_vtep_aging_timer"], err = strconv.Atoi(itemTrim) - if err != nil { - return confRead, fmt.Errorf(failedConvAtoiError, itemTrim, err) - } - } - } - } - } - - return confRead, nil -} - -func delVlan(vlan string, vxlan []interface{}, junSess *junos.Session) error { - configSet := make([]string, 0, 1) - configSet = append(configSet, "delete vlans "+vlan) - for _, v := range vxlan { - vxlanParams := v.(map[string]interface{}) - if vxlanParams["vni_extend_evpn"].(bool) { - configSet = append(configSet, "delete protocols evpn extended-vni-list "+strconv.Itoa(vxlanParams["vni"].(int))) - } - } - - return junSess.ConfigSet(configSet) -} - -func fillVlanData(d *schema.ResourceData, vlanOptions vlanOptions) { - if tfErr := d.Set("name", vlanOptions.name); tfErr != nil { - panic(tfErr) - } - if tfErr := d.Set("community_vlans", vlanOptions.communityVlans); tfErr != nil { - panic(tfErr) - } - if tfErr := d.Set("description", vlanOptions.description); tfErr != nil { - panic(tfErr) - } - if tfErr := d.Set("forward_filter_input", vlanOptions.forwardFilterInput); tfErr != nil { - panic(tfErr) - } - if tfErr := d.Set("forward_filter_output", vlanOptions.forwardFilterOutput); tfErr != nil { - panic(tfErr) - } - if tfErr := d.Set("forward_flood_input", vlanOptions.forwardFloodInput); tfErr != nil { - panic(tfErr) - } - if tfErr := d.Set("l3_interface", vlanOptions.l3Interface); tfErr != nil { - panic(tfErr) - } - if tfErr := d.Set("isolated_vlan", vlanOptions.isolatedVlan); tfErr != nil { - panic(tfErr) - } - if tfErr := d.Set("private_vlan", vlanOptions.privateVlan); tfErr != nil { - panic(tfErr) - } - if tfErr := d.Set("service_id", vlanOptions.serviceID); tfErr != nil { - panic(tfErr) - } - if tfErr := d.Set("vlan_id", vlanOptions.vlanID); tfErr != nil { - panic(tfErr) - } - if tfErr := d.Set("vlan_id_list", vlanOptions.vlanIDList); tfErr != nil { - panic(tfErr) - } - if tfErr := d.Set("vxlan", vlanOptions.vxlan); tfErr != nil { - panic(tfErr) - } -} diff --git a/internal/providersdk/resource_vlan_test.go b/internal/providersdk/resource_vlan_test.go deleted file mode 100644 index e88fb3c5..00000000 --- a/internal/providersdk/resource_vlan_test.go +++ /dev/null @@ -1,109 +0,0 @@ -package providersdk_test - -import ( - "os" - "testing" - - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" -) - -func TestAccResourceVlan_basic(t *testing.T) { - if os.Getenv("TESTACC_SWITCH") != "" { - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - ProtoV5ProviderFactories: testAccProtoV5ProviderFactories, - Steps: []resource.TestStep{ - { - Config: testAccResourceVlanSwConfigCreate(), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("junos_vlan.testacc_vlansw", - "description", "testacc_vlansw"), - resource.TestCheckResourceAttr("junos_vlan.testacc_vlansw", - "vlan_id", "1000"), - resource.TestCheckResourceAttr("junos_vlan.testacc_vlansw", - "service_id", "1000"), - resource.TestCheckResourceAttr("junos_vlan.testacc_vlansw", - "l3_interface", "irb.1000"), - resource.TestCheckResourceAttr("junos_vlan.testacc_vlansw", - "forward_filter_input", "testacc_vlansw"), - resource.TestCheckResourceAttr("junos_vlan.testacc_vlansw", - "forward_filter_output", "testacc_vlansw"), - resource.TestCheckResourceAttr("junos_vlan.testacc_vlansw", - "forward_flood_input", "testacc_vlansw"), - ), - }, - { - Config: testAccResourceVlanSwConfigUpdate(), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("junos_vlan.testacc_vlansw", - "vlan_id", "0"), - resource.TestCheckResourceAttr("junos_vlan.testacc_vlansw", - "vlan_id_list.#", "1"), - resource.TestCheckResourceAttr("junos_vlan.testacc_vlansw", - "vlan_id_list.0", "1001-1002"), - resource.TestCheckResourceAttr("junos_vlan.testacc_vlansw", - "private_vlan", "community"), - resource.TestCheckResourceAttr("junos_vlan.testacc_vlansw", - "l3_interface", ""), - resource.TestCheckResourceAttr("junos_vlan.testacc_vlansw", - "forward_filter_input", ""), - resource.TestCheckResourceAttr("junos_vlan.testacc_vlansw", - "forward_filter_output", ""), - resource.TestCheckResourceAttr("junos_vlan.testacc_vlansw", - "forward_flood_input", ""), - ), - }, - { - ResourceName: "junos_vlan.testacc_vlansw", - ImportState: true, - ImportStateVerify: true, - }, - }, - }) - } -} - -func testAccResourceVlanSwConfigCreate() string { - return ` -resource "junos_firewall_filter" "testacc_vlansw" { - lifecycle { - create_before_destroy = true - } - name = "testacc_vlansw" - family = "ethernet-switching" - term { - name = "testacc_vlansw_term1" - then { - action = "accept" - } - } -} -resource "junos_interface_logical" "testacc_vlansw" { - lifecycle { - create_before_destroy = true - } - name = "irb.1000" -} -resource "junos_vlan" "testacc_vlansw" { - name = "testacc_vlansw" - description = "testacc_vlansw" - vlan_id = 1000 - service_id = 1000 - l3_interface = junos_interface_logical.testacc_vlansw.name - forward_filter_input = junos_firewall_filter.testacc_vlansw.name - forward_filter_output = junos_firewall_filter.testacc_vlansw.name - forward_flood_input = junos_firewall_filter.testacc_vlansw.name -} -` -} - -func testAccResourceVlanSwConfigUpdate() string { - return ` -resource "junos_vlan" "testacc_vlansw" { - name = "testacc_vlansw" - description = "testacc_vlansw" - vlan_id_list = ["1001-1002"] - private_vlan = "community" -} -` -} From 5af7010d73d67209a22db535c7ec31d616959fa8 Mon Sep 17 00:00:00 2001 From: Jeremy Muriel Date: Wed, 17 Apr 2024 20:37:35 +0200 Subject: [PATCH 15/25] r/vlan: add routing_instance argument Partial fix #646 and therefore id format has been changed to _-_ (instead of ) --- .changes/issue-646.md | 2 + docs/resources/vlan.md | 9 +- internal/providerfwk/resource_vlan.go | 167 ++++++++++++++---- .../TestAccResourceVlan_basic/4/main.tf | 12 ++ .../TestAccResourceVlan_basic/5/main.tf | 28 +++ internal/providerfwk/upgradestate_vlan.go | 4 +- 6 files changed, 186 insertions(+), 36 deletions(-) diff --git a/.changes/issue-646.md b/.changes/issue-646.md index 9924e4e0..7bb7a05d 100644 --- a/.changes/issue-646.md +++ b/.changes/issue-646.md @@ -18,5 +18,7 @@ ENHANCEMENTS: * `vlan_id` argument is now a String (instead of Number) to accept `all` or `none` in addition to VLAN id data in the state has been updated for the new format Number in config is automatically converted to String by Terraform + * add `routing_instance` argument (Partial fix [#646](https://github.com/jeremmfr/terraform-provider-junos/issues/646)) + and therefore `id` format has been changed to `_-_` (instead of ``) BUG FIXES: diff --git a/docs/resources/vlan.md b/docs/resources/vlan.md index 3e46bc3a..f9596c88 100644 --- a/docs/resources/vlan.md +++ b/docs/resources/vlan.md @@ -23,6 +23,10 @@ The following arguments are supported: - **name** (Required, String, Forces new resource) The name of VLAN. +- **routing_instance** (Optional, String, Forces new resource) + Routing instance if not root level. + Need to be `default` or name of routing instance. + Defaults to `default` - **community_vlans** (Optional, Set of String) List of VLAN id or name of community vlans for primary vlan. - **description** (Optional, String) @@ -72,11 +76,12 @@ The following arguments are supported: The following attributes are exported: - **id** (String) - An identifier for the resource with format ``. + An identifier for the resource with format `_-_`. ## Import -Junos vlan can be imported using an id made up of ``, e.g. +Junos vlan can be imported using an id made up of +`` or `_-_`, e.g. ```shell $ terraform import junos_vlan.blue blue diff --git a/internal/providerfwk/resource_vlan.go b/internal/providerfwk/resource_vlan.go index a5b649c1..558fdfe8 100644 --- a/internal/providerfwk/resource_vlan.go +++ b/internal/providerfwk/resource_vlan.go @@ -2,6 +2,7 @@ package providerfwk import ( "context" + "fmt" "regexp" "strings" @@ -19,6 +20,7 @@ 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,7 +87,7 @@ func (rsc *vlan) Schema( Attributes: map[string]schema.Attribute{ "id": schema.StringAttribute{ Computed: true, - Description: "An identifier for the resource with format ``.", + Description: "An identifier for the resource with format `_-_`.", PlanModifiers: []planmodifier.String{ stringplanmodifier.UseStateForUnknown(), }, @@ -101,6 +103,19 @@ func (rsc *vlan) Schema( tfvalidator.StringFormat(tfvalidator.DefaultFormat), }, }, + "routing_instance": schema.StringAttribute{ + Optional: true, + Computed: true, + Default: stringdefault.StaticString(junos.DefaultW), + Description: "Routing instance for vlan if not root level.", + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + }, + Validators: []validator.String{ + stringvalidator.LengthBetween(1, 63), + tfvalidator.StringFormat(tfvalidator.DefaultFormat), + }, + }, "community_vlans": schema.SetAttribute{ ElementType: types.StringType, Optional: true, @@ -267,6 +282,7 @@ func (rsc *vlan) Schema( type vlanData struct { ID types.String `tfsdk:"id"` Name types.String `tfsdk:"name"` + RoutingInstance types.String `tfsdk:"routing_instance"` CommunityVlans []types.String `tfsdk:"community_vlans"` Description types.String `tfsdk:"description"` ForwardFilterInput types.String `tfsdk:"forward_filter_input"` @@ -284,6 +300,7 @@ type vlanData struct { type vlanConfig struct { ID types.String `tfsdk:"id"` Name types.String `tfsdk:"name"` + RoutingInstance types.String `tfsdk:"routing_instance"` CommunityVlans types.Set `tfsdk:"community_vlans"` Description types.String `tfsdk:"description"` ForwardFilterInput types.String `tfsdk:"forward_filter_input"` @@ -299,7 +316,7 @@ type vlanConfig struct { } func (rscConfig *vlanConfig) isEmpty() bool { - return tfdata.CheckBlockIsEmpty(rscConfig, "ID", "Name") + return tfdata.CheckBlockIsEmpty(rscConfig, "ID", "Name", "RoutingInstance") } type vlanBlockVxlan struct { @@ -325,7 +342,7 @@ func (rsc *vlan) ValidateConfig( resp.Diagnostics.AddAttributeError( path.Root("name"), tfdiag.MissingConfigErrSummary, - "At least one of arguments need to be set (in addition to `name`)", + "at least one of arguments need to be set (in addition to `name` and `routing_instance`)", ) } @@ -394,17 +411,41 @@ func (rsc *vlan) Create( ctx, rsc, func(fnCtx context.Context, junSess *junos.Session) bool { - vlanExists, err := checkVlanExists(fnCtx, plan.Name.ValueString(), junSess) + if v := plan.RoutingInstance.ValueString(); v != "" && v != junos.DefaultW { + instanceExists, err := checkRoutingInstanceExists(fnCtx, v, junSess) + if err != nil { + resp.Diagnostics.AddError(tfdiag.PreCheckErrSummary, err.Error()) + + return false + } + if !instanceExists { + resp.Diagnostics.AddAttributeError( + path.Root("routing_instance"), + tfdiag.MissingConfigErrSummary, + fmt.Sprintf("routing instance %q doesn't exist", v), + ) + + return false + } + } + vlanExists, err := checkVlanExists(fnCtx, plan.Name.ValueString(), plan.RoutingInstance.ValueString(), junSess) if err != nil { resp.Diagnostics.AddError(tfdiag.PreCheckErrSummary, err.Error()) return false } if vlanExists { - resp.Diagnostics.AddError( - tfdiag.DuplicateConfigErrSummary, - defaultResourceAlreadyExistsMessage(rsc, plan.Name), - ) + if v := plan.RoutingInstance.ValueString(); v != "" && v != junos.DefaultW { + resp.Diagnostics.AddError( + tfdiag.DuplicateConfigErrSummary, + defaultResourceAlreadyExistsInRoutingInstanceMessage(rsc, plan.Name, v), + ) + } else { + resp.Diagnostics.AddError( + tfdiag.DuplicateConfigErrSummary, + defaultResourceAlreadyExistsMessage(rsc, plan.Name), + ) + } return false } @@ -412,17 +453,24 @@ func (rsc *vlan) Create( return true }, func(fnCtx context.Context, junSess *junos.Session) bool { - vlanExists, err := checkVlanExists(fnCtx, plan.Name.ValueString(), junSess) + vlanExists, err := checkVlanExists(fnCtx, plan.Name.ValueString(), plan.RoutingInstance.ValueString(), junSess) if err != nil { resp.Diagnostics.AddError(tfdiag.PostCheckErrSummary, err.Error()) return false } if !vlanExists { - resp.Diagnostics.AddError( - tfdiag.NotFoundErrSummary, - defaultResourceDoesNotExistsAfterCommitMessage(rsc, plan.Name), - ) + if v := plan.RoutingInstance.ValueString(); v != "" && v != junos.DefaultW { + resp.Diagnostics.AddError( + tfdiag.NotFoundErrSummary, + defaultResourceDoesNotExistsInRoutingInstanceAfterCommitMessage(rsc, plan.Name, v), + ) + } else { + resp.Diagnostics.AddError( + tfdiag.NotFoundErrSummary, + defaultResourceDoesNotExistsAfterCommitMessage(rsc, plan.Name), + ) + } return false } @@ -443,12 +491,13 @@ func (rsc *vlan) Read( return } - var _ resourceDataReadFrom1String = &data + var _ resourceDataReadFrom2String = &data defaultResourceRead( ctx, rsc, []string{ state.Name.ValueString(), + state.RoutingInstance.ValueString(), }, &data, nil, @@ -495,25 +544,53 @@ func (rsc *vlan) Delete( func (rsc *vlan) ImportState( ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse, ) { + junSess, err := rsc.client.StartNewSession(ctx) + if err != nil { + resp.Diagnostics.AddError(tfdiag.StartSessErrSummary, err.Error()) + + return + } + defer junSess.Close() + var data vlanData + idSplit := strings.Split(req.ID, junos.IDSeparator) + if len(idSplit) > 1 { + if err := data.read(ctx, idSplit[0], idSplit[1], junSess); err != nil { + resp.Diagnostics.AddError(tfdiag.ConfigReadErrSummary, err.Error()) - var _ resourceDataReadFrom1String = &data - defaultResourceImportState( - ctx, - rsc, - &data, - req, - resp, - defaultResourceImportDontFindIDStrMessage(rsc, req.ID, "name"), - ) + return + } + } else { + if err := data.read(ctx, idSplit[0], junos.DefaultW, junSess); err != nil { + resp.Diagnostics.AddError(tfdiag.ConfigReadErrSummary, err.Error()) + + return + } + } + + if data.ID.IsNull() { + resp.Diagnostics.AddError( + tfdiag.NotFoundErrSummary, + defaultResourceImportDontFindMessage(rsc, req.ID)+ + " (id must be or "+junos.IDSeparator+")", + ) + + return + } + resp.Diagnostics.Append(resp.State.Set(ctx, data)...) } func checkVlanExists( - _ context.Context, name string, junSess *junos.Session, + _ context.Context, name, routingInstance string, junSess *junos.Session, ) ( bool, error, ) { - showConfig, err := junSess.Command(junos.CmdShowConfig + + showPrefix := junos.CmdShowConfig + if routingInstance != "" && routingInstance != junos.DefaultW { + showPrefix += junos.RoutingInstancesWS + routingInstance + " " + } + + showConfig, err := junSess.Command(showPrefix + "vlans " + name + junos.PipeDisplaySet) if err != nil { return false, err @@ -526,7 +603,11 @@ func checkVlanExists( } func (rscData *vlanData) fillID() { - rscData.ID = types.StringValue(rscData.Name.ValueString()) + if v := rscData.RoutingInstance.ValueString(); v != "" { + rscData.ID = types.StringValue(rscData.Name.ValueString() + junos.IDSeparator + v) + } else { + rscData.ID = types.StringValue(rscData.Name.ValueString() + junos.IDSeparator + junos.DefaultW) + } } func (rscData *vlanData) nullID() bool { @@ -539,7 +620,12 @@ func (rscData *vlanData) set( path.Path, error, ) { configSet := make([]string, 0) - setPrefix := "set vlans " + rscData.Name.ValueString() + " " + setPrefix := junos.SetLS + if v := rscData.RoutingInstance.ValueString(); v != "" && v != junos.DefaultW { + setPrefix += junos.RoutingInstancesWS + v + " " + } + setPrefixProtocolsEvpn := setPrefix + "protocols evpn " + setPrefix += "vlans " + rscData.Name.ValueString() + " " for _, v := range rscData.CommunityVlans { configSet = append(configSet, setPrefix+"community-vlans "+v.ValueString()) @@ -580,7 +666,7 @@ func (rscData *vlanData) set( utils.ConvI64toa(rscData.Vxlan.Vni.ValueInt64())) if rscData.Vxlan.VniExtendEvpn.ValueBool() { - configSet = append(configSet, "set protocols evpn extended-vni-list "+ + configSet = append(configSet, setPrefixProtocolsEvpn+"extended-vni-list "+ utils.ConvI64toa(rscData.Vxlan.Vni.ValueInt64())) } if rscData.Vxlan.EncapsulateInnerVlan.ValueBool() { @@ -605,17 +691,27 @@ func (rscData *vlanData) set( } func (rscData *vlanData) read( - _ context.Context, name string, junSess *junos.Session, + _ context.Context, name, routingInstance string, junSess *junos.Session, ) ( err error, ) { - showConfig, err := junSess.Command(junos.CmdShowConfig + + showPrefix := junos.CmdShowConfig + if routingInstance != "" && routingInstance != junos.DefaultW { + showPrefix += junos.RoutingInstancesWS + routingInstance + " " + } + + showConfig, err := junSess.Command(showPrefix + "vlans " + name + junos.PipeDisplaySetRelative) if err != nil { return err } if showConfig != junos.EmptyW { rscData.Name = types.StringValue(name) + if routingInstance == "" { + rscData.RoutingInstance = types.StringValue(junos.DefaultW) + } else { + rscData.RoutingInstance = types.StringValue(routingInstance) + } rscData.fillID() for _, item := range strings.Split(showConfig, "\n") { if strings.Contains(item, junos.XMLStartTagConfigOut) { @@ -661,7 +757,7 @@ func (rscData *vlanData) read( if err != nil { return err } - showConfigEvpn, err := junSess.Command(junos.CmdShowConfig + "protocols evpn" + junos.PipeDisplaySetRelative) + showConfigEvpn, err := junSess.Command(showPrefix + "protocols evpn" + junos.PipeDisplaySetRelative) if err != nil { return err } @@ -702,11 +798,16 @@ func (rscData *vlanData) read( func (rscData *vlanData) del( _ context.Context, junSess *junos.Session, ) error { + delPrefix := junos.DeleteLS + if v := rscData.RoutingInstance.ValueString(); v != "" && v != junos.DefaultW { + delPrefix += junos.RoutingInstancesWS + v + " " + } + configSet := []string{ - "delete vlans " + rscData.Name.ValueString(), + delPrefix + "vlans " + rscData.Name.ValueString(), } if rscData.Vxlan != nil && rscData.Vxlan.VniExtendEvpn.ValueBool() { - configSet = append(configSet, "delete protocols evpn extended-vni-list "+ + configSet = append(configSet, delPrefix+"protocols evpn extended-vni-list "+ utils.ConvI64toa(rscData.Vxlan.Vni.ValueInt64())) } diff --git a/internal/providerfwk/testdata/TestAccResourceVlan_basic/4/main.tf b/internal/providerfwk/testdata/TestAccResourceVlan_basic/4/main.tf index 755791ef..82ef9366 100644 --- a/internal/providerfwk/testdata/TestAccResourceVlan_basic/4/main.tf +++ b/internal/providerfwk/testdata/TestAccResourceVlan_basic/4/main.tf @@ -30,3 +30,15 @@ resource "junos_vlan" "testacc_none" { name = "testacc_none" vlan_id = "none" } + +resource "junos_routing_instance" "testacc_vlan_ri" { + name = "testacc_vlan_ri" + type = "virtual-switch" +} + +resource "junos_vlan" "testacc_vlan_ri" { + name = "testacc_vlan_ri" + routing_instance = junos_routing_instance.testacc_vlan_ri.name + description = "testacc_vlan_ri" + vlan_id = 200 +} diff --git a/internal/providerfwk/testdata/TestAccResourceVlan_basic/5/main.tf b/internal/providerfwk/testdata/TestAccResourceVlan_basic/5/main.tf index 60da8558..24475716 100644 --- a/internal/providerfwk/testdata/TestAccResourceVlan_basic/5/main.tf +++ b/internal/providerfwk/testdata/TestAccResourceVlan_basic/5/main.tf @@ -65,3 +65,31 @@ resource "junos_vlan" "testacc_vlan_vxlan" { unreachable_vtep_aging_timer = 900 } } + +resource "junos_routing_instance" "testacc_vlan_ri" { + name = "testacc_vlan_ri" + type = "virtual-switch" + route_distinguisher = "11:1" + vrf_target = "target:11:2" + vtep_source_interface = junos_interface_logical.testacc_vlan_vxlan.name +} + +resource "junos_evpn" "testacc_vlan_ri" { + routing_instance = junos_routing_instance.testacc_vlan_ri.name + encapsulation = "vxlan" +} + +resource "junos_vlan" "testacc_vlan_ri" { + depends_on = [ + junos_evpn.testacc_vlan_ri, + ] + + name = "testacc_vlan_ri" + routing_instance = junos_routing_instance.testacc_vlan_ri.name + description = "testacc_vlan_ri" + vlan_id = 1030 + vxlan { + vni = 103010 + vni_extend_evpn = true + } +} diff --git a/internal/providerfwk/upgradestate_vlan.go b/internal/providerfwk/upgradestate_vlan.go index 1d0084f3..035a00d5 100644 --- a/internal/providerfwk/upgradestate_vlan.go +++ b/internal/providerfwk/upgradestate_vlan.go @@ -3,6 +3,7 @@ package providerfwk import ( "context" + "github.com/jeremmfr/terraform-provider-junos/internal/junos" "github.com/jeremmfr/terraform-provider-junos/internal/utils" "github.com/hashicorp/terraform-plugin-framework/resource" @@ -127,8 +128,9 @@ func upgradeVlanV0toV1( } var dataV1 vlanData - dataV1.ID = dataV0.ID dataV1.Name = dataV0.Name + dataV1.RoutingInstance = types.StringValue(junos.DefaultW) + dataV1.fillID() dataV1.CommunityVlans = make([]types.String, len(dataV0.CommunityVlans)) for i, v := range dataV0.CommunityVlans { dataV1.CommunityVlans[i] = types.StringValue(utils.ConvI64toa(v.ValueInt64())) From 3598fa5bf8e1a1c7cf3c0220d0501e24d6fb0d48 Mon Sep 17 00:00:00 2001 From: Jeremy Muriel Date: Thu, 18 Apr 2024 09:16:10 +0200 Subject: [PATCH 16/25] r/vlan: add no_arp_suppression, translation_vni arguments Partial fix #646 --- .changes/issue-646.md | 2 ++ docs/resources/vlan.md | 4 +++ internal/providerfwk/resource_vlan.go | 31 +++++++++++++++++++ .../TestAccResourceVlan_basic/5/main.tf | 10 +++--- 4 files changed, 43 insertions(+), 4 deletions(-) diff --git a/.changes/issue-646.md b/.changes/issue-646.md index 7bb7a05d..2e318ff5 100644 --- a/.changes/issue-646.md +++ b/.changes/issue-646.md @@ -20,5 +20,7 @@ ENHANCEMENTS: Number in config is automatically converted to String by Terraform * add `routing_instance` argument (Partial fix [#646](https://github.com/jeremmfr/terraform-provider-junos/issues/646)) and therefore `id` format has been changed to `_-_` (instead of ``) + * add `no_arp_suppression` argument (Partial fix [#646](https://github.com/jeremmfr/terraform-provider-junos/issues/646)) + * add `translation_vni` argument inside `vxlan` block argument BUG FIXES: diff --git a/docs/resources/vlan.md b/docs/resources/vlan.md index f9596c88..4a64771c 100644 --- a/docs/resources/vlan.md +++ b/docs/resources/vlan.md @@ -42,6 +42,8 @@ The following arguments are supported: - **l3_interface** (Optional, String) L3 interface name for this VLAN. Must be start with `irb.` or `vlan.`. +- **no_arp_suppression** (Optional, Boolean) + Turn off ARP suppression. - **private_vlan** (Optional, String) Type of secondary VLAN for private vlan. Must be `community` or `isolated`. @@ -66,6 +68,8 @@ The following arguments are supported: Multicast group registered for VXLAN segment. - **ovsdb_managed** (Optional, Boolean) Bridge-domain is managed remotely via VXLAN OVSDB Controller. + - **translation_vni** (Optional, Number) + Translated VXLAN identifier (1..16777214). - **vni_extend_evpn** (Optional, Boolean) Extend VNI to EVPN. - **unreachable_vtep_aging_timer** (Optional, Number) diff --git a/internal/providerfwk/resource_vlan.go b/internal/providerfwk/resource_vlan.go index 558fdfe8..71c2e932 100644 --- a/internal/providerfwk/resource_vlan.go +++ b/internal/providerfwk/resource_vlan.go @@ -178,6 +178,13 @@ func (rsc *vlan) Schema( "must start with 'irb.' or 'vlan.'"), }, }, + "no_arp_suppression": schema.BoolAttribute{ + Optional: true, + Description: "Turn off ARP suppression.", + Validators: []validator.Bool{ + tfvalidator.BoolTrue(), + }, + }, "private_vlan": schema.StringAttribute{ Optional: true, Description: "Type of secondary VLAN for private vlan.", @@ -263,6 +270,13 @@ func (rsc *vlan) Schema( tfvalidator.BoolTrue(), }, }, + "translation_vni": schema.Int64Attribute{ + Optional: true, + Description: "Translated VXLAN identifier.", + Validators: []validator.Int64{ + int64validator.Between(1, 16777214), + }, + }, "unreachable_vtep_aging_timer": schema.Int64Attribute{ Optional: true, Description: "Unreachable VXLAN tunnel endpoint removal timer (seconds).", @@ -290,6 +304,7 @@ type vlanData struct { ForwardFloodInput types.String `tfsdk:"forward_flood_input"` IsolatedVlan types.String `tfsdk:"isolated_vlan"` L3Interface types.String `tfsdk:"l3_interface"` + NoARPSuppression types.Bool `tfsdk:"no_arp_suppression"` PrivateVlan types.String `tfsdk:"private_vlan"` ServiceID types.Int64 `tfsdk:"service_id"` VlanID types.String `tfsdk:"vlan_id"` @@ -308,6 +323,7 @@ type vlanConfig struct { ForwardFloodInput types.String `tfsdk:"forward_flood_input"` IsolatedVlan types.String `tfsdk:"isolated_vlan"` L3Interface types.String `tfsdk:"l3_interface"` + NoARPSuppression types.Bool `tfsdk:"no_arp_suppression"` PrivateVlan types.String `tfsdk:"private_vlan"` ServiceID types.Int64 `tfsdk:"service_id"` VlanID types.String `tfsdk:"vlan_id"` @@ -326,6 +342,7 @@ type vlanBlockVxlan struct { IngressNodeReplication types.Bool `tfsdk:"ingress_node_replication"` MulticastGroup types.String `tfsdk:"multicast_group"` OvsdbManaged types.Bool `tfsdk:"ovsdb_managed"` + TranslationVni types.Int64 `tfsdk:"translation_vni"` UnreachableVtepAgingTimer types.Int64 `tfsdk:"unreachable_vtep_aging_timer"` } @@ -648,6 +665,9 @@ func (rscData *vlanData) set( if v := rscData.L3Interface.ValueString(); v != "" { configSet = append(configSet, setPrefix+"l3-interface "+v) } + if rscData.NoARPSuppression.ValueBool() { + configSet = append(configSet, setPrefix+"no-arp-suppression") + } if v := rscData.PrivateVlan.ValueString(); v != "" { configSet = append(configSet, setPrefix+"private-vlan "+v) } @@ -681,6 +701,10 @@ func (rscData *vlanData) set( if rscData.Vxlan.OvsdbManaged.ValueBool() { configSet = append(configSet, setPrefix+"vxlan ovsdb-managed") } + if !rscData.Vxlan.TranslationVni.IsNull() { + configSet = append(configSet, setPrefix+"vxlan translation-vni "+ + utils.ConvI64toa(rscData.Vxlan.TranslationVni.ValueInt64())) + } if !rscData.Vxlan.UnreachableVtepAgingTimer.IsNull() { configSet = append(configSet, setPrefix+"vxlan unreachable-vtep-aging-timer "+ utils.ConvI64toa(rscData.Vxlan.UnreachableVtepAgingTimer.ValueInt64())) @@ -736,6 +760,8 @@ func (rscData *vlanData) read( rscData.IsolatedVlan = types.StringValue(itemTrim) case balt.CutPrefixInString(&itemTrim, "l3-interface "): rscData.L3Interface = types.StringValue(itemTrim) + case itemTrim == "no-arp-suppression": + rscData.NoARPSuppression = types.BoolValue(true) case balt.CutPrefixInString(&itemTrim, "private-vlan "): rscData.PrivateVlan = types.StringValue(itemTrim) case balt.CutPrefixInString(&itemTrim, "service-id "): @@ -782,6 +808,11 @@ func (rscData *vlanData) read( rscData.Vxlan.MulticastGroup = types.StringValue(itemTrim) case itemTrim == "ovsdb-managed": rscData.Vxlan.OvsdbManaged = types.BoolValue(true) + case balt.CutPrefixInString(&itemTrim, "translation-vni "): + rscData.Vxlan.TranslationVni, err = tfdata.ConvAtoi64Value(itemTrim) + if err != nil { + return err + } case balt.CutPrefixInString(&itemTrim, "unreachable-vtep-aging-timer "): rscData.Vxlan.UnreachableVtepAgingTimer, err = tfdata.ConvAtoi64Value(itemTrim) if err != nil { diff --git a/internal/providerfwk/testdata/TestAccResourceVlan_basic/5/main.tf b/internal/providerfwk/testdata/TestAccResourceVlan_basic/5/main.tf index 24475716..5ad906bd 100644 --- a/internal/providerfwk/testdata/TestAccResourceVlan_basic/5/main.tf +++ b/internal/providerfwk/testdata/TestAccResourceVlan_basic/5/main.tf @@ -84,12 +84,14 @@ resource "junos_vlan" "testacc_vlan_ri" { junos_evpn.testacc_vlan_ri, ] - name = "testacc_vlan_ri" - routing_instance = junos_routing_instance.testacc_vlan_ri.name - description = "testacc_vlan_ri" - vlan_id = 1030 + name = "testacc_vlan_ri" + routing_instance = junos_routing_instance.testacc_vlan_ri.name + description = "testacc_vlan_ri" + vlan_id = 1030 + no_arp_suppression = true vxlan { vni = 103010 vni_extend_evpn = true + translation_vni = 1103010 } } From 217890d24f5a13c3c106a292d44c3ebc3246b583 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 19 Apr 2024 01:01:57 +0000 Subject: [PATCH 17/25] deps: bump github.com/hashicorp/terraform-plugin-go Bumps [github.com/hashicorp/terraform-plugin-go](https://github.com/hashicorp/terraform-plugin-go) from 0.22.1 to 0.22.2. - [Release notes](https://github.com/hashicorp/terraform-plugin-go/releases) - [Changelog](https://github.com/hashicorp/terraform-plugin-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/hashicorp/terraform-plugin-go/compare/v0.22.1...v0.22.2) --- updated-dependencies: - dependency-name: github.com/hashicorp/terraform-plugin-go dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 8 ++++---- go.sum | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index f43270a1..d10a1810 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 github.com/hashicorp/terraform-plugin-framework v1.7.0 github.com/hashicorp/terraform-plugin-framework-validators v0.12.0 - github.com/hashicorp/terraform-plugin-go v0.22.1 + github.com/hashicorp/terraform-plugin-go v0.22.2 github.com/hashicorp/terraform-plugin-mux v0.15.0 github.com/hashicorp/terraform-plugin-sdk/v2 v2.33.0 github.com/hashicorp/terraform-plugin-testing v1.7.0 @@ -23,7 +23,7 @@ require ( github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect github.com/cloudflare/circl v1.3.7 // indirect github.com/fatih/color v1.16.0 // indirect - github.com/golang/protobuf v1.5.3 // indirect + github.com/golang/protobuf v1.5.4 // indirect github.com/hashicorp/errwrap v1.0.0 // indirect github.com/hashicorp/go-checkpoint v0.5.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect @@ -59,8 +59,8 @@ require ( golang.org/x/text v0.14.0 // indirect golang.org/x/tools v0.13.0 // indirect google.golang.org/appengine v1.6.8 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect - google.golang.org/grpc v1.62.1 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de // indirect + google.golang.org/grpc v1.63.2 // indirect google.golang.org/protobuf v1.33.0 // indirect ) diff --git a/go.sum b/go.sum index e2865f27..17ac025f 100644 --- a/go.sum +++ b/go.sum @@ -36,8 +36,8 @@ github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4er github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= @@ -76,8 +76,8 @@ github.com/hashicorp/terraform-plugin-framework v1.7.0 h1:wOULbVmfONnJo9iq7/q+iB github.com/hashicorp/terraform-plugin-framework v1.7.0/go.mod h1:jY9Id+3KbZ17OMpulgnWLSfwxNVYSoYBQFTgsx044CI= github.com/hashicorp/terraform-plugin-framework-validators v0.12.0 h1:HOjBuMbOEzl7snOdOoUfE2Jgeto6JOjLVQ39Ls2nksc= github.com/hashicorp/terraform-plugin-framework-validators v0.12.0/go.mod h1:jfHGE/gzjxYz6XoUwi/aYiiKrJDeutQNUtGQXkaHklg= -github.com/hashicorp/terraform-plugin-go v0.22.1 h1:iTS7WHNVrn7uhe3cojtvWWn83cm2Z6ryIUDTRO0EV7w= -github.com/hashicorp/terraform-plugin-go v0.22.1/go.mod h1:qrjnqRghvQ6KnDbB12XeZ4FluclYwptntoWCr9QaXTI= +github.com/hashicorp/terraform-plugin-go v0.22.2 h1:5o8uveu6eZUf5J7xGPV0eY0TPXg3qpmwX9sce03Bxnc= +github.com/hashicorp/terraform-plugin-go v0.22.2/go.mod h1:drq8Snexp9HsbFZddvyLHN6LuWHHndSQg+gV+FPkcIM= github.com/hashicorp/terraform-plugin-log v0.9.0 h1:i7hOA+vdAItN1/7UrfBqBwvYPQ9TFvymaRGZED3FCV0= github.com/hashicorp/terraform-plugin-log v0.9.0/go.mod h1:rKL8egZQ/eXSyDqzLUuwUYLVdlYeamldAHSxjUFADow= github.com/hashicorp/terraform-plugin-mux v0.15.0 h1:+/+lDx0WUsIOpkAmdwBIoFU8UP9o2eZASoOnLsWbKME= @@ -222,10 +222,10 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s= -google.golang.org/grpc v1.62.1 h1:B4n+nfKzOICUXMgyrNd19h/I9oH0L1pizfk1d4zSgTk= -google.golang.org/grpc v1.62.1/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de h1:cZGRis4/ot9uVm639a+rHCUaG0JJHEsdyzSQTMX+suY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:H4O17MA/PE9BsGx3w+a+W2VOLLD1Qf7oJneAoU6WktY= +google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= +google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= From cdab9d8eeccb9a2d4fb0f24702f498cae6842014 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 19 Apr 2024 13:12:21 +0000 Subject: [PATCH 18/25] deps: bump golang.org/x/net from 0.21.0 to 0.23.0 Bumps [golang.org/x/net](https://github.com/golang/net) from 0.21.0 to 0.23.0. - [Commits](https://github.com/golang/net/compare/v0.21.0...v0.23.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-type: indirect ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index f43270a1..a7e18f6a 100644 --- a/go.mod +++ b/go.mod @@ -54,7 +54,7 @@ require ( github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect github.com/zclconf/go-cty v1.14.3 // indirect golang.org/x/mod v0.15.0 // indirect - golang.org/x/net v0.21.0 // indirect + golang.org/x/net v0.23.0 // indirect golang.org/x/sys v0.19.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/tools v0.13.0 // indirect diff --git a/go.sum b/go.sum index e2865f27..1f3fa309 100644 --- a/go.sum +++ b/go.sum @@ -170,8 +170,8 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= -golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= +golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= From ab6d05d85d9a08d976051f2980bb3869908971d0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Apr 2024 07:12:41 +0000 Subject: [PATCH 19/25] deps: bump github.com/hashicorp/terraform-plugin-framework Bumps [github.com/hashicorp/terraform-plugin-framework](https://github.com/hashicorp/terraform-plugin-framework) from 1.7.0 to 1.8.0. - [Release notes](https://github.com/hashicorp/terraform-plugin-framework/releases) - [Changelog](https://github.com/hashicorp/terraform-plugin-framework/blob/main/CHANGELOG.md) - [Commits](https://github.com/hashicorp/terraform-plugin-framework/compare/v1.7.0...v1.8.0) --- updated-dependencies: - dependency-name: github.com/hashicorp/terraform-plugin-framework dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 9c0e94a2..c5c4c345 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.21 require ( github.com/google/go-cmp v0.6.0 github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 - github.com/hashicorp/terraform-plugin-framework v1.7.0 + github.com/hashicorp/terraform-plugin-framework v1.8.0 github.com/hashicorp/terraform-plugin-framework-validators v0.12.0 github.com/hashicorp/terraform-plugin-go v0.22.2 github.com/hashicorp/terraform-plugin-mux v0.15.0 diff --git a/go.sum b/go.sum index d843cd30..3a9f7582 100644 --- a/go.sum +++ b/go.sum @@ -72,8 +72,8 @@ github.com/hashicorp/terraform-exec v0.20.0 h1:DIZnPsqzPGuUnq6cH8jWcPunBfY+C+M8J github.com/hashicorp/terraform-exec v0.20.0/go.mod h1:ckKGkJWbsNqFKV1itgMnE0hY9IYf1HoiekpuN0eWoDw= github.com/hashicorp/terraform-json v0.21.0 h1:9NQxbLNqPbEMze+S6+YluEdXgJmhQykRyRNd+zTI05U= github.com/hashicorp/terraform-json v0.21.0/go.mod h1:qdeBs11ovMzo5puhrRibdD6d2Dq6TyE/28JiU4tIQxk= -github.com/hashicorp/terraform-plugin-framework v1.7.0 h1:wOULbVmfONnJo9iq7/q+iBOBJul5vRovaYJIu2cY/Pw= -github.com/hashicorp/terraform-plugin-framework v1.7.0/go.mod h1:jY9Id+3KbZ17OMpulgnWLSfwxNVYSoYBQFTgsx044CI= +github.com/hashicorp/terraform-plugin-framework v1.8.0 h1:P07qy8RKLcoBkCrY2RHJer5AEvJnDuXomBgou6fD8kI= +github.com/hashicorp/terraform-plugin-framework v1.8.0/go.mod h1:/CpTukO88PcL/62noU7cuyaSJ4Rsim+A/pa+3rUVufY= github.com/hashicorp/terraform-plugin-framework-validators v0.12.0 h1:HOjBuMbOEzl7snOdOoUfE2Jgeto6JOjLVQ39Ls2nksc= github.com/hashicorp/terraform-plugin-framework-validators v0.12.0/go.mod h1:jfHGE/gzjxYz6XoUwi/aYiiKrJDeutQNUtGQXkaHklg= github.com/hashicorp/terraform-plugin-go v0.22.2 h1:5o8uveu6eZUf5J7xGPV0eY0TPXg3qpmwX9sce03Bxnc= From 9ee4c77e09097135d0bc03ffab870a9c7bd085db Mon Sep 17 00:00:00 2001 From: Jeremy Muriel Date: Mon, 22 Apr 2024 09:31:37 +0200 Subject: [PATCH 20/25] go.mod: rewrite go version to 1.N.P --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 9c0e94a2..e26184d0 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/jeremmfr/terraform-provider-junos -go 1.21 +go 1.21.0 require ( github.com/google/go-cmp v0.6.0 From bd5ae7155cb86fc9b367b126053f2453c01b1009 Mon Sep 17 00:00:00 2001 From: Jeremy Muriel Date: Thu, 25 Apr 2024 09:09:11 +0200 Subject: [PATCH 21/25] add junos_forwardingoptions_evpn_vxlan resource Partial fix #645 --- .changes/issue-645.md | 4 + .../resources/forwardingoptions_evpn_vxlan.md | 48 +++ docs/resources/forwardingoptions_sampling.md | 2 +- internal/providerfwk/provider.go | 1 + .../providerfwk/resource_bridge_domain.go | 2 +- .../resource_forwardingoptions_evpn_vxlan.go | 378 ++++++++++++++++++ ...ource_forwardingoptions_evpn_vxlan_test.go | 28 ++ .../1/main.tf | 3 + .../2/main.tf | 8 + 9 files changed, 472 insertions(+), 2 deletions(-) create mode 100644 .changes/issue-645.md create mode 100644 docs/resources/forwardingoptions_evpn_vxlan.md create mode 100644 internal/providerfwk/resource_forwardingoptions_evpn_vxlan.go create mode 100644 internal/providerfwk/resource_forwardingoptions_evpn_vxlan_test.go create mode 100644 internal/providerfwk/testdata/TestAccResourceForwardingoptionsEvpnVxlan_basic/1/main.tf create mode 100644 internal/providerfwk/testdata/TestAccResourceForwardingoptionsEvpnVxlan_basic/2/main.tf diff --git a/.changes/issue-645.md b/.changes/issue-645.md new file mode 100644 index 00000000..220b8209 --- /dev/null +++ b/.changes/issue-645.md @@ -0,0 +1,4 @@ + +FEATURES: + +* add **junos_forwardingoptions_evpn_vxlan** resource (Partial Fix [#645](https://github.com/jeremmfr/terraform-provider-junos/issues/645)) diff --git a/docs/resources/forwardingoptions_evpn_vxlan.md b/docs/resources/forwardingoptions_evpn_vxlan.md new file mode 100644 index 00000000..fe4a908b --- /dev/null +++ b/docs/resources/forwardingoptions_evpn_vxlan.md @@ -0,0 +1,48 @@ +--- +page_title: "Junos: junos_forwardingoptions_evpn_vxlan" +--- + +# junos_forwardingoptions_evpn_vxlan + +-> **Note:** This resource should only be created **once** for root level or each routing-instance. +It's used to configure static (not object) options in `forwarding-options evpn-vxlan` block in root or +routing-instance level. + +Configure static configuration in `forwarding-options evpn-vxlan` block for root or +routing-instance level. + +## Example Usage + +```hcl +# Configure forwarding-options evpn-vxlan +resource "junos_forwardingoptions_evpn_vxlan" "demo" { + shared_tunnels = true +} +``` + +## Argument Reference + +The following arguments are supported: + +- **routing_instance** (Optional, String, Forces new resource) + Routing instance if not root level. + Need to be `default` or name of routing instance. + Defaults to `default` +- **shared_tunnels** (Optional, Boolean) + Create VTEP tunnels to EVPN PE. + +## Attribute Reference + +The following attributes are exported: + +- **id** (String) + An identifier for the resource with format ``. + +## Import + +Junos forwarding-options evpn-vxlan can be imported using an id made up of +``, e.g. + +```shell +$ terraform import junos_forwardingoptions_evpn_vxlan.demo default +``` diff --git a/docs/resources/forwardingoptions_sampling.md b/docs/resources/forwardingoptions_sampling.md index 59450375..e7981fe4 100644 --- a/docs/resources/forwardingoptions_sampling.md +++ b/docs/resources/forwardingoptions_sampling.md @@ -183,5 +183,5 @@ Junos forwarding-options sampling can be imported using an id made up of ``, e.g. ```shell -$ terraform import junos_forwardingoptions_sampling_instance.demo default +$ terraform import junos_forwardingoptions_sampling.demo default ``` diff --git a/internal/providerfwk/provider.go b/internal/providerfwk/provider.go index ff05f24e..ee015c7c 100644 --- a/internal/providerfwk/provider.go +++ b/internal/providerfwk/provider.go @@ -239,6 +239,7 @@ func (p *junosProvider) Resources(_ context.Context) []func() resource.Resource newEvpnResource, newFirewallFilterResource, newFirewallPolicerResource, + newForwardingoptionsEvpnVxlanResource, newForwardingoptionsSamplingResource, newForwardingoptionsSamplingInstanceResource, newForwardingoptionsStormControlProfileResource, diff --git a/internal/providerfwk/resource_bridge_domain.go b/internal/providerfwk/resource_bridge_domain.go index 9ef51235..48cd2921 100644 --- a/internal/providerfwk/resource_bridge_domain.go +++ b/internal/providerfwk/resource_bridge_domain.go @@ -339,7 +339,7 @@ func (rsc *bridgeDomain) ValidateConfig( resp.Diagnostics.AddAttributeError( path.Root("name"), tfdiag.MissingConfigErrSummary, - "At least one of arguments need to be set (in addition to `name` and `routing_instance`)", + "at least one of arguments need to be set (in addition to `name` and `routing_instance`)", ) } diff --git a/internal/providerfwk/resource_forwardingoptions_evpn_vxlan.go b/internal/providerfwk/resource_forwardingoptions_evpn_vxlan.go new file mode 100644 index 00000000..acad3e33 --- /dev/null +++ b/internal/providerfwk/resource_forwardingoptions_evpn_vxlan.go @@ -0,0 +1,378 @@ +package providerfwk + +import ( + "context" + "fmt" + "strings" + + "github.com/jeremmfr/terraform-provider-junos/internal/junos" + "github.com/jeremmfr/terraform-provider-junos/internal/tfdata" + "github.com/jeremmfr/terraform-provider-junos/internal/tfdiag" + "github.com/jeremmfr/terraform-provider-junos/internal/tfvalidator" + + "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/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" +) + +// Ensure the implementation satisfies the expected interfaces. +var ( + _ resource.Resource = &forwardingoptionsEvpnVxlan{} + _ resource.ResourceWithConfigure = &forwardingoptionsEvpnVxlan{} + _ resource.ResourceWithValidateConfig = &forwardingoptionsEvpnVxlan{} + _ resource.ResourceWithImportState = &forwardingoptionsEvpnVxlan{} +) + +type forwardingoptionsEvpnVxlan struct { + client *junos.Client +} + +func newForwardingoptionsEvpnVxlanResource() resource.Resource { + return &forwardingoptionsEvpnVxlan{} +} + +func (rsc *forwardingoptionsEvpnVxlan) typeName() string { + return providerName + "_forwardingoptions_evpn_vxlan" +} + +func (rsc *forwardingoptionsEvpnVxlan) junosName() string { + return "forwarding-options evpn-vxlan" +} + +func (rsc *forwardingoptionsEvpnVxlan) junosClient() *junos.Client { + return rsc.client +} + +func (rsc *forwardingoptionsEvpnVxlan) Metadata( + _ context.Context, _ resource.MetadataRequest, resp *resource.MetadataResponse, +) { + resp.TypeName = rsc.typeName() +} + +func (rsc *forwardingoptionsEvpnVxlan) Configure( + ctx context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse, +) { + // Prevent panic if the provider has not been configured. + if req.ProviderData == nil { + return + } + client, ok := req.ProviderData.(*junos.Client) + if !ok { + unexpectedResourceConfigureType(ctx, req, resp) + + return + } + rsc.client = client +} + +func (rsc *forwardingoptionsEvpnVxlan) Schema( + _ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse, +) { + resp.Schema = schema.Schema{ + Description: "Configure static configuration in `" + rsc.junosName() + "` block", + Attributes: map[string]schema.Attribute{ + "id": schema.StringAttribute{ + Computed: true, + Description: "An identifier for the resource with format ``.", + PlanModifiers: []planmodifier.String{ + stringplanmodifier.UseStateForUnknown(), + }, + }, + "routing_instance": schema.StringAttribute{ + Optional: true, + Computed: true, + Default: stringdefault.StaticString(junos.DefaultW), + Description: "Routing instance if not root level.", + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + }, + Validators: []validator.String{ + stringvalidator.LengthBetween(1, 63), + tfvalidator.StringFormat(tfvalidator.DefaultFormat), + }, + }, + "shared_tunnels": schema.BoolAttribute{ + Optional: true, + Description: "Create VTEP tunnels to EVPN PE.", + Validators: []validator.Bool{ + tfvalidator.BoolTrue(), + }, + }, + }, + } +} + +type forwardingoptionsEvpnVxlanData struct { + ID types.String `tfsdk:"id"` + RoutingInstance types.String `tfsdk:"routing_instance"` + SharedTunnels types.Bool `tfsdk:"shared_tunnels"` +} + +func (rscData *forwardingoptionsEvpnVxlanData) isEmpty() bool { + return tfdata.CheckBlockIsEmpty(rscData, "ID", "RoutingInstance") +} + +func (rsc *forwardingoptionsEvpnVxlan) ValidateConfig( + ctx context.Context, req resource.ValidateConfigRequest, resp *resource.ValidateConfigResponse, +) { + var config forwardingoptionsEvpnVxlanData + resp.Diagnostics.Append(req.Config.Get(ctx, &config)...) + if resp.Diagnostics.HasError() { + return + } + + if config.isEmpty() { + resp.Diagnostics.AddAttributeError( + path.Root("routing_instance"), + tfdiag.MissingConfigErrSummary, + "at least one of arguments need to be set (in addition to `routing_instance`)", + ) + } +} + +func (rsc *forwardingoptionsEvpnVxlan) Create( + ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse, +) { + var plan forwardingoptionsEvpnVxlanData + resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) + if resp.Diagnostics.HasError() { + return + } + + defaultResourceCreate( + ctx, + rsc, + func(fnCtx context.Context, junSess *junos.Session) bool { + if v := plan.RoutingInstance.ValueString(); v != "" && v != junos.DefaultW { + instanceExists, err := checkRoutingInstanceExists(fnCtx, v, junSess) + if err != nil { + resp.Diagnostics.AddError(tfdiag.PreCheckErrSummary, err.Error()) + + return false + } + if !instanceExists { + resp.Diagnostics.AddAttributeError( + path.Root("routing_instance"), + tfdiag.MissingConfigErrSummary, + fmt.Sprintf("routing instance %q doesn't exist", v), + ) + + return false + } + } + + return true + }, + nil, + &plan, + resp, + ) +} + +func (rsc *forwardingoptionsEvpnVxlan) Read( + ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse, +) { + var state, data forwardingoptionsEvpnVxlanData + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + + junSess, err := rsc.client.StartNewSession(ctx) + if err != nil { + resp.Diagnostics.AddError(tfdiag.StartSessErrSummary, err.Error()) + + return + } + defer junSess.Close() + + junos.MutexLock() + defer junos.MutexUnlock() + + if v := state.RoutingInstance.ValueString(); v != "" && v != junos.DefaultW { + instanceExists, err := checkRoutingInstanceExists(ctx, v, junSess) + if err != nil { + resp.Diagnostics.AddError(tfdiag.ConfigReadErrSummary, err.Error()) + + return + } + if !instanceExists { + resp.State.RemoveResource(ctx) + + return + } + } + if err := data.read(ctx, state.RoutingInstance.ValueString(), junSess); err != nil { + resp.Diagnostics.AddError(tfdiag.ConfigReadErrSummary, err.Error()) + + return + } + if data.ID.IsNull() { + resp.State.RemoveResource(ctx) + + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} + +func (rsc *forwardingoptionsEvpnVxlan) Update( + ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse, +) { + var plan, state forwardingoptionsEvpnVxlanData + resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + + defaultResourceUpdate( + ctx, + rsc, + &state, + &plan, + resp, + ) +} + +func (rsc *forwardingoptionsEvpnVxlan) Delete( + ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse, +) { + var state forwardingoptionsEvpnVxlanData + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + + defaultResourceDelete( + ctx, + rsc, + &state, + resp, + ) +} + +func (rsc *forwardingoptionsEvpnVxlan) ImportState( + ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse, +) { + junSess, err := rsc.client.StartNewSession(ctx) + if err != nil { + resp.Diagnostics.AddError(tfdiag.StartSessErrSummary, err.Error()) + + return + } + defer junSess.Close() + + var data forwardingoptionsEvpnVxlanData + if req.ID != junos.DefaultW { + instanceExists, err := checkRoutingInstanceExists(ctx, req.ID, junSess) + if err != nil { + resp.Diagnostics.AddError(tfdiag.ConfigReadErrSummary, err.Error()) + + return + } + if !instanceExists { + resp.Diagnostics.AddError( + tfdiag.NotFoundErrSummary, + fmt.Sprintf("routing instance %q doesn't exist", req.ID), + ) + + return + } + } + if err := data.read(ctx, req.ID, junSess); err != nil { + resp.Diagnostics.AddError(tfdiag.ConfigReadErrSummary, err.Error()) + + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, data)...) +} + +func (rscData *forwardingoptionsEvpnVxlanData) fillID() { + if v := rscData.RoutingInstance.ValueString(); v != "" { + rscData.ID = types.StringValue(v) + } else { + rscData.ID = types.StringValue(junos.DefaultW) + } +} + +func (rscData *forwardingoptionsEvpnVxlanData) set( + _ context.Context, junSess *junos.Session, +) ( + path.Path, error, +) { + configSet := make([]string, 0) + setPrefix := junos.SetLS + if v := rscData.RoutingInstance.ValueString(); v != "" && v != junos.DefaultW { + setPrefix = junos.SetRoutingInstances + v + " " + } + setPrefix += "forwarding-options evpn-vxlan " + + if rscData.SharedTunnels.ValueBool() { + configSet = append(configSet, setPrefix+"shared-tunnels") + } + + return path.Empty(), junSess.ConfigSet(configSet) +} + +func (rscData *forwardingoptionsEvpnVxlanData) read( + _ context.Context, routingInstance string, junSess *junos.Session, +) ( + err error, +) { + showPrefix := junos.CmdShowConfig + if routingInstance != "" && routingInstance != junos.DefaultW { + showPrefix += junos.RoutingInstancesWS + routingInstance + " " + } + + showConfig, err := junSess.Command(showPrefix + + "forwarding-options evpn-vxlan" + junos.PipeDisplaySetRelative) + if err != nil { + return err + } + if routingInstance == "" { + rscData.RoutingInstance = types.StringValue(junos.DefaultW) + } else { + rscData.RoutingInstance = types.StringValue(routingInstance) + } + rscData.fillID() + if showConfig != junos.EmptyW { + for _, item := range strings.Split(showConfig, "\n") { + if strings.Contains(item, junos.XMLStartTagConfigOut) { + continue + } + if strings.Contains(item, junos.XMLEndTagConfigOut) { + break + } + itemTrim := strings.TrimPrefix(item, junos.SetLS) + if itemTrim == "shared-tunnels" { + rscData.SharedTunnels = types.BoolValue(true) + } + } + } + + return nil +} + +func (rscData *forwardingoptionsEvpnVxlanData) del( + _ context.Context, junSess *junos.Session, +) error { + delPrefix := junos.DeleteLS + if v := rscData.RoutingInstance.ValueString(); v != "" && v != junos.DefaultW { + delPrefix = junos.DelRoutingInstances + v + " " + } + delPrefix += "forwarding-options evpn-vxlan " + + configSet := []string{ + delPrefix + "shared-tunnels", + } + + return junSess.ConfigSet(configSet) +} diff --git a/internal/providerfwk/resource_forwardingoptions_evpn_vxlan_test.go b/internal/providerfwk/resource_forwardingoptions_evpn_vxlan_test.go new file mode 100644 index 00000000..8b9b8530 --- /dev/null +++ b/internal/providerfwk/resource_forwardingoptions_evpn_vxlan_test.go @@ -0,0 +1,28 @@ +package providerfwk_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/config" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" +) + +func TestAccResourceForwardingoptionsEvpnVxlan_basic(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProtoV5ProviderFactories: testAccProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + ConfigDirectory: config.TestStepDirectory(), + }, + { + ConfigDirectory: config.TestStepDirectory(), + }, + { + ResourceName: "junos_forwardingoptions_evpn_vxlan.ri", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} diff --git a/internal/providerfwk/testdata/TestAccResourceForwardingoptionsEvpnVxlan_basic/1/main.tf b/internal/providerfwk/testdata/TestAccResourceForwardingoptionsEvpnVxlan_basic/1/main.tf new file mode 100644 index 00000000..f6635030 --- /dev/null +++ b/internal/providerfwk/testdata/TestAccResourceForwardingoptionsEvpnVxlan_basic/1/main.tf @@ -0,0 +1,3 @@ +resource "junos_forwardingoptions_evpn_vxlan" "root" { + shared_tunnels = true +} diff --git a/internal/providerfwk/testdata/TestAccResourceForwardingoptionsEvpnVxlan_basic/2/main.tf b/internal/providerfwk/testdata/TestAccResourceForwardingoptionsEvpnVxlan_basic/2/main.tf new file mode 100644 index 00000000..431bf419 --- /dev/null +++ b/internal/providerfwk/testdata/TestAccResourceForwardingoptionsEvpnVxlan_basic/2/main.tf @@ -0,0 +1,8 @@ +resource "junos_forwardingoptions_evpn_vxlan" "ri" { + routing_instance = junos_routing_instance.fwOpts_evpn_vxlan.name + shared_tunnels = true +} + +resource "junos_routing_instance" "fwOpts_evpn_vxlan" { + name = "fwOpts_evpn_vxlan" +} From bfc2cc3b7dde4044d2c55ab80a9af1df83bc06fa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 26 Apr 2024 00:47:25 +0000 Subject: [PATCH 22/25] workflows: bump golangci/golangci-lint-action from 4 to 5 Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 4 to 5. - [Release notes](https://github.com/golangci/golangci-lint-action/releases) - [Commits](https://github.com/golangci/golangci-lint-action/compare/v4...v5) --- updated-dependencies: - dependency-name: golangci/golangci-lint-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/linters.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/linters.yml b/.github/workflows/linters.yml index d66917b7..3db9705a 100644 --- a/.github/workflows/linters.yml +++ b/.github/workflows/linters.yml @@ -17,7 +17,7 @@ jobs: - name: Check out code uses: actions/checkout@v4 - name: golangci-lint - uses: golangci/golangci-lint-action@v4 + uses: golangci/golangci-lint-action@v5 with: version: 'v1.57.1' args: -c .golangci.yml -v From 45026bcd91ffff8c154aa71f357d5ffc960887bc Mon Sep 17 00:00:00 2001 From: Jeremy Muriel Date: Tue, 30 Apr 2024 13:48:52 +0200 Subject: [PATCH 23/25] r/vlan: tests: fix Junos device type to test state upgrade --- .../providerfwk/upgradestate_vlan_test.go | 29 ++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/internal/providerfwk/upgradestate_vlan_test.go b/internal/providerfwk/upgradestate_vlan_test.go index 6cfccb18..647c5edf 100644 --- a/internal/providerfwk/upgradestate_vlan_test.go +++ b/internal/providerfwk/upgradestate_vlan_test.go @@ -1,6 +1,7 @@ package providerfwk_test import ( + "os" "testing" "github.com/hashicorp/terraform-plugin-testing/config" @@ -10,20 +11,22 @@ import ( // export TESTACC_INTERFACE= for choose interface available else it's ge-0/0/3. func TestAccUpgradeStateResourceVlan_V0toV1_basic(t *testing.T) { - resource.Test(t, resource.TestCase{ - Steps: []resource.TestStep{ - { - ConfigDirectory: config.TestStepDirectory(), - }, - { - ProtoV5ProviderFactories: testAccProtoV5ProviderFactories, - ConfigDirectory: config.TestStepDirectory(), - ConfigPlanChecks: resource.ConfigPlanChecks{ - PreApply: []plancheck.PlanCheck{ - plancheck.ExpectEmptyPlan(), + if os.Getenv("TESTACC_SWITCH") != "" { + resource.Test(t, resource.TestCase{ + Steps: []resource.TestStep{ + { + ConfigDirectory: config.TestStepDirectory(), + }, + { + ProtoV5ProviderFactories: testAccProtoV5ProviderFactories, + ConfigDirectory: config.TestStepDirectory(), + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectEmptyPlan(), + }, }, }, }, - }, - }) + }) + } } From cc9c30ecb698f314fa60d00104e33fe99e937c3a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 3 May 2024 14:39:54 +0000 Subject: [PATCH 24/25] deps: bump github.com/jeremmfr/go-netconf from 0.4.15 to 0.5.0 Bumps [github.com/jeremmfr/go-netconf](https://github.com/jeremmfr/go-netconf) from 0.4.15 to 0.5.0. - [Changelog](https://github.com/jeremmfr/go-netconf/blob/master/CHANGELOG.md) - [Commits](https://github.com/jeremmfr/go-netconf/compare/v0.4.15...v0.5.0) --- updated-dependencies: - dependency-name: github.com/jeremmfr/go-netconf dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 18 ++---------------- 2 files changed, 3 insertions(+), 17 deletions(-) diff --git a/go.mod b/go.mod index 81a274c2..b82614dc 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/hashicorp/terraform-plugin-mux v0.15.0 github.com/hashicorp/terraform-plugin-sdk/v2 v2.33.0 github.com/hashicorp/terraform-plugin-testing v1.7.0 - github.com/jeremmfr/go-netconf v0.4.15 + github.com/jeremmfr/go-netconf v0.5.0 github.com/jeremmfr/go-utils v0.12.0 github.com/jeremmfr/junosdecode v1.1.1 golang.org/x/crypto v0.22.0 diff --git a/go.sum b/go.sum index 3a9f7582..b056c9db 100644 --- a/go.sum +++ b/go.sum @@ -92,8 +92,8 @@ github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= -github.com/jeremmfr/go-netconf v0.4.15 h1:Be6g52yxn1ic96QVzhYplsq8i6vxyo1c+IsvwMpXVdo= -github.com/jeremmfr/go-netconf v0.4.15/go.mod h1:DvCOMF9k/yIwLdp6apMNL1WWJzijIua3JNTFIZucfTI= +github.com/jeremmfr/go-netconf v0.5.0 h1:LBJlCWtIyLOwBP+XimsvaENkW2Lu/pcrwvqwMaF07Oc= +github.com/jeremmfr/go-netconf v0.5.0/go.mod h1:vmrY4taeCX3ZNGT23mqCA55EG1wOwlIH+/kgIhYpmHA= github.com/jeremmfr/go-utils v0.12.0 h1:Zgdb+LLeyds9Tbsl+tjqRNBcAVQC5WZOm4Tx9c+dVdg= github.com/jeremmfr/go-utils v0.12.0/go.mod h1:UrdaUGOZaha7uxCFaJXNSOUKx9cnbbfMP+08acDxIzc= github.com/jeremmfr/junosdecode v1.1.1 h1:wOFfJIwLXP9s0eQzzAhuX7a7N1mc+AWgDLYAmR7VoWg= @@ -157,25 +157,20 @@ github.com/zclconf/go-cty v1.14.3 h1:1JXy1XroaGrzZuG6X9dt7HL6s9AwbY+l4UNL8o5B6ho github.com/zclconf/go-cty v1.14.3/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.15.0 h1:SernR4v+D55NyBH2QiEQrlBAnj1ECL6AGrA5+dPaMY8= golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -189,17 +184,11 @@ golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= -golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q= golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -207,14 +196,11 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From bf38653c240d62684eee9f17ea9f22378181850f Mon Sep 17 00:00:00 2001 From: Jeremy Muriel Date: Fri, 3 May 2024 17:03:41 +0200 Subject: [PATCH 25/25] Release v2.7.0 --- .changes/issue-641.md | 10 ---------- .changes/issue-644.md | 8 -------- .changes/issue-645.md | 4 ---- .changes/issue-646.md | 26 ------------------------ .changes/ospf-with-fwk.md | 17 ---------------- CHANGELOG.md | 42 +++++++++++++++++++++++++++++++++++++++ 6 files changed, 42 insertions(+), 65 deletions(-) delete mode 100644 .changes/issue-641.md delete mode 100644 .changes/issue-644.md delete mode 100644 .changes/issue-645.md delete mode 100644 .changes/issue-646.md delete mode 100644 .changes/ospf-with-fwk.md diff --git a/.changes/issue-641.md b/.changes/issue-641.md deleted file mode 100644 index 78bed4aa..00000000 --- a/.changes/issue-641.md +++ /dev/null @@ -1,10 +0,0 @@ - -FEATURES: - -ENHANCEMENTS: - -* **data-source/junos_interfaces_physical_present**: - * add `interfaces` block map attribute with same attributes as `interface_statuses` and additional `logical_interface_names` attribute (Fix [#641](https://github.com/jeremmfr/terraform-provider-junos/issues/641)) - * deprecate `interface_statuses` attribute (read the `interfaces` attribute instead) - -BUG FIXES: diff --git a/.changes/issue-644.md b/.changes/issue-644.md deleted file mode 100644 index 5cc537cc..00000000 --- a/.changes/issue-644.md +++ /dev/null @@ -1,8 +0,0 @@ - -FEATURES: - -ENHANCEMENTS: - -* **resource/junos_evpn**: add `no_core_isolation` argument (Fix [#644](https://github.com/jeremmfr/terraform-provider-junos/issues/644)) - -BUG FIXES: diff --git a/.changes/issue-645.md b/.changes/issue-645.md deleted file mode 100644 index 220b8209..00000000 --- a/.changes/issue-645.md +++ /dev/null @@ -1,4 +0,0 @@ - -FEATURES: - -* add **junos_forwardingoptions_evpn_vxlan** resource (Partial Fix [#645](https://github.com/jeremmfr/terraform-provider-junos/issues/645)) diff --git a/.changes/issue-646.md b/.changes/issue-646.md deleted file mode 100644 index 2e318ff5..00000000 --- a/.changes/issue-646.md +++ /dev/null @@ -1,26 +0,0 @@ - -FEATURES: - -ENHANCEMENTS: - -* **resource/junos_vlan**: - * resource now use new [terraform-plugin-framework](https://github.com/hashicorp/terraform-plugin-framework) - some of config errors are now sent during Plan instead of during Apply - optional boolean attributes doesn't accept value *false* - optional string attributes doesn't accept *empty* value - the resource schema has been upgraded to have one-blocks in single mode instead of list - * `community_vlans` argument is now a Set of String (instead of Set of Number) to accept VLAN name in addition to VLAN id - data in the state has been updated for the new format - Number in config is automatically converted to String by Terraform - * `isolated_vlan` argument is now a String (instead of Number) to accept VLAN name in addition to VLAN id - data in the state has been updated for the new format - Number in config is automatically converted to String by Terraform - * `vlan_id` argument is now a String (instead of Number) to accept `all` or `none` in addition to VLAN id - data in the state has been updated for the new format - Number in config is automatically converted to String by Terraform - * add `routing_instance` argument (Partial fix [#646](https://github.com/jeremmfr/terraform-provider-junos/issues/646)) - and therefore `id` format has been changed to `_-_` (instead of ``) - * add `no_arp_suppression` argument (Partial fix [#646](https://github.com/jeremmfr/terraform-provider-junos/issues/646)) - * add `translation_vni` argument inside `vxlan` block argument - -BUG FIXES: diff --git a/.changes/ospf-with-fwk.md b/.changes/ospf-with-fwk.md deleted file mode 100644 index 1d52761b..00000000 --- a/.changes/ospf-with-fwk.md +++ /dev/null @@ -1,17 +0,0 @@ - -FEATURES: - -ENHANCEMENTS: - -* **resource/junos_ospf_area**: resource now use new [terraform-plugin-framework](https://github.com/hashicorp/terraform-plugin-framework) - some of config errors are now sent during Plan instead of during Apply - optional boolean attributes doesn't accept value *false* - optional string attributes doesn't accept *empty* value - the resource schema has been upgraded to have one-blocks in single mode instead of list -* **resource/junos_ospf**: resource now use new [terraform-plugin-framework](https://github.com/hashicorp/terraform-plugin-framework) - some of config errors are now sent during Plan instead of during Apply - optional boolean attributes doesn't accept value *false* - optional string attributes doesn't accept *empty* value - the resource schema has been upgraded to have one-blocks in single mode instead of list - -BUG FIXES: diff --git a/CHANGELOG.md b/CHANGELOG.md index 33fd085b..22a38b9c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,48 @@ # changelog +## v2.7.0 (2024-05-03) + +FEATURES: + +* add **junos_forwardingoptions_evpn_vxlan** resource (Partial Fix [#645](https://github.com/jeremmfr/terraform-provider-junos/issues/645)) + +ENHANCEMENTS: + +* **data-source/junos_interfaces_physical_present**: + * add `interfaces` block map attribute with same attributes as `interface_statuses` and additional `logical_interface_names` attribute (Fix [#641](https://github.com/jeremmfr/terraform-provider-junos/issues/641)) + * deprecate `interface_statuses` attribute (read the `interfaces` attribute instead) +* **resource/junos_evpn**: add `no_core_isolation` argument (Fix [#644](https://github.com/jeremmfr/terraform-provider-junos/issues/644)) +* **resource/junos_ospf_area**: resource now use new [terraform-plugin-framework](https://github.com/hashicorp/terraform-plugin-framework) + some of config errors are now sent during Plan instead of during Apply + optional boolean attributes doesn't accept value *false* + optional string attributes doesn't accept *empty* value + the resource schema has been upgraded to have one-blocks in single mode instead of list +* **resource/junos_ospf**: resource now use new [terraform-plugin-framework](https://github.com/hashicorp/terraform-plugin-framework) + some of config errors are now sent during Plan instead of during Apply + optional boolean attributes doesn't accept value *false* + optional string attributes doesn't accept *empty* value + the resource schema has been upgraded to have one-blocks in single mode instead of list +* **resource/junos_vlan**: + * resource now use new [terraform-plugin-framework](https://github.com/hashicorp/terraform-plugin-framework) + some of config errors are now sent during Plan instead of during Apply + optional boolean attributes doesn't accept value *false* + optional string attributes doesn't accept *empty* value + the resource schema has been upgraded to have one-blocks in single mode instead of list + * `community_vlans` argument is now a Set of String (instead of Set of Number) to accept VLAN name in addition to VLAN id + data in the state has been updated for the new format + Number in config is automatically converted to String by Terraform + * `isolated_vlan` argument is now a String (instead of Number) to accept VLAN name in addition to VLAN id + data in the state has been updated for the new format + Number in config is automatically converted to String by Terraform + * `vlan_id` argument is now a String (instead of Number) to accept `all` or `none` in addition to VLAN id + data in the state has been updated for the new format + Number in config is automatically converted to String by Terraform + * add `routing_instance` argument (Partial fix [#646](https://github.com/jeremmfr/terraform-provider-junos/issues/646)) + and therefore `id` format has been changed to `_-_` (instead of ``) + * add `no_arp_suppression` argument (Partial fix [#646](https://github.com/jeremmfr/terraform-provider-junos/issues/646)) + * add `translation_vni` argument inside `vxlan` block argument + ## v2.6.0 (2024-03-13) FEATURES: