diff --git a/docs/data-sources/vpn_list_policy_object.md b/docs/data-sources/vpn_list_policy_object.md
index ae0ed185..ee33678f 100644
--- a/docs/data-sources/vpn_list_policy_object.md
+++ b/docs/data-sources/vpn_list_policy_object.md
@@ -3,12 +3,12 @@
page_title: "sdwan_vpn_list_policy_object Data Source - terraform-provider-sdwan"
subcategory: "Policy Objects"
description: |-
- This data source can read the VPN List policy object.
+ This data source can read the VPN List Policy Object .
---
# sdwan_vpn_list_policy_object (Data Source)
-This data source can read the VPN List policy object.
+This data source can read the VPN List Policy Object .
## Example Usage
@@ -23,13 +23,13 @@ data "sdwan_vpn_list_policy_object" "example" {
### Required
-- `id` (String) The id of the policy object
+- `id` (String) The id of the object
### Read-Only
- `entries` (Attributes List) List of entries (see [below for nested schema](#nestedatt--entries))
- `name` (String) The name of the policy object
-- `version` (Number) The version of the policy object
+- `version` (Number) The version of the object
### Nested Schema for `entries`
diff --git a/docs/resources/vpn_list_policy_object.md b/docs/resources/vpn_list_policy_object.md
index bec58520..c577eff9 100644
--- a/docs/resources/vpn_list_policy_object.md
+++ b/docs/resources/vpn_list_policy_object.md
@@ -3,12 +3,12 @@
page_title: "sdwan_vpn_list_policy_object Resource - terraform-provider-sdwan"
subcategory: "Policy Objects"
description: |-
- This resource can manage a VPN List policy object.
+ This resource can manage a VPN List Policy Object .
---
# sdwan_vpn_list_policy_object (Resource)
-This resource can manage a VPN List policy object.
+This resource can manage a VPN List Policy Object .
## Example Usage
@@ -33,8 +33,8 @@ resource "sdwan_vpn_list_policy_object" "example" {
### Read-Only
-- `id` (String) The id of the policy object
-- `version` (Number) The version of the feature template
+- `id` (String) The id of the object
+- `version` (Number) The version of the object
### Nested Schema for `entries`
diff --git a/gen/definitions/policy_objects/vpn_list.yaml b/gen/definitions/generic/vpn_list_policy_object.yaml
similarity index 50%
rename from gen/definitions/policy_objects/vpn_list.yaml
rename to gen/definitions/generic/vpn_list_policy_object.yaml
index 27d449d5..55645ff6 100644
--- a/gen/definitions/policy_objects/vpn_list.yaml
+++ b/gen/definitions/generic/vpn_list_policy_object.yaml
@@ -1,7 +1,18 @@
---
-name: VPN List
-type: vpn
+name: VPN List Policy Object
+rest_endpoint: /template/policy/list/vpn/
+has_version: true
+id_attribute: listId
+doc_category: Policy Objects
attributes:
+ - model_name: type
+ value: vpn
+ - model_name: name
+ tf_name: name
+ type: String
+ mandatory: true
+ description: The name of the policy object
+ example: Example
- model_name: entries
type: List
mandatory: true
diff --git a/internal/provider/data_source_sdwan_vpn_list_policy_object.go b/internal/provider/data_source_sdwan_vpn_list_policy_object.go
index df17b519..03824265 100644
--- a/internal/provider/data_source_sdwan_vpn_list_policy_object.go
+++ b/internal/provider/data_source_sdwan_vpn_list_policy_object.go
@@ -50,15 +50,15 @@ func (d *VPNListPolicyObjectDataSource) Metadata(_ context.Context, req datasour
func (d *VPNListPolicyObjectDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) {
resp.Schema = schema.Schema{
// This description is used by the documentation generator and the language server.
- MarkdownDescription: "This data source can read the VPN List policy object.",
+ MarkdownDescription: "This data source can read the VPN List Policy Object .",
Attributes: map[string]schema.Attribute{
"id": schema.StringAttribute{
- MarkdownDescription: "The id of the policy object",
+ MarkdownDescription: "The id of the object",
Required: true,
},
"version": schema.Int64Attribute{
- MarkdownDescription: "The version of the policy object",
+ MarkdownDescription: "The version of the object",
Computed: true,
},
"name": schema.StringAttribute{
@@ -90,7 +90,7 @@ func (d *VPNListPolicyObjectDataSource) Configure(_ context.Context, req datasou
}
func (d *VPNListPolicyObjectDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
- var config VPNList
+ var config VPNListPolicyObject
// Read config
diags := req.Config.Get(ctx, &config)
diff --git a/internal/provider/data_source_sdwan_vpn_list_policy_object_test.go b/internal/provider/data_source_sdwan_vpn_list_policy_object_test.go
index 757048ff..178bbe7c 100644
--- a/internal/provider/data_source_sdwan_vpn_list_policy_object_test.go
+++ b/internal/provider/data_source_sdwan_vpn_list_policy_object_test.go
@@ -33,6 +33,7 @@ func TestAccDataSourceSdwanVPNListPolicyObject(t *testing.T) {
{
Config: testAccDataSourceSdwanVPNListPolicyObjectConfig,
Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr("data.sdwan_vpn_list_policy_object.test", "name", "Example"),
resource.TestCheckResourceAttr("data.sdwan_vpn_list_policy_object.test", "entries.0.vpn_id", "100-200"),
),
},
@@ -42,8 +43,9 @@ func TestAccDataSourceSdwanVPNListPolicyObject(t *testing.T) {
const testAccDataSourceSdwanVPNListPolicyObjectConfig = `
+
resource "sdwan_vpn_list_policy_object" "test" {
- name = "TF_TEST_MIN"
+ name = "Example"
entries = [{
vpn_id = "100-200"
}]
diff --git a/internal/provider/model_sdwan_vpn_list_policy_object.go b/internal/provider/model_sdwan_vpn_list_policy_object.go
index 5158050b..c609a2b9 100644
--- a/internal/provider/model_sdwan_vpn_list_policy_object.go
+++ b/internal/provider/model_sdwan_vpn_list_policy_object.go
@@ -27,25 +27,23 @@ import (
"github.com/tidwall/sjson"
)
-type VPNList struct {
- Id types.String `tfsdk:"id"`
- Version types.Int64 `tfsdk:"version"`
- Name types.String `tfsdk:"name"`
- Entries []VPNListEntries `tfsdk:"entries"`
+type VPNListPolicyObject struct {
+ Id types.String `tfsdk:"id"`
+ Version types.Int64 `tfsdk:"version"`
+ Name types.String `tfsdk:"name"`
+ Entries []VPNListPolicyObjectEntries `tfsdk:"entries"`
}
-type VPNListEntries struct {
+type VPNListPolicyObjectEntries struct {
VpnId types.String `tfsdk:"vpn_id"`
}
-func (data VPNList) getType() string {
- return "vpn"
-}
-
-func (data VPNList) toBody(ctx context.Context) string {
- body, _ := sjson.Set("", "description", "Desc Not Required")
- body, _ = sjson.Set(body, "name", data.Name.ValueString())
+func (data VPNListPolicyObject) toBody(ctx context.Context) string {
+ body := ""
body, _ = sjson.Set(body, "type", "vpn")
+ if !data.Name.IsNull() {
+ body, _ = sjson.Set(body, "name", data.Name.ValueString())
+ }
if len(data.Entries) > 0 {
body, _ = sjson.Set(body, "entries", []interface{}{})
for _, item := range data.Entries {
@@ -59,16 +57,16 @@ func (data VPNList) toBody(ctx context.Context) string {
return body
}
-func (data *VPNList) fromBody(ctx context.Context, res gjson.Result) {
+func (data *VPNListPolicyObject) fromBody(ctx context.Context, res gjson.Result) {
if value := res.Get("name"); value.Exists() {
data.Name = types.StringValue(value.String())
} else {
data.Name = types.StringNull()
}
if value := res.Get("entries"); value.Exists() {
- data.Entries = make([]VPNListEntries, 0)
+ data.Entries = make([]VPNListPolicyObjectEntries, 0)
value.ForEach(func(k, v gjson.Result) bool {
- item := VPNListEntries{}
+ item := VPNListPolicyObjectEntries{}
if cValue := v.Get("vpn"); cValue.Exists() {
item.VpnId = types.StringValue(cValue.String())
} else {
@@ -78,4 +76,22 @@ func (data *VPNList) fromBody(ctx context.Context, res gjson.Result) {
return true
})
}
+
+}
+
+func (data *VPNListPolicyObject) hasChanges(ctx context.Context, state *VPNListPolicyObject) bool {
+ hasChanges := false
+ if !data.Name.Equal(state.Name) {
+ hasChanges = true
+ }
+ if len(data.Entries) != len(state.Entries) {
+ hasChanges = true
+ } else {
+ for i := range data.Entries {
+ if !data.Entries[i].VpnId.Equal(state.Entries[i].VpnId) {
+ hasChanges = true
+ }
+ }
+ }
+ return hasChanges
}
diff --git a/internal/provider/provider.go b/internal/provider/provider.go
index ee8b785f..8b8f069b 100644
--- a/internal/provider/provider.go
+++ b/internal/provider/provider.go
@@ -261,7 +261,6 @@ func (p *SdwanProvider) Resources(ctx context.Context) []func() resource.Resourc
NewCiscoVPNInterfaceFeatureTemplateResource,
NewCiscoVPNInterfaceIPSecFeatureTemplateResource,
NewCLITemplateFeatureTemplateResource,
- NewVPNListPolicyObjectResource,
NewACLPolicyDefinitionResource,
NewAppProbeClassPolicyObjectResource,
NewApplicationAwareRoutingPolicyDefinitionResource,
@@ -292,6 +291,7 @@ func (p *SdwanProvider) Resources(ctx context.Context) []func() resource.Resourc
NewStandardCommunityListPolicyObjectResource,
NewTLOCListPolicyObjectResource,
NewTrafficDataPolicyDefinitionResource,
+ NewVPNListPolicyObjectResource,
NewVPNMembershipPolicyDefinitionResource,
NewCLIDeviceTemplateResource,
NewFeatureDeviceTemplateResource,
@@ -322,7 +322,6 @@ func (p *SdwanProvider) DataSources(ctx context.Context) []func() datasource.Dat
NewCiscoVPNInterfaceFeatureTemplateDataSource,
NewCiscoVPNInterfaceIPSecFeatureTemplateDataSource,
NewCLITemplateFeatureTemplateDataSource,
- NewVPNListPolicyObjectDataSource,
NewACLPolicyDefinitionDataSource,
NewAppProbeClassPolicyObjectDataSource,
NewApplicationAwareRoutingPolicyDefinitionDataSource,
@@ -353,6 +352,7 @@ func (p *SdwanProvider) DataSources(ctx context.Context) []func() datasource.Dat
NewStandardCommunityListPolicyObjectDataSource,
NewTLOCListPolicyObjectDataSource,
NewTrafficDataPolicyDefinitionDataSource,
+ NewVPNListPolicyObjectDataSource,
NewVPNMembershipPolicyDefinitionDataSource,
NewCLIDeviceTemplateDataSource,
NewFeatureDeviceTemplateDataSource,
diff --git a/internal/provider/resource_sdwan_vpn_list_policy_object.go b/internal/provider/resource_sdwan_vpn_list_policy_object.go
index 477af3c5..2d655bbf 100644
--- a/internal/provider/resource_sdwan_vpn_list_policy_object.go
+++ b/internal/provider/resource_sdwan_vpn_list_policy_object.go
@@ -22,6 +22,7 @@ package provider
import (
"context"
"fmt"
+ "strings"
"sync"
"github.com/CiscoDevNet/terraform-provider-sdwan/internal/provider/helpers"
@@ -57,22 +58,22 @@ func (r *VPNListPolicyObjectResource) Metadata(ctx context.Context, req resource
func (r *VPNListPolicyObjectResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
resp.Schema = schema.Schema{
// This description is used by the documentation generator and the language server.
- MarkdownDescription: helpers.NewAttributeDescription("This resource can manage a VPN List policy object.").String,
+ MarkdownDescription: helpers.NewAttributeDescription("This resource can manage a VPN List Policy Object .").String,
Attributes: map[string]schema.Attribute{
"id": schema.StringAttribute{
- MarkdownDescription: "The id of the policy object",
+ MarkdownDescription: "The id of the object",
Computed: true,
PlanModifiers: []planmodifier.String{
stringplanmodifier.UseStateForUnknown(),
},
},
"version": schema.Int64Attribute{
- MarkdownDescription: "The version of the feature template",
+ MarkdownDescription: "The version of the object",
Computed: true,
},
"name": schema.StringAttribute{
- MarkdownDescription: "The name of the policy object",
+ MarkdownDescription: helpers.NewAttributeDescription("The name of the policy object").String,
Required: true,
},
"entries": schema.ListNestedAttribute{
@@ -104,7 +105,7 @@ func (r *VPNListPolicyObjectResource) Configure(_ context.Context, req resource.
}
func (r *VPNListPolicyObjectResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
- var plan VPNList
+ var plan VPNListPolicyObject
// Read plan
diags := req.Plan.Get(ctx, &plan)
@@ -118,7 +119,7 @@ func (r *VPNListPolicyObjectResource) Create(ctx context.Context, req resource.C
// Create object
body := plan.toBody(ctx)
- res, err := r.client.Post("/template/policy/list/vpn", body)
+ res, err := r.client.Post("/template/policy/list/vpn/", body)
if err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to configure object (POST), got error: %s, %s", err, res.String()))
return
@@ -134,7 +135,7 @@ func (r *VPNListPolicyObjectResource) Create(ctx context.Context, req resource.C
}
func (r *VPNListPolicyObjectResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
- var state VPNList
+ var state VPNListPolicyObject
// Read state
diags := req.State.Get(ctx, &state)
@@ -163,7 +164,7 @@ func (r *VPNListPolicyObjectResource) Read(ctx context.Context, req resource.Rea
}
func (r *VPNListPolicyObjectResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
- var plan, state VPNList
+ var plan, state VPNListPolicyObject
// Read plan
diags := req.Plan.Get(ctx, &plan)
@@ -180,19 +181,22 @@ func (r *VPNListPolicyObjectResource) Update(ctx context.Context, req resource.U
tflog.Debug(ctx, fmt.Sprintf("%s: Beginning Update", plan.Name.ValueString()))
- body := plan.toBody(ctx)
- r.updateMutex.Lock()
- res, err := r.client.Put("/template/policy/list/vpn/"+plan.Id.ValueString(), body)
- r.updateMutex.Unlock()
- if err != nil {
- if res.Get("error.message").String() == "Failed to acquire lock, template or policy locked in edit mode." {
- resp.Diagnostics.AddWarning("Client Warning", "Failed to modify policy due to policy being locked by another change. Policy changes will not be applied. Re-run 'terraform apply' to try again.")
- } else {
- resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to configure object (PUT), got error: %s, %s", err, res.String()))
- return
+ if plan.hasChanges(ctx, &state) {
+ body := plan.toBody(ctx)
+ r.updateMutex.Lock()
+ res, err := r.client.Put("/template/policy/list/vpn/"+plan.Id.ValueString(), body)
+ r.updateMutex.Unlock()
+ if err != nil {
+ if strings.Contains(res.Get("error.message").String(), "Failed to acquire lock") {
+ resp.Diagnostics.AddWarning("Client Warning", "Failed to modify policy due to policy being locked by another change. Policy changes will not be applied. Re-run 'terraform apply' to try again.")
+ } else {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to configure object (PUT), got error: %s, %s", err, res.String()))
+ return
+ }
}
+ } else {
+ tflog.Debug(ctx, fmt.Sprintf("%s: No changes detected", plan.Name.ValueString()))
}
-
plan.Version = types.Int64Value(state.Version.ValueInt64() + 1)
tflog.Debug(ctx, fmt.Sprintf("%s: Update finished successfully", plan.Name.ValueString()))
@@ -202,7 +206,7 @@ func (r *VPNListPolicyObjectResource) Update(ctx context.Context, req resource.U
}
func (r *VPNListPolicyObjectResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
- var state VPNList
+ var state VPNListPolicyObject
// Read state
diags := req.State.Get(ctx, &state)
diff --git a/internal/provider/resource_sdwan_vpn_list_policy_object_test.go b/internal/provider/resource_sdwan_vpn_list_policy_object_test.go
index f6937633..022a3092 100644
--- a/internal/provider/resource_sdwan_vpn_list_policy_object_test.go
+++ b/internal/provider/resource_sdwan_vpn_list_policy_object_test.go
@@ -31,8 +31,9 @@ func TestAccSdwanVPNListPolicyObject(t *testing.T) {
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
Steps: []resource.TestStep{
{
- Config: testAccSdwanVPNListPolicyObjectConfig_all(),
+ Config: testAccSdwanVPNListPolicyObjectConfig,
Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr("sdwan_vpn_list_policy_object.test", "name", "Example"),
resource.TestCheckResourceAttr("sdwan_vpn_list_policy_object.test", "entries.0.vpn_id", "100-200"),
),
},
@@ -40,13 +41,13 @@ func TestAccSdwanVPNListPolicyObject(t *testing.T) {
})
}
-func testAccSdwanVPNListPolicyObjectConfig_all() string {
- return `
- resource "sdwan_vpn_list_policy_object" "test" {
- name = "TF_TEST_ALL"
- entries = [{
- vpn_id = "100-200"
- }]
- }
- `
+const testAccSdwanVPNListPolicyObjectConfig = `
+
+
+resource "sdwan_vpn_list_policy_object" "test" {
+ name = "Example"
+ entries = [{
+ vpn_id = "100-200"
+ }]
}
+`