Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix issue #122 - add query_param groupName to read operations #123

Merged
merged 2 commits into from
Sep 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
- Add `catalystcenter_fabric_port_assignment` resource and data source
- BREAKING CHANGE: Replace `catalystcenter_peer_transit_network` with `catalystcenter_transit_network` resource and data source to use `/dna/intent/api/v1/sda/transitNetworks` API endpoint, this resource now only works with Catalyst Center version 2.3.7.6+
- Add `catalystcenter_authentication_policy_server` resource and data source
- Fix issue with import of `catalystcenter_ip_pool_reservation` resource, [link](https://github.com/CiscoDevNet/terraform-provider-catalystcenter/issues/122)

## 0.1.10

Expand Down
6 changes: 3 additions & 3 deletions docs/data-sources/ip_pool_reservation.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ This data source can read the IP Pool Reservation.

```terraform
data "catalystcenter_ip_pool_reservation" "example" {
id = "76d24097-41c4-4558-a4d0-a8c07ac08470"
site_id = "5e6f7b3a-2b0b-4a7d-8b1c-0d4b1cd5e1b1"
name = "MyRes1"
}
```

Expand All @@ -24,11 +24,12 @@ data "catalystcenter_ip_pool_reservation" "example" {

### Required

- `id` (String) The id of the object
- `name` (String) The name of the IP pool reservation
- `site_id` (String) The site ID

### Read-Only

- `id` (String) The id of the object
- `ipv4_dhcp_servers` (Set of String) List of DHCP Server IPs
- `ipv4_dns_servers` (Set of String) List of DNS Server IPs
- `ipv4_gateway` (String) The gateway for the IP pool reservation
Expand All @@ -46,6 +47,5 @@ data "catalystcenter_ip_pool_reservation" "example" {
- `ipv6_prefix_length` (Number) The IPv6 prefix length is required when `ipv6_prefix` value is `true`.
- `ipv6_subnet` (String) The IPv6 subnet, for example `2001:db8:85a3:0:100::`
- `ipv6_total_host` (Number) The total number of IPv6 hosts
- `name` (String) The name of the IP pool reservation
- `slaac_support` (Boolean) Enable SLAAC support
- `type` (String) The type of the IP pool reservation
1 change: 1 addition & 0 deletions docs/guides/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ description: |-
- Add `catalystcenter_fabric_port_assignment` resource and data source
- BREAKING CHANGE: Replace `catalystcenter_peer_transit_network` with `catalystcenter_transit_network` resource and data source to use `/dna/intent/api/v1/sda/transitNetworks` API endpoint, this resource now only works with Catalyst Center version 2.3.7.6+
- Add `catalystcenter_authentication_policy_server` resource and data source
- Fix issue with import of `catalystcenter_ip_pool_reservation` resource, [link](https://github.com/CiscoDevNet/terraform-provider-catalystcenter/issues/122)

## 0.1.10

Expand Down
2 changes: 1 addition & 1 deletion docs/resources/ip_pool_reservation.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,5 +68,5 @@ resource "catalystcenter_ip_pool_reservation" "example" {
Import is supported using the following syntax:

```shell
terraform import catalystcenter_ip_pool_reservation.example "<site_id>,<id>"
terraform import catalystcenter_ip_pool_reservation.example "<site_id>,<name>"
```
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
data "catalystcenter_ip_pool_reservation" "example" {
id = "76d24097-41c4-4558-a4d0-a8c07ac08470"
site_id = "5e6f7b3a-2b0b-4a7d-8b1c-0d4b1cd5e1b1"
name = "MyRes1"
}
Original file line number Diff line number Diff line change
@@ -1 +1 @@
terraform import catalystcenter_ip_pool_reservation.example "<site_id>,<id>"
terraform import catalystcenter_ip_pool_reservation.example "<site_id>,<name>"
18 changes: 12 additions & 6 deletions gen/definitions/ip_pool_reservation.yaml
Original file line number Diff line number Diff line change
@@ -1,21 +1,26 @@
---
name: IP Pool Reservation
rest_endpoint: /dna/intent/api/v1/reserve-ip-subpool
get_from_all: true
id_from_query_path: response
id_from_query_path: response.0
id_from_query_path_attribute: id
put_id_query_param: id
import_no_id: true
data_source_no_id: true
doc_category: Network Settings
attributes:
- model_name: siteId
type: String
query_param: true
create_query_path: true
response_data_path: response.0.siteId
description: The site ID
example: 5e6f7b3a-2b0b-4a7d-8b1c-0d4b1cd5e1b1
test_value: catalystcenter_area.test.id
- model_name: name
response_model_name: groupName
response_data_path: groupName
query_param: true
query_param_name: groupName
response_data_path: response.0.groupName
type: String
match_id: true
description: The name of the IP pool reservation
Expand All @@ -24,6 +29,7 @@ attributes:
type: String
mandatory: true
write_only: true
response_data_path: response.0.type
exclude_from_put: true
enum_values: [Generic, LAN, WAN, management, service]
description: The type of the IP pool reservation
Expand Down Expand Up @@ -64,19 +70,19 @@ attributes:
- model_name: ipv4GateWay
tf_name: ipv4_gateway
type: String
write_only: true
response_data_path: response.0.ipPools.0.gateways.0
description: The gateway for the IP pool reservation
example: 172.32.1.1
- model_name: ipv4DhcpServers
type: Set
element_type: String
write_only: true
response_data_path: response.0.ipPools.0.dhcpServerIps
description: List of DHCP Server IPs
example: 1.2.3.4
- model_name: ipv4DnsServers
type: Set
element_type: String
write_only: true
response_data_path: response.0.ipPools.0.dnsServerIps
description: List of DNS Server IPs
example: 2.3.4.5
- model_name: ipv6GlobalPool
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,15 @@ func (d *IPPoolReservationDataSource) Schema(ctx context.Context, req datasource
Attributes: map[string]schema.Attribute{
"id": schema.StringAttribute{
MarkdownDescription: "The id of the object",
Required: true,
Computed: true,
},
"site_id": schema.StringAttribute{
MarkdownDescription: "The site ID",
Required: true,
},
"name": schema.StringAttribute{
MarkdownDescription: "The name of the IP pool reservation",
Computed: true,
Required: true,
},
"type": schema.StringAttribute{
MarkdownDescription: "The type of the IP pool reservation",
Expand Down Expand Up @@ -178,13 +178,12 @@ func (d *IPPoolReservationDataSource) Read(ctx context.Context, req datasource.R
tflog.Debug(ctx, fmt.Sprintf("%s: Beginning Read", config.Id.String()))

params := ""
params += "?siteId=" + url.QueryEscape(config.SiteId.ValueString())
params += "?siteId=" + url.QueryEscape(config.SiteId.ValueString()) + "&groupName=" + url.QueryEscape(config.Name.ValueString())
res, err := d.client.Get(config.getPath() + 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 @@ -30,6 +30,7 @@ import (
func TestAccDataSourceCcIPPoolReservation(t *testing.T) {
var checks []resource.TestCheckFunc
checks = append(checks, resource.TestCheckResourceAttr("data.catalystcenter_ip_pool_reservation.test", "name", "MyRes1"))
checks = append(checks, resource.TestCheckResourceAttr("data.catalystcenter_ip_pool_reservation.test", "ipv4_gateway", "172.32.1.1"))
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
Expand Down Expand Up @@ -79,8 +80,9 @@ func testAccDataSourceCcIPPoolReservationConfig() string {

config += `
data "catalystcenter_ip_pool_reservation" "test" {
id = catalystcenter_ip_pool_reservation.test.id
site_id = catalystcenter_area.test.id
name = "MyRes1"
depends_on = [catalystcenter_ip_pool_reservation.test]
}
`
return config
Expand Down
44 changes: 39 additions & 5 deletions internal/provider/model_catalystcenter_ip_pool_reservation.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ package provider
import (
"context"

"github.com/CiscoDevNet/terraform-provider-catalystcenter/internal/provider/helpers"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/tidwall/gjson"
"github.com/tidwall/sjson"
Expand Down Expand Up @@ -146,31 +147,64 @@ func (data IPPoolReservation) toBody(ctx context.Context, state IPPoolReservatio

// Section below is generated&owned by "gen/generator.go". //template:begin fromBody
func (data *IPPoolReservation) fromBody(ctx context.Context, res gjson.Result) {
if value := res.Get("groupName"); value.Exists() {
// Retrieve the 'id' attribute, if Data Source doesn't require id
if value := res.Get("response.0.id"); value.Exists() {
data.Id = types.StringValue(value.String())
} else {
data.Id = types.StringNull()
}
if value := res.Get("response.0.groupName"); value.Exists() {
data.Name = types.StringValue(value.String())
} else {
data.Name = types.StringNull()
}
if value := res.Get("response.0.ipPools.0.gateways.0"); value.Exists() {
data.Ipv4Gateway = types.StringValue(value.String())
} else {
data.Ipv4Gateway = types.StringNull()
}
if value := res.Get("response.0.ipPools.0.dhcpServerIps"); value.Exists() && len(value.Array()) > 0 {
data.Ipv4DhcpServers = helpers.GetStringSet(value.Array())
} else {
data.Ipv4DhcpServers = types.SetNull(types.StringType)
}
if value := res.Get("response.0.ipPools.0.dnsServerIps"); value.Exists() && len(value.Array()) > 0 {
data.Ipv4DnsServers = helpers.GetStringSet(value.Array())
} else {
data.Ipv4DnsServers = types.SetNull(types.StringType)
}
}

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

// Section below is generated&owned by "gen/generator.go". //template:begin updateFromBody
func (data *IPPoolReservation) updateFromBody(ctx context.Context, res gjson.Result) {
if value := res.Get("groupName"); value.Exists() && !data.Name.IsNull() {
if value := res.Get("response.0.groupName"); value.Exists() && !data.Name.IsNull() {
data.Name = types.StringValue(value.String())
} else {
data.Name = types.StringNull()
}
if value := res.Get("response.0.ipPools.0.gateways.0"); value.Exists() && !data.Ipv4Gateway.IsNull() {
data.Ipv4Gateway = types.StringValue(value.String())
} else {
data.Ipv4Gateway = types.StringNull()
}
if value := res.Get("response.0.ipPools.0.dhcpServerIps"); value.Exists() && !data.Ipv4DhcpServers.IsNull() {
data.Ipv4DhcpServers = helpers.GetStringSet(value.Array())
} else {
data.Ipv4DhcpServers = types.SetNull(types.StringType)
}
if value := res.Get("response.0.ipPools.0.dnsServerIps"); value.Exists() && !data.Ipv4DnsServers.IsNull() {
data.Ipv4DnsServers = helpers.GetStringSet(value.Array())
} else {
data.Ipv4DnsServers = types.SetNull(types.StringType)
}
}

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

// Section below is generated&owned by "gen/generator.go". //template:begin isNull
func (data *IPPoolReservation) isNull(ctx context.Context, res gjson.Result) bool {
if !data.Name.IsNull() {
return false
}
if !data.Type.IsNull() {
return false
}
Expand Down
11 changes: 5 additions & 6 deletions internal/provider/resource_catalystcenter_ip_pool_reservation.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,13 +202,13 @@ func (r *IPPoolReservationResource) Create(ctx context.Context, req resource.Cre
return
}
params = ""
params += "?siteId=" + url.QueryEscape(plan.SiteId.ValueString())
params += "?siteId=" + url.QueryEscape(plan.SiteId.ValueString()) + "&groupName=" + url.QueryEscape(plan.Name.ValueString())
res, err = r.client.Get(plan.getPath() + params)
if err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to retrieve object (GET), got error: %s, %s", err, res.String()))
return
}
plan.Id = types.StringValue(res.Get("response.#(groupName==\"" + plan.Name.ValueString() + "\").id").String())
plan.Id = types.StringValue(res.Get("response.0.id").String())

tflog.Debug(ctx, fmt.Sprintf("%s: Create finished successfully", plan.Id.ValueString()))

Expand All @@ -232,7 +232,7 @@ func (r *IPPoolReservationResource) Read(ctx context.Context, req resource.ReadR
tflog.Debug(ctx, fmt.Sprintf("%s: Beginning Read", state.Id.String()))

params := ""
params += "?siteId=" + url.QueryEscape(state.SiteId.ValueString())
params += "?siteId=" + url.QueryEscape(state.SiteId.ValueString()) + "&groupName=" + url.QueryEscape(state.Name.ValueString())
res, err := r.client.Get(state.getPath() + params)
if err != nil && strings.Contains(err.Error(), "StatusCode 404") {
resp.State.RemoveResource(ctx)
Expand All @@ -241,7 +241,6 @@ func (r *IPPoolReservationResource) Read(ctx context.Context, req resource.ReadR
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to retrieve object (GET), got error: %s, %s", err, res.String()))
return
}
res = res.Get("response.#(id==\"" + state.Id.ValueString() + "\")")

// If every attribute is set to null we are dealing with an import operation and therefore reading all attributes
if state.isNull(ctx, res) {
Expand Down Expand Up @@ -327,12 +326,12 @@ func (r *IPPoolReservationResource) ImportState(ctx context.Context, req resourc
if len(idParts) != 2 || idParts[0] == "" || idParts[1] == "" {
resp.Diagnostics.AddError(
"Unexpected Import Identifier",
fmt.Sprintf("Expected import identifier with format: <site_id>,<id>. Got: %q", req.ID),
fmt.Sprintf("Expected import identifier with format: <site_id>,<name>. Got: %q", req.ID),
)
return
}
resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("site_id"), idParts[0])...)
resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("id"), idParts[1])...)
resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("name"), idParts[1])...)
}

// End of section. //template:end import
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (
func TestAccCcIPPoolReservation(t *testing.T) {
var checks []resource.TestCheckFunc
checks = append(checks, resource.TestCheckResourceAttr("catalystcenter_ip_pool_reservation.test", "name", "MyRes1"))
checks = append(checks, resource.TestCheckResourceAttr("catalystcenter_ip_pool_reservation.test", "ipv4_gateway", "172.32.1.1"))

var steps []resource.TestStep
if os.Getenv("SKIP_MINIMUM_TEST") == "" {
Expand Down
1 change: 1 addition & 0 deletions templates/guides/changelog.md.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ description: |-
- Add `catalystcenter_fabric_vlan_to_ssid` resource and data source
- BREAKING CHANGE: Replace `catalystcenter_peer_transit_network` with `catalystcenter_transit_network` resource and data source to use `/dna/intent/api/v1/sda/transitNetworks` API endpoint, this resource now only works with Catalyst Center version 2.3.7.6+
- Add `catalystcenter_authentication_policy_server` resource and data source
- Fix issue with import of `catalystcenter_ip_pool_reservation` resource, [link](https://github.com/CiscoDevNet/terraform-provider-catalystcenter/issues/122)

## 0.1.10

Expand Down
Loading