diff --git a/CHANGELOG.md b/CHANGELOG.md index 69f2a725..415d128a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,8 @@ - Add support for leaf-lists to `iosxr_gnmi` resource - Add `port` and `operator` attributes to `iosxr_logging_vrf` resource and data source - Add `iosxr_router_hsrp_interface_address_family_ipv6_group_v2` resource and data source -- Add `route_reflector_client` to `iosxr_router_bgp_neighbor_address_family` and `iosxr_router_bgp_neighbor_group` resource and data source +- Add `route_reflector_client` attribute to `iosxr_router_bgp_neighbor_address_family` and `iosxr_router_bgp_neighbor_group` resource and data source +- Add `communities` attributes to `iosxr_snmp_server` resource and data source ## 0.2.5 diff --git a/docs/data-sources/snmp_server.md b/docs/data-sources/snmp_server.md index 3897e191..8cb82bcd 100644 --- a/docs/data-sources/snmp_server.md +++ b/docs/data-sources/snmp_server.md @@ -30,6 +30,7 @@ data "iosxr_snmp_server" "example" { - `bgp_bgp4_mib_updown` (Boolean) Enable CISCO-BGP4-MIB v2 up/down traps - `bgp_cbgp2_updown` (Boolean) Enable CISCO-BGP4-MIB v2 up/down traps - `bridgemib` (Boolean) Enable SNMP Trap for Bridge MIB +- `communities` (Attributes List) The UNENCRYPTED (cleartext) community string (see [below for nested schema](#nestedatt--communities)) - `config` (Boolean) Enable SNMP config traps - `contact` (String) Text for mib Object sysContact - `copy_complete` (Boolean) Enable CISCO-CONFIG-COPY-MIB ccCopyCompletion traps @@ -73,6 +74,21 @@ data "iosxr_snmp_server" "example" { - `traps_snmp_linkup` (Boolean) Enable SNMPv2-MIB linkUp traps - `users` (Attributes List) Name of the user (see [below for nested schema](#nestedatt--users)) + +### Nested Schema for `communities` + +Read-Only: + +- `community` (String) The UNENCRYPTED (cleartext) community string +- `ipv4` (String) Type of Access-list +- `ipv6` (String) Type of Access-list +- `ro` (Boolean) Read-only community +- `rw` (Boolean) Read-write community +- `sdrowner` (Boolean) SDR Owner permissions for MIB Objects +- `systemowner` (Boolean) System Owner permissions for MIB objects +- `view` (String) Restrict this community to a named view + + ### Nested Schema for `groups` diff --git a/docs/guides/changelog.md b/docs/guides/changelog.md index 8535392b..57fbecfe 100644 --- a/docs/guides/changelog.md +++ b/docs/guides/changelog.md @@ -13,7 +13,8 @@ description: |- - Add support for leaf-lists to `iosxr_gnmi` resource - Add `port` and `operator` attributes to `iosxr_logging_vrf` resource and data source - Add `iosxr_router_hsrp_interface_address_family_ipv6_group_v2` resource and data source -- Add `route_reflector_client` to `iosxr_router_bgp_neighbor_address_family` and `iosxr_router_bgp_neighbor_group` resource and data source +- Add `route_reflector_client` attribute to `iosxr_router_bgp_neighbor_address_family` and `iosxr_router_bgp_neighbor_group` resource and data source +- Add `communities` attributes to `iosxr_snmp_server` resource and data source ## 0.2.5 diff --git a/docs/resources/snmp_server.md b/docs/resources/snmp_server.md index 0c04bafd..b69fd623 100644 --- a/docs/resources/snmp_server.md +++ b/docs/resources/snmp_server.md @@ -58,6 +58,18 @@ resource "iosxr_snmp_server" "example" { v3_ipv6 = "ACL2" } ] + communities = [ + { + community = "COMMUNITY1" + view = "VIEW1" + ro = true + rw = false + sdrowner = false + systemowner = true + ipv4 = "ACL1" + ipv6 = "ACL2" + } + ] } ``` @@ -70,6 +82,7 @@ resource "iosxr_snmp_server" "example" { - `bgp_bgp4_mib_updown` (Boolean) Enable CISCO-BGP4-MIB v2 up/down traps - `bgp_cbgp2_updown` (Boolean) Enable CISCO-BGP4-MIB v2 up/down traps - `bridgemib` (Boolean) Enable SNMP Trap for Bridge MIB +- `communities` (Attributes List) The UNENCRYPTED (cleartext) community string (see [below for nested schema](#nestedatt--communities)) - `config` (Boolean) Enable SNMP config traps - `contact` (String) Text for mib Object sysContact - `copy_complete` (Boolean) Enable CISCO-CONFIG-COPY-MIB ccCopyCompletion traps @@ -157,6 +170,24 @@ resource "iosxr_snmp_server" "example" { - `id` (String) The path of the object. + +### Nested Schema for `communities` + +Required: + +- `community` (String) The UNENCRYPTED (cleartext) community string + +Optional: + +- `ipv4` (String) Type of Access-list +- `ipv6` (String) Type of Access-list +- `ro` (Boolean) Read-only community +- `rw` (Boolean) Read-write community +- `sdrowner` (Boolean) SDR Owner permissions for MIB Objects +- `systemowner` (Boolean) System Owner permissions for MIB objects +- `view` (String) Restrict this community to a named view + + ### Nested Schema for `groups` diff --git a/examples/resources/iosxr_snmp_server/resource.tf b/examples/resources/iosxr_snmp_server/resource.tf index 27c3ff26..f39ea5a3 100644 --- a/examples/resources/iosxr_snmp_server/resource.tf +++ b/examples/resources/iosxr_snmp_server/resource.tf @@ -43,4 +43,16 @@ resource "iosxr_snmp_server" "example" { v3_ipv6 = "ACL2" } ] + communities = [ + { + community = "COMMUNITY1" + view = "VIEW1" + ro = true + rw = false + sdrowner = false + systemowner = true + ipv4 = "ACL1" + ipv6 = "ACL2" + } + ] } diff --git a/gen/definitions/snmp_server.yaml b/gen/definitions/snmp_server.yaml index 1b77a4fb..0fd042e9 100644 --- a/gen/definitions/snmp_server.yaml +++ b/gen/definitions/snmp_server.yaml @@ -161,3 +161,25 @@ attributes: example: ACL1 - yang_name: v3/ipv6 example: ACL2 + - yang_name: community/unencrypted/unencrypted-string + tf_name: communities + type: List + attributes: + - yang_name: community-string + tf_name: community + id: true + example: COMMUNITY1 + - yang_name: view + example: VIEW1 + - yang_name: ro + example: true + - yang_name: rw + example: false + - yang_name: sdrowner + example: false + - yang_name: systemowner + example: true + - yang_name: ipv4 + example: ACL1 + - yang_name: ipv6 + example: ACL2 diff --git a/internal/provider/data_source_iosxr_snmp_server.go b/internal/provider/data_source_iosxr_snmp_server.go index b7e29c1b..c1bea70e 100644 --- a/internal/provider/data_source_iosxr_snmp_server.go +++ b/internal/provider/data_source_iosxr_snmp_server.go @@ -298,6 +298,46 @@ func (d *SNMPServerDataSource) Schema(ctx context.Context, req datasource.Schema }, }, }, + "communities": schema.ListNestedAttribute{ + MarkdownDescription: "The UNENCRYPTED (cleartext) community string", + Computed: true, + NestedObject: schema.NestedAttributeObject{ + Attributes: map[string]schema.Attribute{ + "community": schema.StringAttribute{ + MarkdownDescription: "The UNENCRYPTED (cleartext) community string", + Computed: true, + }, + "view": schema.StringAttribute{ + MarkdownDescription: "Restrict this community to a named view", + Computed: true, + }, + "ro": schema.BoolAttribute{ + MarkdownDescription: "Read-only community", + Computed: true, + }, + "rw": schema.BoolAttribute{ + MarkdownDescription: "Read-write community", + Computed: true, + }, + "sdrowner": schema.BoolAttribute{ + MarkdownDescription: "SDR Owner permissions for MIB Objects", + Computed: true, + }, + "systemowner": schema.BoolAttribute{ + MarkdownDescription: "System Owner permissions for MIB objects", + Computed: true, + }, + "ipv4": schema.StringAttribute{ + MarkdownDescription: "Type of Access-list", + Computed: true, + }, + "ipv6": schema.StringAttribute{ + MarkdownDescription: "Type of Access-list", + Computed: true, + }, + }, + }, + }, }, } } diff --git a/internal/provider/data_source_iosxr_snmp_server_test.go b/internal/provider/data_source_iosxr_snmp_server_test.go index 138ddbf4..7c923a24 100644 --- a/internal/provider/data_source_iosxr_snmp_server_test.go +++ b/internal/provider/data_source_iosxr_snmp_server_test.go @@ -63,6 +63,14 @@ func TestAccDataSourceIosxrSNMPServer(t *testing.T) { checks = append(checks, resource.TestCheckResourceAttr("data.iosxr_snmp_server.test", "groups.0.v3_notify", "VIEW3")) checks = append(checks, resource.TestCheckResourceAttr("data.iosxr_snmp_server.test", "groups.0.v3_ipv4", "ACL1")) checks = append(checks, resource.TestCheckResourceAttr("data.iosxr_snmp_server.test", "groups.0.v3_ipv6", "ACL2")) + checks = append(checks, resource.TestCheckResourceAttr("data.iosxr_snmp_server.test", "communities.0.community", "COMMUNITY1")) + checks = append(checks, resource.TestCheckResourceAttr("data.iosxr_snmp_server.test", "communities.0.view", "VIEW1")) + checks = append(checks, resource.TestCheckResourceAttr("data.iosxr_snmp_server.test", "communities.0.ro", "true")) + checks = append(checks, resource.TestCheckResourceAttr("data.iosxr_snmp_server.test", "communities.0.rw", "false")) + checks = append(checks, resource.TestCheckResourceAttr("data.iosxr_snmp_server.test", "communities.0.sdrowner", "false")) + checks = append(checks, resource.TestCheckResourceAttr("data.iosxr_snmp_server.test", "communities.0.systemowner", "true")) + checks = append(checks, resource.TestCheckResourceAttr("data.iosxr_snmp_server.test", "communities.0.ipv4", "ACL1")) + checks = append(checks, resource.TestCheckResourceAttr("data.iosxr_snmp_server.test", "communities.0.ipv6", "ACL2")) resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, @@ -118,6 +126,16 @@ func testAccDataSourceIosxrSNMPServerConfig() string { config += ` v3_ipv4 = "ACL1"` + "\n" config += ` v3_ipv6 = "ACL2"` + "\n" config += ` }]` + "\n" + config += ` communities = [{` + "\n" + config += ` community = "COMMUNITY1"` + "\n" + config += ` view = "VIEW1"` + "\n" + config += ` ro = true` + "\n" + config += ` rw = false` + "\n" + config += ` sdrowner = false` + "\n" + config += ` systemowner = true` + "\n" + config += ` ipv4 = "ACL1"` + "\n" + config += ` ipv6 = "ACL2"` + "\n" + config += ` }]` + "\n" config += `}` + "\n" config += ` diff --git a/internal/provider/model_iosxr_snmp_server.go b/internal/provider/model_iosxr_snmp_server.go index ab8ac7f6..f3452819 100644 --- a/internal/provider/model_iosxr_snmp_server.go +++ b/internal/provider/model_iosxr_snmp_server.go @@ -31,104 +31,106 @@ import ( ) type SNMPServer struct { - Device types.String `tfsdk:"device"` - Id types.String `tfsdk:"id"` - DeleteMode types.String `tfsdk:"delete_mode"` - Location types.String `tfsdk:"location"` - Contact types.String `tfsdk:"contact"` - Rf types.Bool `tfsdk:"rf"` - Bfd types.Bool `tfsdk:"bfd"` - Ntp types.Bool `tfsdk:"ntp"` - EthernetOamEvents types.Bool `tfsdk:"ethernet_oam_events"` - CopyComplete types.Bool `tfsdk:"copy_complete"` - TrapsSnmpLinkup types.Bool `tfsdk:"traps_snmp_linkup"` - TrapsSnmpLinkdown types.Bool `tfsdk:"traps_snmp_linkdown"` - Power types.Bool `tfsdk:"power"` - Config types.Bool `tfsdk:"config"` - Entity types.Bool `tfsdk:"entity"` - System types.Bool `tfsdk:"system"` - Bridgemib types.Bool `tfsdk:"bridgemib"` - EntityStateOperstatus types.Bool `tfsdk:"entity_state_operstatus"` - EntityRedundancyAll types.Bool `tfsdk:"entity_redundancy_all"` - TrapSourceBoth types.String `tfsdk:"trap_source_both"` - L2vpnAll types.Bool `tfsdk:"l2vpn_all"` - L2vpnVcUp types.Bool `tfsdk:"l2vpn_vc_up"` - L2vpnVcDown types.Bool `tfsdk:"l2vpn_vc_down"` - Sensor types.Bool `tfsdk:"sensor"` - FruCtrl types.Bool `tfsdk:"fru_ctrl"` - IsisAll types.String `tfsdk:"isis_all"` - IsisDatabaseOverload types.String `tfsdk:"isis_database_overload"` - IsisManualAddressDrops types.String `tfsdk:"isis_manual_address_drops"` - IsisCorruptedLspDetected types.String `tfsdk:"isis_corrupted_lsp_detected"` - IsisAttemptToExceedMaxSequence types.String `tfsdk:"isis_attempt_to_exceed_max_sequence"` - IsisIdLenMismatch types.String `tfsdk:"isis_id_len_mismatch"` - IsisMaxAreaAddressesMismatch types.String `tfsdk:"isis_max_area_addresses_mismatch"` - IsisOwnLspPurge types.String `tfsdk:"isis_own_lsp_purge"` - IsisSequenceNumberSkip types.String `tfsdk:"isis_sequence_number_skip"` - IsisAuthenticationTypeFailure types.String `tfsdk:"isis_authentication_type_failure"` - IsisAuthenticationFailure types.String `tfsdk:"isis_authentication_failure"` - IsisVersionSkew types.String `tfsdk:"isis_version_skew"` - IsisAreaMismatch types.String `tfsdk:"isis_area_mismatch"` - IsisRejectedAdjacency types.String `tfsdk:"isis_rejected_adjacency"` - IsisLspTooLargeToPropagate types.String `tfsdk:"isis_lsp_too_large_to_propagate"` - IsisOrigLspBuffSizeMismatch types.String `tfsdk:"isis_orig_lsp_buff_size_mismatch"` - IsisProtocolsSupportedMismatch types.String `tfsdk:"isis_protocols_supported_mismatch"` - IsisAdjacencyChange types.String `tfsdk:"isis_adjacency_change"` - IsisLspErrorDetected types.String `tfsdk:"isis_lsp_error_detected"` - BgpCbgp2Updown types.Bool `tfsdk:"bgp_cbgp2_updown"` - BgpBgp4MibUpdown types.Bool `tfsdk:"bgp_bgp4_mib_updown"` - Users []SNMPServerUsers `tfsdk:"users"` - Groups []SNMPServerGroups `tfsdk:"groups"` + Device types.String `tfsdk:"device"` + Id types.String `tfsdk:"id"` + DeleteMode types.String `tfsdk:"delete_mode"` + Location types.String `tfsdk:"location"` + Contact types.String `tfsdk:"contact"` + Rf types.Bool `tfsdk:"rf"` + Bfd types.Bool `tfsdk:"bfd"` + Ntp types.Bool `tfsdk:"ntp"` + EthernetOamEvents types.Bool `tfsdk:"ethernet_oam_events"` + CopyComplete types.Bool `tfsdk:"copy_complete"` + TrapsSnmpLinkup types.Bool `tfsdk:"traps_snmp_linkup"` + TrapsSnmpLinkdown types.Bool `tfsdk:"traps_snmp_linkdown"` + Power types.Bool `tfsdk:"power"` + Config types.Bool `tfsdk:"config"` + Entity types.Bool `tfsdk:"entity"` + System types.Bool `tfsdk:"system"` + Bridgemib types.Bool `tfsdk:"bridgemib"` + EntityStateOperstatus types.Bool `tfsdk:"entity_state_operstatus"` + EntityRedundancyAll types.Bool `tfsdk:"entity_redundancy_all"` + TrapSourceBoth types.String `tfsdk:"trap_source_both"` + L2vpnAll types.Bool `tfsdk:"l2vpn_all"` + L2vpnVcUp types.Bool `tfsdk:"l2vpn_vc_up"` + L2vpnVcDown types.Bool `tfsdk:"l2vpn_vc_down"` + Sensor types.Bool `tfsdk:"sensor"` + FruCtrl types.Bool `tfsdk:"fru_ctrl"` + IsisAll types.String `tfsdk:"isis_all"` + IsisDatabaseOverload types.String `tfsdk:"isis_database_overload"` + IsisManualAddressDrops types.String `tfsdk:"isis_manual_address_drops"` + IsisCorruptedLspDetected types.String `tfsdk:"isis_corrupted_lsp_detected"` + IsisAttemptToExceedMaxSequence types.String `tfsdk:"isis_attempt_to_exceed_max_sequence"` + IsisIdLenMismatch types.String `tfsdk:"isis_id_len_mismatch"` + IsisMaxAreaAddressesMismatch types.String `tfsdk:"isis_max_area_addresses_mismatch"` + IsisOwnLspPurge types.String `tfsdk:"isis_own_lsp_purge"` + IsisSequenceNumberSkip types.String `tfsdk:"isis_sequence_number_skip"` + IsisAuthenticationTypeFailure types.String `tfsdk:"isis_authentication_type_failure"` + IsisAuthenticationFailure types.String `tfsdk:"isis_authentication_failure"` + IsisVersionSkew types.String `tfsdk:"isis_version_skew"` + IsisAreaMismatch types.String `tfsdk:"isis_area_mismatch"` + IsisRejectedAdjacency types.String `tfsdk:"isis_rejected_adjacency"` + IsisLspTooLargeToPropagate types.String `tfsdk:"isis_lsp_too_large_to_propagate"` + IsisOrigLspBuffSizeMismatch types.String `tfsdk:"isis_orig_lsp_buff_size_mismatch"` + IsisProtocolsSupportedMismatch types.String `tfsdk:"isis_protocols_supported_mismatch"` + IsisAdjacencyChange types.String `tfsdk:"isis_adjacency_change"` + IsisLspErrorDetected types.String `tfsdk:"isis_lsp_error_detected"` + BgpCbgp2Updown types.Bool `tfsdk:"bgp_cbgp2_updown"` + BgpBgp4MibUpdown types.Bool `tfsdk:"bgp_bgp4_mib_updown"` + Users []SNMPServerUsers `tfsdk:"users"` + Groups []SNMPServerGroups `tfsdk:"groups"` + Communities []SNMPServerCommunities `tfsdk:"communities"` } type SNMPServerData struct { - Device types.String `tfsdk:"device"` - Id types.String `tfsdk:"id"` - Location types.String `tfsdk:"location"` - Contact types.String `tfsdk:"contact"` - Rf types.Bool `tfsdk:"rf"` - Bfd types.Bool `tfsdk:"bfd"` - Ntp types.Bool `tfsdk:"ntp"` - EthernetOamEvents types.Bool `tfsdk:"ethernet_oam_events"` - CopyComplete types.Bool `tfsdk:"copy_complete"` - TrapsSnmpLinkup types.Bool `tfsdk:"traps_snmp_linkup"` - TrapsSnmpLinkdown types.Bool `tfsdk:"traps_snmp_linkdown"` - Power types.Bool `tfsdk:"power"` - Config types.Bool `tfsdk:"config"` - Entity types.Bool `tfsdk:"entity"` - System types.Bool `tfsdk:"system"` - Bridgemib types.Bool `tfsdk:"bridgemib"` - EntityStateOperstatus types.Bool `tfsdk:"entity_state_operstatus"` - EntityRedundancyAll types.Bool `tfsdk:"entity_redundancy_all"` - TrapSourceBoth types.String `tfsdk:"trap_source_both"` - L2vpnAll types.Bool `tfsdk:"l2vpn_all"` - L2vpnVcUp types.Bool `tfsdk:"l2vpn_vc_up"` - L2vpnVcDown types.Bool `tfsdk:"l2vpn_vc_down"` - Sensor types.Bool `tfsdk:"sensor"` - FruCtrl types.Bool `tfsdk:"fru_ctrl"` - IsisAll types.String `tfsdk:"isis_all"` - IsisDatabaseOverload types.String `tfsdk:"isis_database_overload"` - IsisManualAddressDrops types.String `tfsdk:"isis_manual_address_drops"` - IsisCorruptedLspDetected types.String `tfsdk:"isis_corrupted_lsp_detected"` - IsisAttemptToExceedMaxSequence types.String `tfsdk:"isis_attempt_to_exceed_max_sequence"` - IsisIdLenMismatch types.String `tfsdk:"isis_id_len_mismatch"` - IsisMaxAreaAddressesMismatch types.String `tfsdk:"isis_max_area_addresses_mismatch"` - IsisOwnLspPurge types.String `tfsdk:"isis_own_lsp_purge"` - IsisSequenceNumberSkip types.String `tfsdk:"isis_sequence_number_skip"` - IsisAuthenticationTypeFailure types.String `tfsdk:"isis_authentication_type_failure"` - IsisAuthenticationFailure types.String `tfsdk:"isis_authentication_failure"` - IsisVersionSkew types.String `tfsdk:"isis_version_skew"` - IsisAreaMismatch types.String `tfsdk:"isis_area_mismatch"` - IsisRejectedAdjacency types.String `tfsdk:"isis_rejected_adjacency"` - IsisLspTooLargeToPropagate types.String `tfsdk:"isis_lsp_too_large_to_propagate"` - IsisOrigLspBuffSizeMismatch types.String `tfsdk:"isis_orig_lsp_buff_size_mismatch"` - IsisProtocolsSupportedMismatch types.String `tfsdk:"isis_protocols_supported_mismatch"` - IsisAdjacencyChange types.String `tfsdk:"isis_adjacency_change"` - IsisLspErrorDetected types.String `tfsdk:"isis_lsp_error_detected"` - BgpCbgp2Updown types.Bool `tfsdk:"bgp_cbgp2_updown"` - BgpBgp4MibUpdown types.Bool `tfsdk:"bgp_bgp4_mib_updown"` - Users []SNMPServerUsers `tfsdk:"users"` - Groups []SNMPServerGroups `tfsdk:"groups"` + Device types.String `tfsdk:"device"` + Id types.String `tfsdk:"id"` + Location types.String `tfsdk:"location"` + Contact types.String `tfsdk:"contact"` + Rf types.Bool `tfsdk:"rf"` + Bfd types.Bool `tfsdk:"bfd"` + Ntp types.Bool `tfsdk:"ntp"` + EthernetOamEvents types.Bool `tfsdk:"ethernet_oam_events"` + CopyComplete types.Bool `tfsdk:"copy_complete"` + TrapsSnmpLinkup types.Bool `tfsdk:"traps_snmp_linkup"` + TrapsSnmpLinkdown types.Bool `tfsdk:"traps_snmp_linkdown"` + Power types.Bool `tfsdk:"power"` + Config types.Bool `tfsdk:"config"` + Entity types.Bool `tfsdk:"entity"` + System types.Bool `tfsdk:"system"` + Bridgemib types.Bool `tfsdk:"bridgemib"` + EntityStateOperstatus types.Bool `tfsdk:"entity_state_operstatus"` + EntityRedundancyAll types.Bool `tfsdk:"entity_redundancy_all"` + TrapSourceBoth types.String `tfsdk:"trap_source_both"` + L2vpnAll types.Bool `tfsdk:"l2vpn_all"` + L2vpnVcUp types.Bool `tfsdk:"l2vpn_vc_up"` + L2vpnVcDown types.Bool `tfsdk:"l2vpn_vc_down"` + Sensor types.Bool `tfsdk:"sensor"` + FruCtrl types.Bool `tfsdk:"fru_ctrl"` + IsisAll types.String `tfsdk:"isis_all"` + IsisDatabaseOverload types.String `tfsdk:"isis_database_overload"` + IsisManualAddressDrops types.String `tfsdk:"isis_manual_address_drops"` + IsisCorruptedLspDetected types.String `tfsdk:"isis_corrupted_lsp_detected"` + IsisAttemptToExceedMaxSequence types.String `tfsdk:"isis_attempt_to_exceed_max_sequence"` + IsisIdLenMismatch types.String `tfsdk:"isis_id_len_mismatch"` + IsisMaxAreaAddressesMismatch types.String `tfsdk:"isis_max_area_addresses_mismatch"` + IsisOwnLspPurge types.String `tfsdk:"isis_own_lsp_purge"` + IsisSequenceNumberSkip types.String `tfsdk:"isis_sequence_number_skip"` + IsisAuthenticationTypeFailure types.String `tfsdk:"isis_authentication_type_failure"` + IsisAuthenticationFailure types.String `tfsdk:"isis_authentication_failure"` + IsisVersionSkew types.String `tfsdk:"isis_version_skew"` + IsisAreaMismatch types.String `tfsdk:"isis_area_mismatch"` + IsisRejectedAdjacency types.String `tfsdk:"isis_rejected_adjacency"` + IsisLspTooLargeToPropagate types.String `tfsdk:"isis_lsp_too_large_to_propagate"` + IsisOrigLspBuffSizeMismatch types.String `tfsdk:"isis_orig_lsp_buff_size_mismatch"` + IsisProtocolsSupportedMismatch types.String `tfsdk:"isis_protocols_supported_mismatch"` + IsisAdjacencyChange types.String `tfsdk:"isis_adjacency_change"` + IsisLspErrorDetected types.String `tfsdk:"isis_lsp_error_detected"` + BgpCbgp2Updown types.Bool `tfsdk:"bgp_cbgp2_updown"` + BgpBgp4MibUpdown types.Bool `tfsdk:"bgp_bgp4_mib_updown"` + Users []SNMPServerUsers `tfsdk:"users"` + Groups []SNMPServerGroups `tfsdk:"groups"` + Communities []SNMPServerCommunities `tfsdk:"communities"` } type SNMPServerUsers struct { UserName types.String `tfsdk:"user_name"` @@ -146,6 +148,16 @@ type SNMPServerGroups struct { V3Ipv4 types.String `tfsdk:"v3_ipv4"` V3Ipv6 types.String `tfsdk:"v3_ipv6"` } +type SNMPServerCommunities struct { + Community types.String `tfsdk:"community"` + View types.String `tfsdk:"view"` + Ro types.Bool `tfsdk:"ro"` + Rw types.Bool `tfsdk:"rw"` + Sdrowner types.Bool `tfsdk:"sdrowner"` + Systemowner types.Bool `tfsdk:"systemowner"` + Ipv4 types.String `tfsdk:"ipv4"` + Ipv6 types.String `tfsdk:"ipv6"` +} func (data SNMPServer) getPath() string { return "Cisco-IOS-XR-um-snmp-server-cfg:/snmp-server" @@ -376,6 +388,43 @@ func (data SNMPServer) toBody(ctx context.Context) string { } } } + if len(data.Communities) > 0 { + body, _ = sjson.Set(body, "community.unencrypted.unencrypted-string", []interface{}{}) + for index, item := range data.Communities { + if !item.Community.IsNull() && !item.Community.IsUnknown() { + body, _ = sjson.Set(body, "community.unencrypted.unencrypted-string"+"."+strconv.Itoa(index)+"."+"community-string", item.Community.ValueString()) + } + if !item.View.IsNull() && !item.View.IsUnknown() { + body, _ = sjson.Set(body, "community.unencrypted.unencrypted-string"+"."+strconv.Itoa(index)+"."+"view", item.View.ValueString()) + } + if !item.Ro.IsNull() && !item.Ro.IsUnknown() { + if item.Ro.ValueBool() { + body, _ = sjson.Set(body, "community.unencrypted.unencrypted-string"+"."+strconv.Itoa(index)+"."+"ro", map[string]string{}) + } + } + if !item.Rw.IsNull() && !item.Rw.IsUnknown() { + if item.Rw.ValueBool() { + body, _ = sjson.Set(body, "community.unencrypted.unencrypted-string"+"."+strconv.Itoa(index)+"."+"rw", map[string]string{}) + } + } + if !item.Sdrowner.IsNull() && !item.Sdrowner.IsUnknown() { + if item.Sdrowner.ValueBool() { + body, _ = sjson.Set(body, "community.unencrypted.unencrypted-string"+"."+strconv.Itoa(index)+"."+"sdrowner", map[string]string{}) + } + } + if !item.Systemowner.IsNull() && !item.Systemowner.IsUnknown() { + if item.Systemowner.ValueBool() { + body, _ = sjson.Set(body, "community.unencrypted.unencrypted-string"+"."+strconv.Itoa(index)+"."+"systemowner", map[string]string{}) + } + } + if !item.Ipv4.IsNull() && !item.Ipv4.IsUnknown() { + body, _ = sjson.Set(body, "community.unencrypted.unencrypted-string"+"."+strconv.Itoa(index)+"."+"ipv4", item.Ipv4.ValueString()) + } + if !item.Ipv6.IsNull() && !item.Ipv6.IsUnknown() { + body, _ = sjson.Set(body, "community.unencrypted.unencrypted-string"+"."+strconv.Itoa(index)+"."+"ipv6", item.Ipv6.ValueString()) + } + } + } return body } @@ -791,6 +840,86 @@ func (data *SNMPServer) updateFromBody(ctx context.Context, res []byte) { data.Groups[i].V3Ipv6 = types.StringNull() } } + for i := range data.Communities { + keys := [...]string{"community-string"} + keyValues := [...]string{data.Communities[i].Community.ValueString()} + + var r gjson.Result + gjson.GetBytes(res, "community.unencrypted.unencrypted-string").ForEach( + func(_, v gjson.Result) bool { + found := false + for ik := range keys { + if v.Get(keys[ik]).String() == keyValues[ik] { + found = true + continue + } + found = false + break + } + if found { + r = v + return false + } + return true + }, + ) + if value := r.Get("community-string"); value.Exists() && !data.Communities[i].Community.IsNull() { + data.Communities[i].Community = types.StringValue(value.String()) + } else { + data.Communities[i].Community = types.StringNull() + } + if value := r.Get("view"); value.Exists() && !data.Communities[i].View.IsNull() { + data.Communities[i].View = types.StringValue(value.String()) + } else { + data.Communities[i].View = types.StringNull() + } + if value := r.Get("ro"); !data.Communities[i].Ro.IsNull() { + if value.Exists() { + data.Communities[i].Ro = types.BoolValue(true) + } else { + data.Communities[i].Ro = types.BoolValue(false) + } + } else { + data.Communities[i].Ro = types.BoolNull() + } + if value := r.Get("rw"); !data.Communities[i].Rw.IsNull() { + if value.Exists() { + data.Communities[i].Rw = types.BoolValue(true) + } else { + data.Communities[i].Rw = types.BoolValue(false) + } + } else { + data.Communities[i].Rw = types.BoolNull() + } + if value := r.Get("sdrowner"); !data.Communities[i].Sdrowner.IsNull() { + if value.Exists() { + data.Communities[i].Sdrowner = types.BoolValue(true) + } else { + data.Communities[i].Sdrowner = types.BoolValue(false) + } + } else { + data.Communities[i].Sdrowner = types.BoolNull() + } + if value := r.Get("systemowner"); !data.Communities[i].Systemowner.IsNull() { + if value.Exists() { + data.Communities[i].Systemowner = types.BoolValue(true) + } else { + data.Communities[i].Systemowner = types.BoolValue(false) + } + } else { + data.Communities[i].Systemowner = types.BoolNull() + } + if value := r.Get("ipv4"); value.Exists() && !data.Communities[i].Ipv4.IsNull() { + data.Communities[i].Ipv4 = types.StringValue(value.String()) + } else { + data.Communities[i].Ipv4 = types.StringNull() + } + if value := r.Get("ipv6"); value.Exists() && !data.Communities[i].Ipv6.IsNull() { + data.Communities[i].Ipv6 = types.StringValue(value.String()) + } else { + data.Communities[i].Ipv6 = types.StringNull() + } + } } func (data *SNMPServerData) fromBody(ctx context.Context, res []byte) { @@ -1019,6 +1148,46 @@ func (data *SNMPServerData) fromBody(ctx context.Context, res []byte) { return true }) } + if value := gjson.GetBytes(res, "community.unencrypted.unencrypted-string"); value.Exists() { + data.Communities = make([]SNMPServerCommunities, 0) + value.ForEach(func(k, v gjson.Result) bool { + item := SNMPServerCommunities{} + if cValue := v.Get("community-string"); cValue.Exists() { + item.Community = types.StringValue(cValue.String()) + } + if cValue := v.Get("view"); cValue.Exists() { + item.View = types.StringValue(cValue.String()) + } + if cValue := v.Get("ro"); cValue.Exists() { + item.Ro = types.BoolValue(true) + } else { + item.Ro = types.BoolValue(false) + } + if cValue := v.Get("rw"); cValue.Exists() { + item.Rw = types.BoolValue(true) + } else { + item.Rw = types.BoolValue(false) + } + if cValue := v.Get("sdrowner"); cValue.Exists() { + item.Sdrowner = types.BoolValue(true) + } else { + item.Sdrowner = types.BoolValue(false) + } + if cValue := v.Get("systemowner"); cValue.Exists() { + item.Systemowner = types.BoolValue(true) + } else { + item.Systemowner = types.BoolValue(false) + } + if cValue := v.Get("ipv4"); cValue.Exists() { + item.Ipv4 = types.StringValue(cValue.String()) + } + if cValue := v.Get("ipv6"); cValue.Exists() { + item.Ipv6 = types.StringValue(cValue.String()) + } + data.Communities = append(data.Communities, item) + return true + }) + } } func (data *SNMPServer) getDeletedListItems(ctx context.Context, state SNMPServer) []string { @@ -1083,6 +1252,36 @@ func (data *SNMPServer) getDeletedListItems(ctx context.Context, state SNMPServe deletedListItems = append(deletedListItems, fmt.Sprintf("%v/groups/group%v", state.getPath(), keyString)) } } + for i := range state.Communities { + keys := [...]string{"community-string"} + stateKeyValues := [...]string{state.Communities[i].Community.ValueString()} + + emptyKeys := true + if !reflect.ValueOf(state.Communities[i].Community.ValueString()).IsZero() { + emptyKeys = false + } + if emptyKeys { + continue + } + + found := false + for j := range data.Communities { + found = true + if state.Communities[i].Community.ValueString() != data.Communities[j].Community.ValueString() { + found = false + } + if found { + break + } + } + if !found { + keyString := "" + for ki := range keys { + keyString += "[" + keys[ki] + "=" + stateKeyValues[ki] + "]" + } + deletedListItems = append(deletedListItems, fmt.Sprintf("%v/community/unencrypted/unencrypted-string%v", state.getPath(), keyString)) + } + } return deletedListItems } @@ -1170,6 +1369,26 @@ func (data *SNMPServer) getEmptyLeafsDelete(ctx context.Context) []string { emptyLeafsDelete = append(emptyLeafsDelete, fmt.Sprintf("%v/groups/group%v/v3/priv", data.getPath(), keyString)) } } + for i := range data.Communities { + keys := [...]string{"community-string"} + keyValues := [...]string{data.Communities[i].Community.ValueString()} + keyString := "" + for ki := range keys { + keyString += "[" + keys[ki] + "=" + keyValues[ki] + "]" + } + if !data.Communities[i].Ro.IsNull() && !data.Communities[i].Ro.ValueBool() { + emptyLeafsDelete = append(emptyLeafsDelete, fmt.Sprintf("%v/community/unencrypted/unencrypted-string%v/ro", data.getPath(), keyString)) + } + if !data.Communities[i].Rw.IsNull() && !data.Communities[i].Rw.ValueBool() { + emptyLeafsDelete = append(emptyLeafsDelete, fmt.Sprintf("%v/community/unencrypted/unencrypted-string%v/rw", data.getPath(), keyString)) + } + if !data.Communities[i].Sdrowner.IsNull() && !data.Communities[i].Sdrowner.ValueBool() { + emptyLeafsDelete = append(emptyLeafsDelete, fmt.Sprintf("%v/community/unencrypted/unencrypted-string%v/sdrowner", data.getPath(), keyString)) + } + if !data.Communities[i].Systemowner.IsNull() && !data.Communities[i].Systemowner.ValueBool() { + emptyLeafsDelete = append(emptyLeafsDelete, fmt.Sprintf("%v/community/unencrypted/unencrypted-string%v/systemowner", data.getPath(), keyString)) + } + } return emptyLeafsDelete } @@ -1324,5 +1543,15 @@ func (data *SNMPServer) getDeletePaths(ctx context.Context) []string { } deletePaths = append(deletePaths, fmt.Sprintf("%v/groups/group%v", data.getPath(), keyString)) } + for i := range data.Communities { + keys := [...]string{"community-string"} + keyValues := [...]string{data.Communities[i].Community.ValueString()} + + keyString := "" + for ki := range keys { + keyString += "[" + keys[ki] + "=" + keyValues[ki] + "]" + } + deletePaths = append(deletePaths, fmt.Sprintf("%v/community/unencrypted/unencrypted-string%v", data.getPath(), keyString)) + } return deletePaths } diff --git a/internal/provider/resource_iosxr_snmp_server.go b/internal/provider/resource_iosxr_snmp_server.go index c1a0fb7e..8881e78f 100644 --- a/internal/provider/resource_iosxr_snmp_server.go +++ b/internal/provider/resource_iosxr_snmp_server.go @@ -456,6 +456,61 @@ func (r *SNMPServerResource) Schema(ctx context.Context, req resource.SchemaRequ }, }, }, + "communities": schema.ListNestedAttribute{ + MarkdownDescription: helpers.NewAttributeDescription("The UNENCRYPTED (cleartext) community string").String, + Optional: true, + NestedObject: schema.NestedAttributeObject{ + Attributes: map[string]schema.Attribute{ + "community": schema.StringAttribute{ + MarkdownDescription: helpers.NewAttributeDescription("The UNENCRYPTED (cleartext) community string").String, + Required: true, + Validators: []validator.String{ + stringvalidator.LengthBetween(1, 32), + }, + }, + "view": schema.StringAttribute{ + MarkdownDescription: helpers.NewAttributeDescription("Restrict this community to a named view").String, + Optional: true, + Validators: []validator.String{ + stringvalidator.LengthBetween(1, 1024), + stringvalidator.RegexMatches(regexp.MustCompile(`[\w\-\.:,_@#%$\+=\|;]+`), ""), + }, + }, + "ro": schema.BoolAttribute{ + MarkdownDescription: helpers.NewAttributeDescription("Read-only community").String, + Optional: true, + }, + "rw": schema.BoolAttribute{ + MarkdownDescription: helpers.NewAttributeDescription("Read-write community").String, + Optional: true, + }, + "sdrowner": schema.BoolAttribute{ + MarkdownDescription: helpers.NewAttributeDescription("SDR Owner permissions for MIB Objects").String, + Optional: true, + }, + "systemowner": schema.BoolAttribute{ + MarkdownDescription: helpers.NewAttributeDescription("System Owner permissions for MIB objects").String, + Optional: true, + }, + "ipv4": schema.StringAttribute{ + MarkdownDescription: helpers.NewAttributeDescription("Type of Access-list").String, + Optional: true, + Validators: []validator.String{ + stringvalidator.LengthBetween(1, 32), + stringvalidator.RegexMatches(regexp.MustCompile(`[\w\-\.:,_@#%$\+=\|;]+`), ""), + }, + }, + "ipv6": schema.StringAttribute{ + MarkdownDescription: helpers.NewAttributeDescription("Type of Access-list").String, + Optional: true, + Validators: []validator.String{ + stringvalidator.LengthBetween(1, 32), + stringvalidator.RegexMatches(regexp.MustCompile(`[\w\-\.:,_@#%$\+=\|;]+`), ""), + }, + }, + }, + }, + }, }, } } diff --git a/internal/provider/resource_iosxr_snmp_server_test.go b/internal/provider/resource_iosxr_snmp_server_test.go index d027a77e..5f1d33b7 100644 --- a/internal/provider/resource_iosxr_snmp_server_test.go +++ b/internal/provider/resource_iosxr_snmp_server_test.go @@ -64,6 +64,14 @@ func TestAccIosxrSNMPServer(t *testing.T) { checks = append(checks, resource.TestCheckResourceAttr("iosxr_snmp_server.test", "groups.0.v3_notify", "VIEW3")) checks = append(checks, resource.TestCheckResourceAttr("iosxr_snmp_server.test", "groups.0.v3_ipv4", "ACL1")) checks = append(checks, resource.TestCheckResourceAttr("iosxr_snmp_server.test", "groups.0.v3_ipv6", "ACL2")) + checks = append(checks, resource.TestCheckResourceAttr("iosxr_snmp_server.test", "communities.0.community", "COMMUNITY1")) + checks = append(checks, resource.TestCheckResourceAttr("iosxr_snmp_server.test", "communities.0.view", "VIEW1")) + checks = append(checks, resource.TestCheckResourceAttr("iosxr_snmp_server.test", "communities.0.ro", "true")) + checks = append(checks, resource.TestCheckResourceAttr("iosxr_snmp_server.test", "communities.0.rw", "false")) + checks = append(checks, resource.TestCheckResourceAttr("iosxr_snmp_server.test", "communities.0.sdrowner", "false")) + checks = append(checks, resource.TestCheckResourceAttr("iosxr_snmp_server.test", "communities.0.systemowner", "true")) + checks = append(checks, resource.TestCheckResourceAttr("iosxr_snmp_server.test", "communities.0.ipv4", "ACL1")) + checks = append(checks, resource.TestCheckResourceAttr("iosxr_snmp_server.test", "communities.0.ipv6", "ACL2")) var steps []resource.TestStep if os.Getenv("SKIP_MINIMUM_TEST") == "" { steps = append(steps, resource.TestStep{ @@ -134,6 +142,16 @@ func testAccIosxrSNMPServerConfig_all() string { config += ` v3_ipv4 = "ACL1"` + "\n" config += ` v3_ipv6 = "ACL2"` + "\n" config += ` }]` + "\n" + config += ` communities = [{` + "\n" + config += ` community = "COMMUNITY1"` + "\n" + config += ` view = "VIEW1"` + "\n" + config += ` ro = true` + "\n" + config += ` rw = false` + "\n" + config += ` sdrowner = false` + "\n" + config += ` systemowner = true` + "\n" + config += ` ipv4 = "ACL1"` + "\n" + config += ` ipv6 = "ACL2"` + "\n" + config += ` }]` + "\n" config += `}` + "\n" return config } diff --git a/templates/guides/changelog.md.tmpl b/templates/guides/changelog.md.tmpl index 8535392b..57fbecfe 100644 --- a/templates/guides/changelog.md.tmpl +++ b/templates/guides/changelog.md.tmpl @@ -13,7 +13,8 @@ description: |- - Add support for leaf-lists to `iosxr_gnmi` resource - Add `port` and `operator` attributes to `iosxr_logging_vrf` resource and data source - Add `iosxr_router_hsrp_interface_address_family_ipv6_group_v2` resource and data source -- Add `route_reflector_client` to `iosxr_router_bgp_neighbor_address_family` and `iosxr_router_bgp_neighbor_group` resource and data source +- Add `route_reflector_client` attribute to `iosxr_router_bgp_neighbor_address_family` and `iosxr_router_bgp_neighbor_group` resource and data source +- Add `communities` attributes to `iosxr_snmp_server` resource and data source ## 0.2.5