diff --git a/CHANGELOG.md b/CHANGELOG.md index 016e209..8602670 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +## 0.1.4 (unreleased) + +- Add `ise_trustsec_ip_to_sgt_mapping` resource and data source +- Add `ise_trustsec_ip_to_sgt_mapping_group` resource and data source + ## 0.1.3 - Add support for nested conditions to `ise_network_access_authentication_rule` resource and data source diff --git a/docs/data-sources/trustsec_ip_to_sgt_mapping.md b/docs/data-sources/trustsec_ip_to_sgt_mapping.md index 0663e0d..edc9807 100644 --- a/docs/data-sources/trustsec_ip_to_sgt_mapping.md +++ b/docs/data-sources/trustsec_ip_to_sgt_mapping.md @@ -21,17 +21,17 @@ data "ise_trustsec_ip_to_sgt_mapping" "example" { ## Schema -### Required +### Optional - `id` (String) The id of the object +- `name` (String) The name of the IP to SGT mapping ### Read-Only -- `deploy_to` (String) Mandatory unless mappingGroup is set or unless `deployType=ALL` +- `deploy_to` (String) Mandatory unless `mapping_group` is set or unless `deploy_type` is `ALL` - `deploy_type` (String) Deploy Type - `description` (String) Description -- `host_ip` (String) Mandatory if hostName is empty -- valid IP -- `host_name` (String) Mandatory if hostIp is empty -- `mapping_group` (String) IP to SGT Mapping Group ID. Mandatory unless sgt and deployTo and deployType are set -- `name` (String) The name of the IP to SGT mapping -- `sgt` (String) Trustsec Security Group ID. Mandatory unless mappingGroup is set +- `host_ip` (String) Mandatory if `host_name` is empty +- `host_name` (String) Mandatory if `host_ip` is empty +- `mapping_group` (String) IP to SGT Mapping Group ID. Mandatory unless `sgt` and `deploy_to` and `deploy_type` are set +- `sgt` (String) Trustsec Security Group ID. Mandatory unless `mapping_group` is set diff --git a/docs/guides/changelog.md b/docs/guides/changelog.md index 020a2fc..1a33b8c 100644 --- a/docs/guides/changelog.md +++ b/docs/guides/changelog.md @@ -7,6 +7,11 @@ description: |- # Changelog +## 0.1.4 (unreleased) + +- Add `ise_trustsec_ip_to_sgt_mapping` resource and data source +- Add `ise_trustsec_ip_to_sgt_mapping_group` resource and data source + ## 0.1.3 - Add support for nested conditions to `ise_network_access_authentication_rule` resource and data source diff --git a/docs/resources/trustsec_ip_to_sgt_mapping.md b/docs/resources/trustsec_ip_to_sgt_mapping.md index d5cbdd2..071a9dd 100644 --- a/docs/resources/trustsec_ip_to_sgt_mapping.md +++ b/docs/resources/trustsec_ip_to_sgt_mapping.md @@ -30,14 +30,14 @@ resource "ise_trustsec_ip_to_sgt_mapping" "example" { ### Optional -- `deploy_to` (String) Mandatory unless mappingGroup is set or unless `deployType=ALL` +- `deploy_to` (String) Mandatory unless `mapping_group` is set or unless `deploy_type` is `ALL` - `deploy_type` (String) Deploy Type - Choices: `ALL`, `ND`, `NDG` - `description` (String) Description -- `host_ip` (String) Mandatory if hostName is empty -- valid IP -- `host_name` (String) Mandatory if hostIp is empty -- `mapping_group` (String) IP to SGT Mapping Group ID. Mandatory unless sgt and deployTo and deployType are set -- `sgt` (String) Trustsec Security Group ID. Mandatory unless mappingGroup is set +- `host_ip` (String) Mandatory if `host_name` is empty +- `host_name` (String) Mandatory if `host_ip` is empty +- `mapping_group` (String) IP to SGT Mapping Group ID. Mandatory unless `sgt` and `deploy_to` and `deploy_type` are set +- `sgt` (String) Trustsec Security Group ID. Mandatory unless `mapping_group` is set ### Read-Only diff --git a/gen/definitions/trustsec_ip_to_sgt_mapping.yaml b/gen/definitions/trustsec_ip_to_sgt_mapping.yaml index b9c911f..b7d4095 100644 --- a/gen/definitions/trustsec_ip_to_sgt_mapping.yaml +++ b/gen/definitions/trustsec_ip_to_sgt_mapping.yaml @@ -2,6 +2,7 @@ name: TrustSec IP to SGT Mapping rest_endpoint: /ers/config/sgmapping doc_category: TrustSec +data_source_name_query: true id_path: response.id attributes: - model_name: name @@ -18,7 +19,7 @@ attributes: - model_name: deployTo data_path: [SGMapping] type: String - description: "Mandatory unless mappingGroup is set or unless `deployType=ALL`" + description: "Mandatory unless `mapping_group` is set or unless `deploy_type` is `ALL`" exclude_test: true example: "All Locations" - model_name: deployType @@ -31,26 +32,27 @@ attributes: - model_name: hostName data_path: [SGMapping] type: String - description: Mandatory if hostIp is empty + description: Mandatory if `host_ip` is empty example: "server1.cisco.com" exclude_test: true - model_name: hostIp data_path: [SGMapping] type: String - description: Mandatory if hostName is empty -- valid IP + description: Mandatory if `host_name` is empty example: "10.0.0.1/32" minimum_test_value: '"10.0.0.1/32"' - model_name: sgt data_path: [SGMapping] type: String example: "93e1bf00-8c01-11e6-996c-525400b48521" + test_value: ise_trustsec_security_group.test.id minimum_test_value: ise_trustsec_security_group.test.id - description: Trustsec Security Group ID. Mandatory unless mappingGroup is set + description: Trustsec Security Group ID. Mandatory unless `mapping_group` is set - model_name: mappingGroup data_path: [SGMapping] type: String example: "48fc1ac2-d500-493d-99ad-8d8fab0ef11f" - description: IP to SGT Mapping Group ID. Mandatory unless sgt and deployTo and deployType are set + description: IP to SGT Mapping Group ID. Mandatory unless `sgt` and `deploy_to` and `deploy_type` are set exclude_test: true test_prerequisites: | diff --git a/internal/provider/data_source_ise_trustsec_ip_to_sgt_mapping.go b/internal/provider/data_source_ise_trustsec_ip_to_sgt_mapping.go index 16eaa08..206b466 100644 --- a/internal/provider/data_source_ise_trustsec_ip_to_sgt_mapping.go +++ b/internal/provider/data_source_ise_trustsec_ip_to_sgt_mapping.go @@ -24,10 +24,14 @@ import ( "context" "fmt" + "github.com/hashicorp/terraform-plugin-framework-validators/datasourcevalidator" "github.com/hashicorp/terraform-plugin-framework/datasource" "github.com/hashicorp/terraform-plugin-framework/datasource/schema" + "github.com/hashicorp/terraform-plugin-framework/path" + "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/netascode/go-ise" + "github.com/tidwall/gjson" ) //template:end imports @@ -60,10 +64,12 @@ func (d *TrustSecIPToSGTMappingDataSource) Schema(ctx context.Context, req datas Attributes: map[string]schema.Attribute{ "id": schema.StringAttribute{ MarkdownDescription: "The id of the object", - Required: true, + Optional: true, + Computed: true, }, "name": schema.StringAttribute{ MarkdownDescription: "The name of the IP to SGT mapping", + Optional: true, Computed: true, }, "description": schema.StringAttribute{ @@ -71,7 +77,7 @@ func (d *TrustSecIPToSGTMappingDataSource) Schema(ctx context.Context, req datas Computed: true, }, "deploy_to": schema.StringAttribute{ - MarkdownDescription: "Mandatory unless mappingGroup is set or unless `deployType=ALL`", + MarkdownDescription: "Mandatory unless `mapping_group` is set or unless `deploy_type` is `ALL`", Computed: true, }, "deploy_type": schema.StringAttribute{ @@ -79,24 +85,32 @@ func (d *TrustSecIPToSGTMappingDataSource) Schema(ctx context.Context, req datas Computed: true, }, "host_name": schema.StringAttribute{ - MarkdownDescription: "Mandatory if hostIp is empty", + MarkdownDescription: "Mandatory if `host_ip` is empty", Computed: true, }, "host_ip": schema.StringAttribute{ - MarkdownDescription: "Mandatory if hostName is empty -- valid IP", + MarkdownDescription: "Mandatory if `host_name` is empty", Computed: true, }, "sgt": schema.StringAttribute{ - MarkdownDescription: "Trustsec Security Group ID. Mandatory unless mappingGroup is set", + MarkdownDescription: "Trustsec Security Group ID. Mandatory unless `mapping_group` is set", Computed: true, }, "mapping_group": schema.StringAttribute{ - MarkdownDescription: "IP to SGT Mapping Group ID. Mandatory unless sgt and deployTo and deployType are set", + MarkdownDescription: "IP to SGT Mapping Group ID. Mandatory unless `sgt` and `deploy_to` and `deploy_type` are set", Computed: true, }, }, } } +func (d *TrustSecIPToSGTMappingDataSource) ConfigValidators(ctx context.Context) []datasource.ConfigValidator { + return []datasource.ConfigValidator{ + datasourcevalidator.ExactlyOneOf( + path.MatchRoot("id"), + path.MatchRoot("name"), + ), + } +} func (d *TrustSecIPToSGTMappingDataSource) Configure(_ context.Context, req datasource.ConfigureRequest, _ *datasource.ConfigureResponse) { if req.ProviderData == nil { @@ -120,6 +134,33 @@ func (d *TrustSecIPToSGTMappingDataSource) Read(ctx context.Context, req datasou } tflog.Debug(ctx, fmt.Sprintf("%s: Beginning Read", config.Id.String())) + if config.Id.IsNull() && !config.Name.IsNull() { + for page := 1; ; page++ { + res, err := d.client.Get(fmt.Sprintf("%s?size=100&page=%v", config.getPath(), page)) + if err != nil { + resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to retrieve objects, got error: %s", err)) + return + } + if value := res.Get("SearchResult.resources"); len(value.Array()) > 0 { + value.ForEach(func(k, v gjson.Result) bool { + if config.Name.ValueString() == v.Get("name").String() { + config.Id = types.StringValue(v.Get("id").String()) + tflog.Debug(ctx, fmt.Sprintf("%s: Found object with name '%v', id: %v", config.Id.String(), config.Name.ValueString(), config.Id.String())) + return false + } + return true + }) + } + if !config.Id.IsNull() || !res.Get("SearchResult.nextPage").Exists() { + break + } + } + + if config.Id.IsNull() { + resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to find object with name: %s", config.Name.ValueString())) + return + } + } res, err := d.client.Get(config.getPath() + "/" + config.Id.ValueString()) if err != nil { diff --git a/internal/provider/data_source_ise_trustsec_ip_to_sgt_mapping_test.go b/internal/provider/data_source_ise_trustsec_ip_to_sgt_mapping_test.go index ed52967..85e67bc 100644 --- a/internal/provider/data_source_ise_trustsec_ip_to_sgt_mapping_test.go +++ b/internal/provider/data_source_ise_trustsec_ip_to_sgt_mapping_test.go @@ -34,7 +34,6 @@ func TestAccDataSourceIseTrustSecIPToSGTMapping(t *testing.T) { checks = append(checks, resource.TestCheckResourceAttr("data.ise_trustsec_ip_to_sgt_mapping.test", "name", "10.0.0.1/32")) checks = append(checks, resource.TestCheckResourceAttr("data.ise_trustsec_ip_to_sgt_mapping.test", "deploy_type", "ALL")) checks = append(checks, resource.TestCheckResourceAttr("data.ise_trustsec_ip_to_sgt_mapping.test", "host_ip", "10.0.0.1/32")) - checks = append(checks, resource.TestCheckResourceAttr("data.ise_trustsec_ip_to_sgt_mapping.test", "sgt", "93e1bf00-8c01-11e6-996c-525400b48521")) resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, @@ -69,7 +68,7 @@ func testAccDataSourceIseTrustSecIPToSGTMappingConfig() string { config += ` name = "10.0.0.1/32"` + "\n" config += ` deploy_type = "ALL"` + "\n" config += ` host_ip = "10.0.0.1/32"` + "\n" - config += ` sgt = "93e1bf00-8c01-11e6-996c-525400b48521"` + "\n" + config += ` sgt = ise_trustsec_security_group.test.id` + "\n" config += `}` + "\n" config += ` diff --git a/internal/provider/resource_ise_trustsec_ip_to_sgt_mapping.go b/internal/provider/resource_ise_trustsec_ip_to_sgt_mapping.go index b694380..3081f64 100644 --- a/internal/provider/resource_ise_trustsec_ip_to_sgt_mapping.go +++ b/internal/provider/resource_ise_trustsec_ip_to_sgt_mapping.go @@ -80,7 +80,7 @@ func (r *TrustSecIPToSGTMappingResource) Schema(ctx context.Context, req resourc Optional: true, }, "deploy_to": schema.StringAttribute{ - MarkdownDescription: helpers.NewAttributeDescription("Mandatory unless mappingGroup is set or unless `deployType=ALL`").String, + MarkdownDescription: helpers.NewAttributeDescription("Mandatory unless `mapping_group` is set or unless `deploy_type` is `ALL`").String, Optional: true, }, "deploy_type": schema.StringAttribute{ @@ -91,19 +91,19 @@ func (r *TrustSecIPToSGTMappingResource) Schema(ctx context.Context, req resourc }, }, "host_name": schema.StringAttribute{ - MarkdownDescription: helpers.NewAttributeDescription("Mandatory if hostIp is empty").String, + MarkdownDescription: helpers.NewAttributeDescription("Mandatory if `host_ip` is empty").String, Optional: true, }, "host_ip": schema.StringAttribute{ - MarkdownDescription: helpers.NewAttributeDescription("Mandatory if hostName is empty -- valid IP").String, + MarkdownDescription: helpers.NewAttributeDescription("Mandatory if `host_name` is empty").String, Optional: true, }, "sgt": schema.StringAttribute{ - MarkdownDescription: helpers.NewAttributeDescription("Trustsec Security Group ID. Mandatory unless mappingGroup is set").String, + MarkdownDescription: helpers.NewAttributeDescription("Trustsec Security Group ID. Mandatory unless `mapping_group` is set").String, Optional: true, }, "mapping_group": schema.StringAttribute{ - MarkdownDescription: helpers.NewAttributeDescription("IP to SGT Mapping Group ID. Mandatory unless sgt and deployTo and deployType are set").String, + MarkdownDescription: helpers.NewAttributeDescription("IP to SGT Mapping Group ID. Mandatory unless `sgt` and `deploy_to` and `deploy_type` are set").String, Optional: true, }, }, diff --git a/internal/provider/resource_ise_trustsec_ip_to_sgt_mapping_test.go b/internal/provider/resource_ise_trustsec_ip_to_sgt_mapping_test.go index 5f1abe0..1a35f02 100644 --- a/internal/provider/resource_ise_trustsec_ip_to_sgt_mapping_test.go +++ b/internal/provider/resource_ise_trustsec_ip_to_sgt_mapping_test.go @@ -35,7 +35,6 @@ func TestAccIseTrustSecIPToSGTMapping(t *testing.T) { checks = append(checks, resource.TestCheckResourceAttr("ise_trustsec_ip_to_sgt_mapping.test", "name", "10.0.0.1/32")) checks = append(checks, resource.TestCheckResourceAttr("ise_trustsec_ip_to_sgt_mapping.test", "deploy_type", "ALL")) checks = append(checks, resource.TestCheckResourceAttr("ise_trustsec_ip_to_sgt_mapping.test", "host_ip", "10.0.0.1/32")) - checks = append(checks, resource.TestCheckResourceAttr("ise_trustsec_ip_to_sgt_mapping.test", "sgt", "93e1bf00-8c01-11e6-996c-525400b48521")) var steps []resource.TestStep if os.Getenv("SKIP_MINIMUM_TEST") == "" { @@ -94,7 +93,7 @@ func testAccIseTrustSecIPToSGTMappingConfig_all() string { config += ` name = "10.0.0.1/32"` + "\n" config += ` deploy_type = "ALL"` + "\n" config += ` host_ip = "10.0.0.1/32"` + "\n" - config += ` sgt = "93e1bf00-8c01-11e6-996c-525400b48521"` + "\n" + config += ` sgt = ise_trustsec_security_group.test.id` + "\n" config += `}` + "\n" return config } diff --git a/templates/guides/changelog.md.tmpl b/templates/guides/changelog.md.tmpl index 020a2fc..1a33b8c 100644 --- a/templates/guides/changelog.md.tmpl +++ b/templates/guides/changelog.md.tmpl @@ -7,6 +7,11 @@ description: |- # Changelog +## 0.1.4 (unreleased) + +- Add `ise_trustsec_ip_to_sgt_mapping` resource and data source +- Add `ise_trustsec_ip_to_sgt_mapping_group` resource and data source + ## 0.1.3 - Add support for nested conditions to `ise_network_access_authentication_rule` resource and data source