diff --git a/docs/data-sources/networking_ip_interface_data_source.md b/docs/data-sources/networking_ip_interface_data_source.md
index 9dfba188..6d754de0 100644
--- a/docs/data-sources/networking_ip_interface_data_source.md
+++ b/docs/data-sources/networking_ip_interface_data_source.md
@@ -42,6 +42,7 @@ data "netapp-ontap_network_ip_interface" "ip_interface" {
- `ip` (Attributes) (see [below for nested schema](#nestedatt--ip))
- `location` (Attributes) (see [below for nested schema](#nestedatt--location))
- `scope` (String) IPInterface scope
+- `service_policy` (String) IPInterface service policy
diff --git a/docs/data-sources/networking_ip_interfaces_data_source.md b/docs/data-sources/networking_ip_interfaces_data_source.md
index bd1f0656..998c17dd 100644
--- a/docs/data-sources/networking_ip_interfaces_data_source.md
+++ b/docs/data-sources/networking_ip_interfaces_data_source.md
@@ -67,6 +67,7 @@ Read-Only:
- `name` (String) IPInterface name
- `scope` (String) IPInterface scope
- `svm_name` (String) IPInterface svm name. Applies only to SVM-scoped objects
+- `service_policy` (String) IPInterface service policy
diff --git a/docs/resources/network_ip_interface_resource.md b/docs/resources/network_ip_interface_resource.md
index 1dd2ceac..ce0cc3ec 100644
--- a/docs/resources/network_ip_interface_resource.md
+++ b/docs/resources/network_ip_interface_resource.md
@@ -38,6 +38,7 @@ resource "netapp-ontap_network_ip_interface" "example" {
home_port = "e0d"
home_node = "ontap_cluster_1-01"
}
+ service_policy = "default-management"
}
```
@@ -52,6 +53,10 @@ resource "netapp-ontap_network_ip_interface" "example" {
- `name` (String) IPInterface name
- `svm_name` (String) IPInterface svm name
+### Optional
+
+- `service_policy` (String) IPInterface service policy
+
### Read-Only
- `id` (String) IPInterface UUID
diff --git a/examples/resources/netapp-ontap_network_ip_interface/resource.tf b/examples/resources/netapp-ontap_network_ip_interface/resource.tf
index 97f2651b..ef706352 100644
--- a/examples/resources/netapp-ontap_network_ip_interface/resource.tf
+++ b/examples/resources/netapp-ontap_network_ip_interface/resource.tf
@@ -1,14 +1,15 @@
resource "netapp-ontap_network_ip_interface" "ip_interface" {
# required to know which system to interface with
cx_profile_name = "cluster4"
- name = "testme"
- svm_name = "ansibleSVM"
+ name = "testme"
+ svm_name = "ansibleSVM"
ip = {
address = "10.10.10.10"
netmask = 20
- }
+ }
location = {
home_port = "e0c"
home_node = "ontap_cluster_1-01"
}
+ service_policy = "default-management"
}
diff --git a/internal/interfaces/networking_ip_interface.go b/internal/interfaces/networking_ip_interface.go
index f5d562e5..d1c22da8 100644
--- a/internal/interfaces/networking_ip_interface.go
+++ b/internal/interfaces/networking_ip_interface.go
@@ -11,12 +11,13 @@ import (
// IPInterfaceGetDataModelONTAP describes the GET record data model using go types for mapping.
type IPInterfaceGetDataModelONTAP struct {
- Name string `mapstructure:"name"`
- Scope string `mapstructure:"scope"`
- SVM IPInterfaceSvmName `mapstructure:"svm"`
- UUID string `mapstructure:"uuid"`
- IP IPInterfaceGetIP `mapstructure:"ip"`
- Location IPInterfaceResourceLocation `mapstructure:"location"`
+ IP IPInterfaceGetIP `mapstructure:"ip"`
+ Location IPInterfaceResourceLocation `mapstructure:"location"`
+ Name string `mapstructure:"name"`
+ Scope string `mapstructure:"scope"`
+ ServicePolicy IPInterfaceServicePolicy `mapstructure:"service_policy"`
+ SVM IPInterfaceSvmName `mapstructure:"svm"`
+ UUID string `mapstructure:"uuid"`
}
// IPInterfaceGetIP describes the GET record data for IP.
@@ -27,10 +28,11 @@ type IPInterfaceGetIP struct {
// IPInterfaceResourceBodyDataModelONTAP describes the body data model using go types for mapping.
type IPInterfaceResourceBodyDataModelONTAP struct {
- Name string `mapstructure:"name"`
- SVM IPInterfaceSvmName `mapstructure:"svm,omitempty"` // API errors if body contains svm name when updating. can not use universal 'svm struct'
- IP IPInterfaceResourceIP `mapstructure:"ip"`
- Location IPInterfaceResourceLocation `mapstructure:"location"`
+ IP IPInterfaceResourceIP `mapstructure:"ip"`
+ Location IPInterfaceResourceLocation `mapstructure:"location"`
+ Name string `mapstructure:"name"`
+ ServicePolicy IPInterfaceServicePolicy `mapstructure:"service_policy"`
+ SVM IPInterfaceSvmName `mapstructure:"svm,omitempty"` // API errors if body contains svm name when updating. can not use universal 'svm struct'
}
// IPInterfaceSvmName describes the svm name specifcally for network ip interface.
@@ -61,6 +63,11 @@ type IPInterfaceResourceHomePort struct {
Node IPInterfaceResourceHomeNode `mapstructure:"node"`
}
+// IPInterfaceServicePolicy is the body data model for the service_policy field
+type IPInterfaceServicePolicy struct {
+ Name string `mapstructure:"name,omitempty"`
+}
+
// IPInterfaceDataSourceFilterModel describes filter model.
type IPInterfaceDataSourceFilterModel struct {
Name string `tfsdk:"name"`
@@ -78,7 +85,14 @@ func GetIPInterface(errorHandler *utils.ErrorHandler, r restclient.RestClient, i
// query.Set("svm.name", svmName)
// query.Set("scope", "svm")
// }
- query.Fields([]string{"name", "svm.name", "ip", "scope", "location"})
+ query.Fields([]string{
+ "name",
+ "svm.name",
+ "ip",
+ "scope",
+ "location",
+ "service_policy",
+ })
statusCode, response, err := r.GetNilOrOneRecord(api, query, nil)
if err == nil && response == nil {
err = fmt.Errorf("no response for GET %s", api)
@@ -107,7 +121,14 @@ func GetIPInterfaceByName(errorHandler *utils.ErrorHandler, r restclient.RestCli
query.Set("svm.name", svmName)
query.Set("scope", "svm")
}
- query.Fields([]string{"name", "svm.name", "ip", "scope", "location"})
+ query.Fields([]string{
+ "name",
+ "svm.name",
+ "ip",
+ "scope",
+ "location",
+ "service_policy",
+ })
statusCode, response, err := r.GetNilOrOneRecord(api, query, nil)
if err == nil && response == nil {
err = fmt.Errorf("no response for GET %s", api)
@@ -129,7 +150,14 @@ func GetIPInterfaceByName(errorHandler *utils.ErrorHandler, r restclient.RestCli
func GetListIPInterfaces(errorHandler *utils.ErrorHandler, r restclient.RestClient, filter *IPInterfaceDataSourceFilterModel) ([]IPInterfaceGetDataModelONTAP, error) {
api := "network/ip/interfaces"
query := r.NewQuery()
- query.Fields([]string{"name", "svm.name", "ip", "scope", "location"})
+ query.Fields([]string{
+ "name",
+ "svm.name",
+ "ip",
+ "scope",
+ "location",
+ "service_policy",
+ })
if filter != nil {
if filter.Name != "" {
diff --git a/internal/provider/networking/network_ip_interface_data_source.go b/internal/provider/networking/network_ip_interface_data_source.go
index ac9460be..c6af3b61 100644
--- a/internal/provider/networking/network_ip_interface_data_source.go
+++ b/internal/provider/networking/network_ip_interface_data_source.go
@@ -5,13 +5,12 @@ import (
"fmt"
"strconv"
- "github.com/netapp/terraform-provider-netapp-ontap/internal/provider/connection"
-
"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-log/tflog"
"github.com/netapp/terraform-provider-netapp-ontap/internal/interfaces"
+ "github.com/netapp/terraform-provider-netapp-ontap/internal/provider/connection"
"github.com/netapp/terraform-provider-netapp-ontap/internal/utils"
)
@@ -49,6 +48,7 @@ type IPInterfaceDataSourceModel struct {
Scope types.String `tfsdk:"scope"`
IP *IPDataSourceModel `tfsdk:"ip"`
Location *LocationDataSourceModel `tfsdk:"location"`
+ ServicePolicy types.String `tfsdk:"service_policy"`
}
// IPDataSourceModel describes the data source model for IP address and mask.
@@ -117,6 +117,10 @@ func (d *IPInterfaceDataSource) Schema(ctx context.Context, req datasource.Schem
},
Computed: true,
},
+ "service_policy": schema.StringAttribute{
+ Computed: true,
+ MarkdownDescription: "IPInterface service policy",
+ },
},
}
}
@@ -182,6 +186,7 @@ func (d *IPInterfaceDataSource) Read(ctx context.Context, req datasource.ReadReq
HomeNode: types.StringValue(restInfo.Location.HomeNode.Name),
HomePort: types.StringValue(restInfo.Location.HomePort.Name),
}
+ data.ServicePolicy = types.StringValue(restInfo.ServicePolicy.Name)
// Write logs using the tflog package
// Documentation: https://terraform.io/plugin/log
diff --git a/internal/provider/networking/network_ip_interface_resource.go b/internal/provider/networking/network_ip_interface_resource.go
index 5755f342..9d0e8d67 100644
--- a/internal/provider/networking/network_ip_interface_resource.go
+++ b/internal/provider/networking/network_ip_interface_resource.go
@@ -6,8 +6,6 @@ import (
"strconv"
"strings"
- "github.com/netapp/terraform-provider-netapp-ontap/internal/provider/connection"
-
"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
@@ -16,6 +14,7 @@ import (
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-log/tflog"
"github.com/netapp/terraform-provider-netapp-ontap/internal/interfaces"
+ "github.com/netapp/terraform-provider-netapp-ontap/internal/provider/connection"
"github.com/netapp/terraform-provider-netapp-ontap/internal/utils"
)
@@ -65,6 +64,7 @@ type IPInterfaceResourceModel struct {
SVMName types.String `tfsdk:"svm_name"`
IP *IPInterfaceResourceIP `tfsdk:"ip"`
Location *IPInterfaceResourceLocation `tfsdk:"location"`
+ ServicePolicy types.String `tfsdk:"service_policy"`
UUID types.String `tfsdk:"id"`
}
@@ -121,6 +121,14 @@ func (r *IPInterfaceResource) Schema(ctx context.Context, req resource.SchemaReq
},
Required: true,
},
+ "service_policy": schema.StringAttribute{
+ MarkdownDescription: "IPInterface service policy",
+ Optional: true,
+ Computed: true,
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.UseStateForUnknown(),
+ },
+ },
"id": schema.StringAttribute{
MarkdownDescription: "IPInterface UUID",
Computed: true,
@@ -202,6 +210,9 @@ func (r *IPInterfaceResource) Read(ctx context.Context, req resource.ReadRequest
}
ip.Netmask = types.Int64Value(int64(intValue))
data.IP = &ip
+
+ data.ServicePolicy = types.StringValue(restInfo.ServicePolicy.Name)
+
// Write logs using the tflog package
// Documentation: https://terraform.io/plugin/log
tflog.Debug(ctx, fmt.Sprintf("read a resource: %#v", data))
@@ -238,6 +249,7 @@ func (r *IPInterfaceResource) Create(ctx context.Context, req resource.CreateReq
body.Location.HomeNode = interfaces.IPInterfaceResourceHomeNode{
Name: data.Location.HomeNode.ValueString(),
}
+ body.ServicePolicy.Name = data.ServicePolicy.ValueString()
client, err := connection.GetRestClient(errorHandler, r.config, data.CxProfileName)
if err != nil {
@@ -254,6 +266,16 @@ func (r *IPInterfaceResource) Create(ctx context.Context, req resource.CreateReq
tflog.Trace(ctx, fmt.Sprintf("created a resource, UUID=%s", data.UUID))
+ if data.ServicePolicy.IsUnknown() {
+ // read newly created interface to populate service policy (not fetched by CreateIPInterface)
+ restInfo, err := interfaces.GetIPInterface(errorHandler, *client, data.UUID.ValueString())
+ if err != nil {
+ // error reporting done inside GetIPInterface
+ return
+ }
+ data.ServicePolicy = types.StringValue(restInfo.ServicePolicy.Name)
+ }
+
// Save data into Terraform state
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
}
@@ -284,6 +306,7 @@ func (r *IPInterfaceResource) Update(ctx context.Context, req resource.UpdateReq
body.Location.HomeNode = interfaces.IPInterfaceResourceHomeNode{
Name: data.Location.HomeNode.ValueString(),
}
+ body.ServicePolicy.Name = data.ServicePolicy.ValueString()
client, err := connection.GetRestClient(errorHandler, r.config, data.CxProfileName)
if err != nil {
diff --git a/internal/provider/networking/network_ip_interface_resource_alias_test.go b/internal/provider/networking/network_ip_interface_resource_alias_test.go
index a7c4d0d5..fef70a61 100644
--- a/internal/provider/networking/network_ip_interface_resource_alias_test.go
+++ b/internal/provider/networking/network_ip_interface_resource_alias_test.go
@@ -18,28 +18,30 @@ func TestAccNetworkIpInterfaceResourceAlias(t *testing.T) {
Steps: []resource.TestStep{
// non-existant SVM return code 2621462. Must happen before create/read
{
- Config: testAccNetworkIPInterfaceResourceConfigAlias("non-existant", "10.10.10.10", "ontap_cluster_1-01"),
+ Config: testAccNetworkIPInterfaceResourceConfigAlias("non-existant", "10.10.10.10", "ontap_cluster_1-01", "default-data-files"),
ExpectError: regexp.MustCompile("2621462"),
},
// non-existant home node
{
- Config: testAccNetworkIPInterfaceResourceConfigAlias("terraform", "10.10.10.10", "non-existant_home_node"),
- ExpectError: regexp.MustCompile("393271"),
+ Config: testAccNetworkIPInterfaceResourceConfigAlias("terraform", "10.10.10.10", "non-existant_home_node", "default-data-files"),
+ ExpectError: regexp.MustCompile("53281680"),
},
// Create and Read
// {
- // Config: testAccNetworkIPInterfaceResourceConfigAlias("terraform", "10.10.10.10", "ontap_cluster_1-01"),
+ // Config: testAccNetworkIPInterfaceResourceConfigAlias("terraform", "10.10.10.10", "ontap_cluster_1-01", "default-data-files"),
// Check: resource.ComposeTestCheckFunc(
// resource.TestCheckResourceAttr("netapp-ontap_networking_ip_interface_resource.example", "name", "test-interface"),
// resource.TestCheckResourceAttr("netapp-ontap_networking_ip_interface_resource.example", "svm_name", "terraform"),
+ // resource.TestCheckResourceAttr("netapp-ontap_networking_ip_interface_resource.example", "service_policy", "default-data-files"),
// ),
// },
// // Update and Read
// {
- // Config: testAccNetworkIPInterfaceResourceConfigAlias("terraform", "10.10.10.20", "ontap_cluster_1-01"),
+ // Config: testAccNetworkIPInterfaceResourceConfigAlias("terraform", "10.10.10.20", "ontap_cluster_1-01", "default-data-iscsi"),
// Check: resource.ComposeTestCheckFunc(
// resource.TestCheckResourceAttr("netapp-ontap_networking_ip_interface_resource.example", "name", "test-interface"),
// resource.TestCheckResourceAttr("netapp-ontap_networking_ip_interface_resource.example", "ip.address", "10.10.10.20"),
+ // resource.TestCheckResourceAttr("netapp-ontap_networking_ip_interface_resource.example", "service_policy", "default-data-iscsi"),
// ),
// },
// Test importing a resource
@@ -56,7 +58,7 @@ func TestAccNetworkIpInterfaceResourceAlias(t *testing.T) {
})
}
-func testAccNetworkIPInterfaceResourceConfigAlias(svmName, address, homeNode string) string {
+func testAccNetworkIPInterfaceResourceConfigAlias(svmName, address, homeNode, servicePolicy string) string {
host := os.Getenv("TF_ACC_NETAPP_HOST5")
admin := os.Getenv("TF_ACC_NETAPP_USER")
password := os.Getenv("TF_ACC_NETAPP_PASS2")
@@ -89,6 +91,7 @@ resource "netapp-ontap_networking_ip_interface_resource" "example" {
home_port = "e0d"
home_node = "%s"
}
+ service_policy = "%s"
}
-`, host, admin, password, svmName, address, homeNode)
+`, host, admin, password, svmName, address, homeNode, servicePolicy)
}
diff --git a/internal/provider/networking/network_ip_interface_resource_test.go b/internal/provider/networking/network_ip_interface_resource_test.go
index 185dab69..c2f0d0f3 100644
--- a/internal/provider/networking/network_ip_interface_resource_test.go
+++ b/internal/provider/networking/network_ip_interface_resource_test.go
@@ -18,28 +18,30 @@ func TestAccNetworkIpInterfaceResource(t *testing.T) {
Steps: []resource.TestStep{
// non-existant SVM return code 2621462. Must happen before create/read
{
- Config: testAccNetworkIPInterfaceResourceConfig("non-existant", "10.10.10.10", "ontap_cluster_1-01"),
+ Config: testAccNetworkIPInterfaceResourceConfig("non-existant", "10.10.10.10", "ontap_cluster_1-01", "default-data-files"),
ExpectError: regexp.MustCompile("2621462"),
},
// non-existant home node
{
- Config: testAccNetworkIPInterfaceResourceConfig("terraform", "10.10.10.10", "non-existant_home_node"),
- ExpectError: regexp.MustCompile("393271"),
+ Config: testAccNetworkIPInterfaceResourceConfig("terraform", "10.10.10.10", "non-existant_home_node", "default-data-files"),
+ ExpectError: regexp.MustCompile("53281680"),
},
// Create and Read
// {
- // Config: testAccNetworkIPInterfaceResourceConfig("svm0", "10.10.10.10", "ontap_cluster_1-01"),
+ // Config: testAccNetworkIPInterfaceResourceConfig("svm0", "10.10.10.10", "ontap_cluster_1-01", "default-data-files"),
// Check: resource.ComposeTestCheckFunc(
// resource.TestCheckResourceAttr("netapp-ontap_network_ip_interface.example", "name", "test-interface"),
// resource.TestCheckResourceAttr("netapp-ontap_network_ip_interface.example", "svm_name", "svm0"),
+ // resource.TestCheckResourceAttr("netapp-ontap_network_ip_interface.example", "service_policy", "default-data-files"),
// ),
// },
// // Update and Read
// {
- // Config: testAccNetworkIPInterfaceResourceConfig("svm0", "10.10.10.20", "ontap_cluster_1-01"),
+ // Config: testAccNetworkIPInterfaceResourceConfig("svm0", "10.10.10.20", "ontap_cluster_1-01", "default-data-iscsi"),
// Check: resource.ComposeTestCheckFunc(
// resource.TestCheckResourceAttr("netapp-ontap_network_ip_interface.example", "name", "test-interface"),
// resource.TestCheckResourceAttr("netapp-ontap_network_ip_interface.example", "ip.address", "10.10.10.20"),
+ // resource.TestCheckResourceAttr("netapp-ontap_network_ip_interface.example", "service_policy", "default-data-iscsi"),
// ),
// },
// // Test importing a resource
@@ -56,7 +58,7 @@ func TestAccNetworkIpInterfaceResource(t *testing.T) {
})
}
-func testAccNetworkIPInterfaceResourceConfig(svmName, address, homeNode string) string {
+func testAccNetworkIPInterfaceResourceConfig(svmName, address, homeNode, servicePolicy string) string {
host := os.Getenv("TF_ACC_NETAPP_HOST5")
admin := os.Getenv("TF_ACC_NETAPP_USER")
password := os.Getenv("TF_ACC_NETAPP_PASS2")
@@ -89,6 +91,7 @@ resource "netapp-ontap_network_ip_interface" "example" {
home_port = "e0d"
home_node = "%s"
}
+ service_policy = "%s"
}
-`, host, admin, password, svmName, address, homeNode)
+`, host, admin, password, svmName, address, homeNode, servicePolicy)
}
diff --git a/internal/provider/networking/network_ip_interfaces_data_source.go b/internal/provider/networking/network_ip_interfaces_data_source.go
index 09eb4402..420d71cf 100644
--- a/internal/provider/networking/network_ip_interfaces_data_source.go
+++ b/internal/provider/networking/network_ip_interfaces_data_source.go
@@ -5,13 +5,12 @@ import (
"fmt"
"strconv"
- "github.com/netapp/terraform-provider-netapp-ontap/internal/provider/connection"
-
"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-log/tflog"
"github.com/netapp/terraform-provider-netapp-ontap/internal/interfaces"
+ "github.com/netapp/terraform-provider-netapp-ontap/internal/provider/connection"
"github.com/netapp/terraform-provider-netapp-ontap/internal/utils"
)
@@ -133,6 +132,10 @@ func (d *IPInterfacesDataSource) Schema(ctx context.Context, req datasource.Sche
},
Computed: true,
},
+ "service_policy": schema.StringAttribute{
+ Computed: true,
+ MarkdownDescription: "IPInterface service policy",
+ },
},
},
Computed: true,
@@ -199,6 +202,7 @@ func (d *IPInterfacesDataSource) Read(ctx context.Context, req datasource.ReadRe
Name: types.StringValue(record.Name),
Scope: types.StringValue(record.Scope),
SVMName: types.StringValue(record.SVM.Name),
+ ServicePolicy: types.StringValue(record.ServicePolicy.Name),
}
intNetmask, err := strconv.Atoi(record.IP.Netmask)
if err != nil {