Skip to content

Commit

Permalink
Modified fabric site resource to use new endpoint (#98)
Browse files Browse the repository at this point in the history
  • Loading branch information
kuba-mazurkiewicz authored Jul 19, 2024
1 parent b062e3f commit 4695e66
Show file tree
Hide file tree
Showing 15 changed files with 168 additions and 91 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,5 @@ log*.txt
.terraform.lock.hcl
# Transient Terraform backend lock
.terraform.tfstate.lock.info

.envrc
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
## 0.1.10 (unreleased)

- BREAKING CHANGE: Modified `fabric_site` resource to use `/dna/intent/api/v1/sda/fabricSites` API endpoint, this resource now only works with Catalyst Center version 2.3.7.5+
- Fix issue with mandatory attributes in `transit_peer_network` resource, [link](https://github.com/CiscoDevNet/terraform-provider-catalystcenter/issues/92)
- BREAKING CHANGE: Fix `ip_pool` update if more than 25 pools are registered
- BREAKING CHANGE: Rename `radio_type_a_power_treshold_v1` attribute of `catalystcenter_wireless_rf_profile` resource to `radio_type_a_power_threshold_v1`
Expand Down
7 changes: 4 additions & 3 deletions docs/data-sources/fabric_site.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ This data source can read the Fabric Site.

```terraform
data "catalystcenter_fabric_site" "example" {
id = "Global/Site1"
id = "76d24097-41c4-4558-a4d0-a8c07ac08470"
}
```

Expand All @@ -24,8 +24,9 @@ data "catalystcenter_fabric_site" "example" {
### Optional

- `id` (String) The id of the object
- `site_name_hierarchy` (String) Existing site name hierarchy available at global level
- `site_id` (String) ID of the network hierarchy

### Read-Only

- `fabric_type` (String) Type of SD-Access Fabric
- `authentication_profile_name` (String) Authentication profile used for this fabric
- `pub_sub_enabled` (Boolean) Specifies whether this fabric site will use pub/sub for control nodes
1 change: 1 addition & 0 deletions docs/guides/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ description: |-

## 0.1.10 (unreleased)

- BREAKING CHANGE: Modified `fabric_site` resource to use `/dna/intent/api/v1/sda/fabricSites` API endpoint, this resource now only works with Catalyst Center version 2.3.7.5+
- Fix issue with mandatory attributes in `transit_peer_network` resource, [link](https://github.com/CiscoDevNet/terraform-provider-catalystcenter/issues/92)
- BREAKING CHANGE: Fix `ip_pool` update if more than 25 pools are registered
- BREAKING CHANGE: Rename `radio_type_a_power_treshold_v1` attribute of `catalystcenter_wireless_rf_profile` resource to `radio_type_a_power_threshold_v1`
Expand Down
22 changes: 10 additions & 12 deletions docs/resources/fabric_site.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,20 @@
page_title: "catalystcenter_fabric_site Resource - terraform-provider-catalystcenter"
subcategory: "SDA"
description: |-
This resource can manage a Fabric Site.
Manages Fabric Sites
---

# catalystcenter_fabric_site (Resource)

This resource can manage a Fabric Site.
Manages Fabric Sites

## Example Usage

```terraform
resource "catalystcenter_fabric_site" "example" {
site_name_hierarchy = "Global/Site1"
fabric_type = "FABRIC_SITE"
site_id = "8e6f7b3a-2b0b-4a7d-8b1c-0d4b1cd5e1b1"
authentication_profile_name = "No Authentication"
pub_sub_enabled = false
}
```

Expand All @@ -24,13 +25,10 @@ resource "catalystcenter_fabric_site" "example" {

### Required

- `site_name_hierarchy` (String) Existing site name hierarchy available at global level

### Optional

- `fabric_type` (String) Type of SD-Access Fabric
- Choices: `FABRIC_SITE`, `FABRIC_ZONE`
- Default value: `FABRIC_SITE`
- `authentication_profile_name` (String) Authentication profile used for this fabric
- Choices: `Closed Authentication`, `Low Impact`, `No Authentication`, `Open Authentication`
- `pub_sub_enabled` (Boolean) Specifies whether this fabric site will use pub/sub for control nodes
- `site_id` (String) ID of the network hierarchy

### Read-Only

Expand All @@ -41,5 +39,5 @@ resource "catalystcenter_fabric_site" "example" {
Import is supported using the following syntax:

```shell
terraform import catalystcenter_fabric_site.example "<site_name_hierarchy>"
terraform import catalystcenter_fabric_site.example "<id>"
```
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
data "catalystcenter_fabric_site" "example" {
id = "Global/Site1"
id = "76d24097-41c4-4558-a4d0-a8c07ac08470"
}
2 changes: 1 addition & 1 deletion examples/resources/catalystcenter_fabric_site/import.sh
Original file line number Diff line number Diff line change
@@ -1 +1 @@
terraform import catalystcenter_fabric_site.example "<site_name_hierarchy>"
terraform import catalystcenter_fabric_site.example "<id>"
5 changes: 3 additions & 2 deletions examples/resources/catalystcenter_fabric_site/resource.tf
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
resource "catalystcenter_fabric_site" "example" {
site_name_hierarchy = "Global/Site1"
fabric_type = "FABRIC_SITE"
site_id = "8e6f7b3a-2b0b-4a7d-8b1c-0d4b1cd5e1b1"
authentication_profile_name = "No Authentication"
pub_sub_enabled = false
}
51 changes: 32 additions & 19 deletions gen/definitions/fabric_site.yaml
Original file line number Diff line number Diff line change
@@ -1,28 +1,41 @@
---
name: Fabric Site
rest_endpoint: /dna/intent/api/v1/business/sda/fabric-site
id_from_attribute: true
id_query_param: siteNameHierarchy
delete_id_query_param: siteNameHierarchy
no_update: true
skip_minimum_test: true
rest_endpoint: /dna/intent/api/v1/sda/fabricSites
get_rest_endpoint: /dna/intent/api/v1/sda/fabricSites?limit=500
res_description: Manages Fabric Sites
id_from_query_path: response
get_from_all: true
put_id_include_path: "0.id"
put_no_id: true
doc_category: SDA
attributes:
- model_name: siteNameHierarchy
type: String
id: true
- model_name: siteId
requires_replace: true
data_path: '0'
match_id: true
data_source_query: true
description: Existing site name hierarchy available at global level
example: Global/Site1
test_value: '"${catalystcenter_area.test.parent_name}/${catalystcenter_area.test.name}"'
- model_name: fabricType
response_data_path: siteId
mandatory: true
type: String
description: ID of the network hierarchy
example: 8e6f7b3a-2b0b-4a7d-8b1c-0d4b1cd5e1b1
test_value: catalystcenter_area.test.id
- model_name: authenticationProfileName
data_path: '0'
response_data_path: authenticationProfileName
mandatory: true
type: String
description: Type of SD-Access Fabric
enum_values: [FABRIC_SITE, FABRIC_ZONE]
write_only: true # when configuring FABRIC_SITE, GET return FABRIC_LAN (v2.3.7.4)
requires_replace: true # PUT not implemented
example: FABRIC_SITE
default_value: FABRIC_SITE
description: Authentication profile used for this fabric
enum_values: [Closed Authentication, Low Impact, No Authentication, Open Authentication]
example: No Authentication
- model_name: isPubSubEnabled
data_path: '0'
response_data_path: isPubSubEnabled
tf_name: pub_sub_enabled
type: Bool
mandatory: true
description: Specifies whether this fabric site will use pub/sub for control nodes
example: false
test_prerequisites: |
resource "catalystcenter_area" "test" {
name = "Area 1"
Expand Down
31 changes: 17 additions & 14 deletions internal/provider/data_source_catalystcenter_fabric_site.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ package provider
import (
"context"
"fmt"
"net/url"

"github.com/hashicorp/terraform-plugin-framework-validators/datasourcevalidator"
"github.com/hashicorp/terraform-plugin-framework/datasource"
Expand Down Expand Up @@ -66,13 +65,17 @@ func (d *FabricSiteDataSource) Schema(ctx context.Context, req datasource.Schema
Optional: true,
Computed: true,
},
"site_name_hierarchy": schema.StringAttribute{
MarkdownDescription: "Existing site name hierarchy available at global level",
"site_id": schema.StringAttribute{
MarkdownDescription: "ID of the network hierarchy",
Optional: true,
Computed: true,
},
"fabric_type": schema.StringAttribute{
MarkdownDescription: "Type of SD-Access Fabric",
"authentication_profile_name": schema.StringAttribute{
MarkdownDescription: "Authentication profile used for this fabric",
Computed: true,
},
"pub_sub_enabled": schema.BoolAttribute{
MarkdownDescription: "Specifies whether this fabric site will use pub/sub for control nodes",
Computed: true,
},
},
Expand All @@ -82,7 +85,7 @@ func (d *FabricSiteDataSource) ConfigValidators(ctx context.Context) []datasourc
return []datasource.ConfigValidator{
datasourcevalidator.ExactlyOneOf(
path.MatchRoot("id"),
path.MatchRoot("site_name_hierarchy"),
path.MatchRoot("site_id"),
),
}
}
Expand All @@ -109,36 +112,36 @@ func (d *FabricSiteDataSource) Read(ctx context.Context, req datasource.ReadRequ
}

tflog.Debug(ctx, fmt.Sprintf("%s: Beginning Read", config.Id.String()))
if config.Id.IsNull() && !config.SiteNameHierarchy.IsNull() {
res, err := d.client.Get(config.getPath())
if config.Id.IsNull() && !config.SiteId.IsNull() {
res, err := d.client.Get("/dna/intent/api/v1/sda/fabricSites?limit=500")
if err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to retrieve objects, got error: %s", err))
return
}
if value := res; len(value.Array()) > 0 {
if value := res.Get("response"); len(value.Array()) > 0 {
value.ForEach(func(k, v gjson.Result) bool {
if config.SiteNameHierarchy.ValueString() == v.Get("siteNameHierarchy").String() {
if config.SiteId.ValueString() == v.Get("siteId").String() {
config.Id = types.StringValue(v.Get("id").String())
tflog.Debug(ctx, fmt.Sprintf("%s: Found object with siteNameHierarchy '%v', id: %v", config.Id.String(), config.SiteNameHierarchy.ValueString(), config.Id.String()))
tflog.Debug(ctx, fmt.Sprintf("%s: Found object with siteId '%v', id: %v", config.Id.String(), config.SiteId.ValueString(), config.Id.String()))
return false
}
return true
})
}

if config.Id.IsNull() {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to find object with siteNameHierarchy: %s", config.SiteNameHierarchy.ValueString()))
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to find object with siteId: %s", config.SiteId.ValueString()))
return
}
}

params := ""
params += "?siteNameHierarchy=" + url.QueryEscape(config.Id.ValueString())
res, err := d.client.Get(config.getPath() + params)
res, err := d.client.Get("/dna/intent/api/v1/sda/fabricSites?limit=500" + params)
if err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to retrieve object, got error: %s", err))
return
}
res = res.Get("response.#(id==\"" + config.Id.ValueString() + "\")")

config.fromBody(ctx, res)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ import (
// Section below is generated&owned by "gen/generator.go". //template:begin testAccDataSource
func TestAccDataSourceCcFabricSite(t *testing.T) {
var checks []resource.TestCheckFunc
checks = append(checks, resource.TestCheckResourceAttr("data.catalystcenter_fabric_site.test", "authentication_profile_name", "No Authentication"))
checks = append(checks, resource.TestCheckResourceAttr("data.catalystcenter_fabric_site.test", "pub_sub_enabled", "false"))
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
Expand Down Expand Up @@ -56,8 +58,9 @@ resource "catalystcenter_area" "test" {
// Section below is generated&owned by "gen/generator.go". //template:begin testAccDataSourceConfig
func testAccDataSourceCcFabricSiteConfig() string {
config := `resource "catalystcenter_fabric_site" "test" {` + "\n"
config += ` site_name_hierarchy = "${catalystcenter_area.test.parent_name}/${catalystcenter_area.test.name}"` + "\n"
config += ` fabric_type = "FABRIC_SITE"` + "\n"
config += ` site_id = catalystcenter_area.test.id` + "\n"
config += ` authentication_profile_name = "No Authentication"` + "\n"
config += ` pub_sub_enabled = false` + "\n"
config += `}` + "\n"

config += `
Expand Down
61 changes: 46 additions & 15 deletions internal/provider/model_catalystcenter_fabric_site.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,17 @@ import (

// Section below is generated&owned by "gen/generator.go". //template:begin types
type FabricSite struct {
Id types.String `tfsdk:"id"`
SiteNameHierarchy types.String `tfsdk:"site_name_hierarchy"`
FabricType types.String `tfsdk:"fabric_type"`
Id types.String `tfsdk:"id"`
SiteId types.String `tfsdk:"site_id"`
AuthenticationProfileName types.String `tfsdk:"authentication_profile_name"`
PubSubEnabled types.Bool `tfsdk:"pub_sub_enabled"`
}

// End of section. //template:end types

// Section below is generated&owned by "gen/generator.go". //template:begin getPath
func (data FabricSite) getPath() string {
return "/dna/intent/api/v1/business/sda/fabric-site"
return "/dna/intent/api/v1/sda/fabricSites"
}

// End of section. //template:end getPath
Expand All @@ -54,13 +55,17 @@ func (data FabricSite) toBody(ctx context.Context, state FabricSite) string {
put := false
if state.Id.ValueString() != "" {
put = true
body, _ = sjson.Set(body, "0.id", state.Id.ValueString())
}
_ = put
if !data.SiteNameHierarchy.IsNull() {
body, _ = sjson.Set(body, "siteNameHierarchy", data.SiteNameHierarchy.ValueString())
if !data.SiteId.IsNull() {
body, _ = sjson.Set(body, "0.siteId", data.SiteId.ValueString())
}
if !data.FabricType.IsNull() {
body, _ = sjson.Set(body, "fabricType", data.FabricType.ValueString())
if !data.AuthenticationProfileName.IsNull() {
body, _ = sjson.Set(body, "0.authenticationProfileName", data.AuthenticationProfileName.ValueString())
}
if !data.PubSubEnabled.IsNull() {
body, _ = sjson.Set(body, "0.isPubSubEnabled", data.PubSubEnabled.ValueBool())
}
return body
}
Expand All @@ -69,29 +74,55 @@ func (data FabricSite) toBody(ctx context.Context, state FabricSite) string {

// Section below is generated&owned by "gen/generator.go". //template:begin fromBody
func (data *FabricSite) fromBody(ctx context.Context, res gjson.Result) {
if value := res.Get("siteNameHierarchy"); value.Exists() {
data.SiteNameHierarchy = types.StringValue(value.String())
if value := res.Get("siteId"); value.Exists() {
data.SiteId = types.StringValue(value.String())
} else {
data.SiteId = types.StringNull()
}
if value := res.Get("authenticationProfileName"); value.Exists() {
data.AuthenticationProfileName = types.StringValue(value.String())
} else {
data.SiteNameHierarchy = types.StringNull()
data.AuthenticationProfileName = types.StringNull()
}
if value := res.Get("isPubSubEnabled"); value.Exists() {
data.PubSubEnabled = types.BoolValue(value.Bool())
} else {
data.PubSubEnabled = types.BoolNull()
}
}

// End of section. //template:end fromBody

// Section below is generated&owned by "gen/generator.go". //template:begin updateFromBody
func (data *FabricSite) updateFromBody(ctx context.Context, res gjson.Result) {
if value := res.Get("siteNameHierarchy"); value.Exists() && !data.SiteNameHierarchy.IsNull() {
data.SiteNameHierarchy = types.StringValue(value.String())
if value := res.Get("siteId"); value.Exists() && !data.SiteId.IsNull() {
data.SiteId = types.StringValue(value.String())
} else {
data.SiteId = types.StringNull()
}
if value := res.Get("authenticationProfileName"); value.Exists() && !data.AuthenticationProfileName.IsNull() {
data.AuthenticationProfileName = types.StringValue(value.String())
} else {
data.SiteNameHierarchy = types.StringNull()
data.AuthenticationProfileName = types.StringNull()
}
if value := res.Get("isPubSubEnabled"); value.Exists() && !data.PubSubEnabled.IsNull() {
data.PubSubEnabled = types.BoolValue(value.Bool())
} else {
data.PubSubEnabled = types.BoolNull()
}
}

// End of section. //template:end updateFromBody

// Section below is generated&owned by "gen/generator.go". //template:begin isNull
func (data *FabricSite) isNull(ctx context.Context, res gjson.Result) bool {
if !data.FabricType.IsNull() {
if !data.SiteId.IsNull() {
return false
}
if !data.AuthenticationProfileName.IsNull() {
return false
}
if !data.PubSubEnabled.IsNull() {
return false
}
return true
Expand Down
Loading

0 comments on commit 4695e66

Please sign in to comment.