From b9d19417fd2bab242b2207b4f3932eda195c252b Mon Sep 17 00:00:00 2001 From: Chris Archibald Date: Fri, 20 Oct 2023 16:55:43 +0000 Subject: [PATCH] Sync bitbucket and GitHub --- .../networking_ip_interface_data_source.md | 35 +++- .../networking_ip_interfaces_data_source.md | 41 +++- .../data-source.tf | 6 +- .../data-source.tf | 6 +- .../interfaces/networking_ip_interface.go | 28 ++- .../networking_ip_interface_test.go | 179 ++++++++++++++++++ .../networking_ip_interface_data_source.go | 75 ++++++-- .../networking_ip_interfaces_data_source.go | 70 +++++-- 8 files changed, 390 insertions(+), 50 deletions(-) create mode 100644 internal/interfaces/networking_ip_interface_test.go diff --git a/docs/data-sources/networking_ip_interface_data_source.md b/docs/data-sources/networking_ip_interface_data_source.md index da496b79..1f05ceea 100644 --- a/docs/data-sources/networking_ip_interface_data_source.md +++ b/docs/data-sources/networking_ip_interface_data_source.md @@ -3,13 +3,21 @@ page_title: "netapp-ontap_networking_ip_interface_data_source Data Source - terraform-provider-netapp-ontap" subcategory: "networking" description: |- - IPInterface data source + Retrieves the details of IP interface of SVMs. --- -# netapp-ontap_networking_ip_interface_data_source (Data Source) +# Data Source ip_interface -IPInterface data source +Retrieves the details of IP interface of SVMs. +## Example Usage +```terraform +data "netapp-ontap_networking_ip_interface_data_source" "ip_interface" { + # required to know which system to interface with + cx_profile_name = "cluster4" + name = "cluster_mgmt" +} +``` @@ -22,10 +30,29 @@ IPInterface data source ### Optional -- `svm_name` (String) IPInterface svm name +- `svm_name` (String) IPInterface svm name. Applies only to SVM-scoped objects ### Read-Only +- `ip` (Attributes) (see [below for nested schema](#nestedatt--ip)) +- `location` (Attributes) (see [below for nested schema](#nestedatt--location)) - `scope` (String) IPInterface scope + +### Nested Schema for `ip` + +Read-Only: + +- `address` (String) IPInterface IP address +- `netmask` (Number) IPInterface IP netmask + + + +### Nested Schema for `location` + +Read-Only: + +- `home_node` (String) IPInterface home node +- `home_port` (String) IPInterface home port + diff --git a/docs/data-sources/networking_ip_interfaces_data_source.md b/docs/data-sources/networking_ip_interfaces_data_source.md index 95500298..cb4bdbff 100644 --- a/docs/data-sources/networking_ip_interfaces_data_source.md +++ b/docs/data-sources/networking_ip_interfaces_data_source.md @@ -1,15 +1,27 @@ --- # generated by https://github.com/hashicorp/terraform-plugin-docs -page_title: "netapp-ontap_networking_ip_interfaces_data_source Data Source - terraform-provider-netapp-ontap" +page_title: "netapp-ontap_netapp-ontap_networking_ip_interfaces_data_source Data Source - terraform-provider-netapp-ontap" subcategory: "networking" description: |- - IPInterfaces data source + Retrieves the details of IP interfaces of SVMs. --- -# netapp-ontap_networking_ip_interfaces_data_source (Data Source) +# Data Source ip_interfaces -IPInterfaces data source +Retrieves the details of IP interfaces of SVMs. +## Example Usage +```terraform +data "netapp-ontap_networking_ip_interfaces_data_source" "ip_interfaces" { + # required to know which system to interface with + cx_profile_name = "cluster4" + filter = { + name = "lif*" + svm_name = "*" + scope = "svm" + } +} +``` @@ -40,17 +52,30 @@ Optional: ### Nested Schema for `ip_interfaces` -Required: +Read-Only: - `cx_profile_name` (String) Connection profile name +- `ip` (Attributes) (see [below for nested schema](#nestedatt--ip_interfaces--ip)) +- `location` (Attributes) (see [below for nested schema](#nestedatt--ip_interfaces--location)) - `name` (String) IPInterface name +- `scope` (String) IPInterface scope +- `svm_name` (String) IPInterface svm name. Applies only to SVM-scoped objects -Optional: + +### Nested Schema for `ip_interfaces.ip` -- `svm_name` (String) IPInterface svm name +Read-Only: + +- `address` (String) IPInterface IP address +- `netmask` (Number) IPInterface IP netmask + + + +### Nested Schema for `ip_interfaces.location` Read-Only: -- `scope` (String) IPInterface scope +- `home_node` (String) IPInterface home node +- `home_port` (String) IPInterface home port diff --git a/examples/data-sources/netapp-ontap_networking_ip_interface/data-source.tf b/examples/data-sources/netapp-ontap_networking_ip_interface/data-source.tf index e71943fa..837e23b5 100644 --- a/examples/data-sources/netapp-ontap_networking_ip_interface/data-source.tf +++ b/examples/data-sources/netapp-ontap_networking_ip_interface/data-source.tf @@ -1,5 +1,5 @@ -data "netapp-ontap_ip_interface_data_source" "ip_interface" { +data "netapp-ontap_networking_ip_interface_data_source" "ip_interface" { # required to know which system to interface with - cx_profile_name = "cluster1" - name = "laurentn-vsim1_clus_1" + cx_profile_name = "cluster4" + name = "cluster_mgmt" } diff --git a/examples/data-sources/netapp-ontap_networking_ip_interfaces/data-source.tf b/examples/data-sources/netapp-ontap_networking_ip_interfaces/data-source.tf index 6067136e..8825369a 100644 --- a/examples/data-sources/netapp-ontap_networking_ip_interfaces/data-source.tf +++ b/examples/data-sources/netapp-ontap_networking_ip_interfaces/data-source.tf @@ -2,6 +2,8 @@ data "netapp-ontap_networking_ip_interfaces_data_source" "ip_interfaces" { # required to know which system to interface with cx_profile_name = "cluster4" filter = { - name = "*svm*" + name = "lif*" + svm_name = "*" + scope = "svm" } -} \ No newline at end of file +} diff --git a/internal/interfaces/networking_ip_interface.go b/internal/interfaces/networking_ip_interface.go index 3fb151f1..3781e824 100644 --- a/internal/interfaces/networking_ip_interface.go +++ b/internal/interfaces/networking_ip_interface.go @@ -2,7 +2,6 @@ package interfaces import ( "fmt" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/mitchellh/mapstructure" "github.com/netapp/terraform-provider-netapp-ontap/internal/restclient" @@ -13,7 +12,7 @@ import ( type IPInterfaceGetDataModelONTAP struct { Name string `mapstructure:"name"` Scope string `mapstructure:"scope"` - SVMName string `mapstructure:"svm.name"` + SVM IPInterfaceSvmName `mapstructure:"svm"` UUID string `mapstructure:"uuid"` IP IPInterfaceGetIP `mapstructure:"ip"` Location IPInterfaceResourceLocation `mapstructure:"location"` @@ -61,6 +60,13 @@ type IPInterfaceResourceHomePort struct { Node IPInterfaceResourceHomeNode `mapstructure:"node"` } +// IPInterfaceDataSourceFilterModel describes filter model. +type IPInterfaceDataSourceFilterModel struct { + Name string `tfsdk:"name"` + SVMName string `tfsdk:"svm_name"` + Scope string `tfsdk:"scope"` +} + // GetIPInterface to get ip_interface info func GetIPInterface(errorHandler *utils.ErrorHandler, r restclient.RestClient, name string, svmName string) (*IPInterfaceGetDataModelONTAP, error) { api := "network/ip/interfaces" @@ -90,18 +96,24 @@ func GetIPInterface(errorHandler *utils.ErrorHandler, r restclient.RestClient, n return &dataONTAP, nil } -// GetIPInterfaces to get ip_interface info for all resources matching a filter -func GetIPInterfaces(errorHandler *utils.ErrorHandler, r restclient.RestClient, filter *IPInterfaceGetDataModelONTAP) ([]IPInterfaceGetDataModelONTAP, error) { +// GetListIPInterfaces to get ip_interface info for all resources matching a filter +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"}) + if filter != nil { - var filterMap map[string]interface{} - if err := mapstructure.Decode(filter, &filterMap); err != nil { - return nil, errorHandler.MakeAndReportError("error encoding ip_interface filter info", fmt.Sprintf("error on filter %#v: %s", filter, err)) + if filter.Name != "" { + query.Set("name", filter.Name) + } + if filter.SVMName != "" { + query.Set("svm.name", filter.SVMName) + } + if filter.Scope != "" { + query.Set("scope", filter.Scope) } - query.SetValues(filterMap) } + statusCode, response, err := r.GetZeroOrMoreRecords(api, query, nil) if err == nil && response == nil { err = fmt.Errorf("no response for GET %s", api) diff --git a/internal/interfaces/networking_ip_interface_test.go b/internal/interfaces/networking_ip_interface_test.go new file mode 100644 index 00000000..31b976ad --- /dev/null +++ b/internal/interfaces/networking_ip_interface_test.go @@ -0,0 +1,179 @@ +package interfaces + +import ( + "context" + "errors" + "fmt" + "reflect" + "testing" + + "github.com/hashicorp/terraform-plugin-framework/diag" + "github.com/mitchellh/mapstructure" + "github.com/netapp/terraform-provider-netapp-ontap/internal/restclient" + "github.com/netapp/terraform-provider-netapp-ontap/internal/utils" +) + +var ipInterfaceRecord = IPInterfaceGetDataModelONTAP{ + Name: "string", + SVM: IPInterfaceSvmName{ + Name: "string", + }, + Scope: "string", + UUID: "string", + IP: IPInterfaceGetIP{ + Address: "string", + Netmask: "string", + }, + Location: IPInterfaceResourceLocation{ + HomeNode: &IPInterfaceResourceHomeNode{ + Name: "string", + }, + HomePort: &IPInterfaceResourceHomePort{ + Name: "string", + Node: IPInterfaceResourceHomeNode{ + Name: "string", + }, + }, + }, +} + +func TestGetIPInterface(t *testing.T) { + errorHandler := utils.NewErrorHandler(context.Background(), &diag.Diagnostics{}) + + var recordInterface map[string]any + err := mapstructure.Decode(ipInterfaceRecord, &recordInterface) + if err != nil { + panic(err) + } + + var badRecordInterface map[string]any + badRecord := struct{ Name int }{123} + err = mapstructure.Decode(badRecord, &badRecordInterface) + if err != nil { + panic(err) + } + + noRecords := restclient.RestResponse{NumRecords: 0, Records: []map[string]any{}} + oneRecord := restclient.RestResponse{NumRecords: 1, Records: []map[string]any{recordInterface}} + twoRecords := restclient.RestResponse{NumRecords: 2, Records: []map[string]any{recordInterface, recordInterface}} + genericError := errors.New("generic error for UT") + badRecordResponse := restclient.RestResponse{NumRecords: 1, Records: []map[string]any{badRecordInterface}} + responses := map[string][]restclient.MockResponse{ + "test_no_records_1": { + {ExpectedMethod: "GET", ExpectedURL: "network/ip/interfaces", StatusCode: 200, Response: noRecords, Err: nil}, + }, + "test_one_record_1": { + {ExpectedMethod: "GET", ExpectedURL: "network/ip/interfaces", StatusCode: 200, Response: oneRecord, Err: nil}, + }, + "test_two_records_error": { + {ExpectedMethod: "GET", ExpectedURL: "network/ip/interfaces", StatusCode: 200, Response: twoRecords, Err: genericError}, + }, + "test_decode_error": { + {ExpectedMethod: "GET", ExpectedURL: "network/ip/interfaces", StatusCode: 200, Response: badRecordResponse, Err: nil}, + }, + } + tests := []struct { + name string + responses []restclient.MockResponse + // args args + want *IPInterfaceGetDataModelONTAP + wantErr bool + }{ + {name: "test_no_records_1", responses: responses["test_no_records_1"], want: nil, wantErr: true}, + {name: "test_one_record_1", responses: responses["test_one_record_1"], want: &ipInterfaceRecord, wantErr: false}, + {name: "test_two_records_error", responses: responses["test_two_records_error"], want: nil, wantErr: true}, + {name: "test_decode_error", responses: responses["test_decode_error"], want: nil, wantErr: true}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + r, err := restclient.NewMockedRestClient(tt.responses) + if err != nil { + panic(err) + } + got, err := GetIPInterface(errorHandler, *r, "name", "svmName") + if err != nil { + fmt.Printf("err: %s\n", err) + } + if (err != nil) != tt.wantErr { + t.Errorf("GetIPInterface() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetIPInterface() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestGetListIPInterfaces(t *testing.T) { + errorHandler := utils.NewErrorHandler(context.Background(), &diag.Diagnostics{}) + + var recordInterface map[string]any + err := mapstructure.Decode(ipInterfaceRecord, &recordInterface) + if err != nil { + panic(err) + } + + var badRecordInterface map[string]any + badRecord := struct{ Name int }{123} + err = mapstructure.Decode(badRecord, &badRecordInterface) + if err != nil { + panic(err) + } + + noRecords := restclient.RestResponse{NumRecords: 0, Records: []map[string]any{}} + oneRecord := restclient.RestResponse{NumRecords: 1, Records: []map[string]any{recordInterface}} + twoRecords := restclient.RestResponse{NumRecords: 2, Records: []map[string]any{recordInterface, recordInterface}} + badRecordResponse := restclient.RestResponse{NumRecords: 1, Records: []map[string]any{badRecordInterface}} + + var ipInterfacesOneRecord = []IPInterfaceGetDataModelONTAP{ipInterfaceRecord} + var ipInterfacesTwoRecords = []IPInterfaceGetDataModelONTAP{ipInterfaceRecord, ipInterfaceRecord} + + responses := map[string][]restclient.MockResponse{ + "test_no_records_1": { + {ExpectedMethod: "GET", ExpectedURL: "network/ip/interfaces", StatusCode: 200, Response: noRecords, Err: nil}, + }, + "test_one_record_1": { + {ExpectedMethod: "GET", ExpectedURL: "network/ip/interfaces", StatusCode: 200, Response: oneRecord, Err: nil}, + }, + "test_two_records_1": { + {ExpectedMethod: "GET", ExpectedURL: "network/ip/interfaces", StatusCode: 200, Response: twoRecords, Err: nil}, + }, + "test_decode_error": { + {ExpectedMethod: "GET", ExpectedURL: "network/ip/interfaces", StatusCode: 200, Response: badRecordResponse, Err: nil}, + }, + } + tests := []struct { + name string + responses []restclient.MockResponse + // args args + want []IPInterfaceGetDataModelONTAP + wantErr bool + }{ + {name: "test_no_records_1", responses: responses["test_no_records_1"], want: nil, wantErr: false}, + {name: "test_one_record_1", responses: responses["test_one_record_1"], want: ipInterfacesOneRecord, wantErr: false}, + {name: "test_two_records_1", responses: responses["test_two_records_1"], want: ipInterfacesTwoRecords, wantErr: false}, + {name: "test_decode_error", responses: responses["test_decode_error"], want: nil, wantErr: true}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + r, err := restclient.NewMockedRestClient(tt.responses) + if err != nil { + panic(err) + } + got, err := GetListIPInterfaces(errorHandler, *r, &IPInterfaceDataSourceFilterModel{}) + if err != nil { + fmt.Printf("err: %s\n", err) + } + if (err != nil) != tt.wantErr { + t.Errorf("GetListIPInterfaces() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetListIPInterfaces() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/internal/provider/networking_ip_interface_data_source.go b/internal/provider/networking_ip_interface_data_source.go index 6403521c..735ab8d8 100644 --- a/internal/provider/networking_ip_interface_data_source.go +++ b/internal/provider/networking_ip_interface_data_source.go @@ -3,6 +3,7 @@ package provider import ( "context" "fmt" + "strconv" "github.com/hashicorp/terraform-plugin-framework/datasource" "github.com/hashicorp/terraform-plugin-framework/datasource/schema" @@ -31,17 +32,24 @@ type IPInterfaceDataSource struct { // IPInterfaceDataSourceModel describes the data source data model. type IPInterfaceDataSourceModel struct { - CxProfileName types.String `tfsdk:"cx_profile_name"` - Name types.String `tfsdk:"name"` - SVMName types.String `tfsdk:"svm_name"` - Scope types.String `tfsdk:"scope"` + CxProfileName types.String `tfsdk:"cx_profile_name"` + Name types.String `tfsdk:"name"` + SVMName types.String `tfsdk:"svm_name"` + Scope types.String `tfsdk:"scope"` + IP *IPDataSourceModel `tfsdk:"ip"` + Location *LocationDataSourceModel `tfsdk:"location"` } -// IPInterfaceDataSourceFilterModel describes the data source data model for queries. -type IPInterfaceDataSourceFilterModel struct { - Name types.String `tfsdk:"name"` - SVMName types.String `tfsdk:"svm_name"` - Scope types.String `tfsdk:"scope"` +// IPDataSourceModel describes the data source model for IP address and mask. +type IPDataSourceModel struct { + Address types.String `tfsdk:"address"` + Netmask types.Int64 `tfsdk:"netmask"` +} + +// LocationDataSourceModel describes the data source model for home node/port. +type LocationDataSourceModel struct { + HomeNode types.String `tfsdk:"home_node"` + HomePort types.String `tfsdk:"home_port"` } // Metadata returns the data source type name. @@ -57,20 +65,46 @@ func (d *IPInterfaceDataSource) Schema(ctx context.Context, req datasource.Schem Attributes: map[string]schema.Attribute{ "cx_profile_name": schema.StringAttribute{ - MarkdownDescription: "Connection profile name", Required: true, + MarkdownDescription: "Connection profile name", }, "name": schema.StringAttribute{ - MarkdownDescription: "IPInterface name", Required: true, + MarkdownDescription: "IPInterface name", }, "svm_name": schema.StringAttribute{ - MarkdownDescription: "IPInterface svm name", Optional: true, + MarkdownDescription: "IPInterface svm name", }, "scope": schema.StringAttribute{ - MarkdownDescription: "IPInterface scope", Computed: true, + MarkdownDescription: "IPInterface scope", + }, + "ip": schema.SingleNestedAttribute{ + Attributes: map[string]schema.Attribute{ + "address": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "IPInterface IP address", + }, + "netmask": schema.Int64Attribute{ + Computed: true, + MarkdownDescription: "IPInterface IP netmask", + }, + }, + Computed: true, + }, + "location": schema.SingleNestedAttribute{ + Attributes: map[string]schema.Attribute{ + "home_node": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "IPInterface home node", + }, + "home_port": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "IPInterface home port", + }, + }, + Computed: true, }, }, } @@ -123,7 +157,20 @@ func (d *IPInterfaceDataSource) Read(ctx context.Context, req datasource.ReadReq data.Name = types.StringValue(restInfo.Name) data.Scope = types.StringValue(restInfo.Scope) - data.SVMName = types.StringValue(restInfo.SVMName) + data.SVMName = types.StringValue(restInfo.SVM.Name) + intNetmask, err := strconv.Atoi(restInfo.IP.Netmask) + if err != nil { + errorHandler.MakeAndReportError("Failed to read ip interface", fmt.Sprintf("Error: failed to convert string value '%s' to int for net mask.", restInfo.IP.Netmask)) + return + } + data.IP = &IPDataSourceModel{ + Address: types.StringValue(restInfo.IP.Address), + Netmask: types.Int64Value(int64(intNetmask)), + } + data.Location = &LocationDataSourceModel{ + HomeNode: types.StringValue(restInfo.Location.HomeNode.Name), + HomePort: types.StringValue(restInfo.Location.HomePort.Name), + } // Write logs using the tflog package // Documentation: https://terraform.io/plugin/log diff --git a/internal/provider/networking_ip_interfaces_data_source.go b/internal/provider/networking_ip_interfaces_data_source.go index 1bfbf6c8..10486152 100644 --- a/internal/provider/networking_ip_interfaces_data_source.go +++ b/internal/provider/networking_ip_interfaces_data_source.go @@ -3,6 +3,7 @@ package provider import ( "context" "fmt" + "strconv" "github.com/hashicorp/terraform-plugin-framework/datasource" "github.com/hashicorp/terraform-plugin-framework/datasource/schema" @@ -36,6 +37,13 @@ type IPInterfacesDataSourceModel struct { Filter *IPInterfaceDataSourceFilterModel `tfsdk:"filter"` } +// IPInterfaceDataSourceFilterModel describes the data source data model for queries. +type IPInterfaceDataSourceFilterModel struct { + Name types.String `tfsdk:"name"` + SVMName types.String `tfsdk:"svm_name"` + Scope types.String `tfsdk:"scope"` +} + // Metadata returns the data source type name. func (d *IPInterfacesDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { resp.TypeName = req.ProviderTypeName + "_" + d.config.name @@ -55,16 +63,16 @@ func (d *IPInterfacesDataSource) Schema(ctx context.Context, req datasource.Sche "filter": schema.SingleNestedAttribute{ Attributes: map[string]schema.Attribute{ "name": schema.StringAttribute{ - MarkdownDescription: "IPInterface name", Optional: true, + MarkdownDescription: "IPInterface name", }, "svm_name": schema.StringAttribute{ - MarkdownDescription: "IPInterface svm name", Optional: true, + MarkdownDescription: "IPInterface svm name", }, "scope": schema.StringAttribute{ - MarkdownDescription: "IPInterface scope", Optional: true, + MarkdownDescription: "IPInterface scope", }, }, Optional: true, @@ -73,20 +81,46 @@ func (d *IPInterfacesDataSource) Schema(ctx context.Context, req datasource.Sche NestedObject: schema.NestedAttributeObject{ Attributes: map[string]schema.Attribute{ "cx_profile_name": schema.StringAttribute{ + Computed: true, MarkdownDescription: "Connection profile name", - Required: true, }, "name": schema.StringAttribute{ + Computed: true, MarkdownDescription: "IPInterface name", - Required: true, }, "svm_name": schema.StringAttribute{ + Computed: true, MarkdownDescription: "IPInterface svm name", - Optional: true, }, "scope": schema.StringAttribute{ - MarkdownDescription: "IPInterface scope", Computed: true, + MarkdownDescription: "IPInterface scope", + }, + "ip": schema.SingleNestedAttribute{ + Attributes: map[string]schema.Attribute{ + "address": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "IPInterface IP address", + }, + "netmask": schema.Int64Attribute{ + Computed: true, + MarkdownDescription: "IPInterface IP netmask", + }, + }, + Computed: true, + }, + "location": schema.SingleNestedAttribute{ + Attributes: map[string]schema.Attribute{ + "home_node": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "IPInterface home node", + }, + "home_port": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "IPInterface home port", + }, + }, + Computed: true, }, }, }, @@ -132,15 +166,16 @@ func (d *IPInterfacesDataSource) Read(ctx context.Context, req datasource.ReadRe return } - var filter *interfaces.IPInterfaceGetDataModelONTAP = nil + var filter *interfaces.IPInterfaceDataSourceFilterModel = nil if data.Filter != nil { - filter = &interfaces.IPInterfaceGetDataModelONTAP{ + filter = &interfaces.IPInterfaceDataSourceFilterModel{ Name: data.Filter.Name.ValueString(), Scope: data.Filter.Scope.ValueString(), SVMName: data.Filter.SVMName.ValueString(), } } - restInfo, err := interfaces.GetIPInterfaces(errorHandler, *client, filter) + + restInfo, err := interfaces.GetListIPInterfaces(errorHandler, *client, filter) if err != nil { // error reporting done inside GetIPInterfaces return @@ -152,7 +187,20 @@ func (d *IPInterfacesDataSource) Read(ctx context.Context, req datasource.ReadRe CxProfileName: types.String(data.CxProfileName), Name: types.StringValue(record.Name), Scope: types.StringValue(record.Scope), - SVMName: types.StringValue(record.SVMName), + SVMName: types.StringValue(record.SVM.Name), + } + intNetmask, err := strconv.Atoi(record.IP.Netmask) + if err != nil { + errorHandler.MakeAndReportError("Failed to read ip interface", fmt.Sprintf("Error: failed to convert string value '%s' to int for net mask.", record.IP.Netmask)) + return + } + data.IPInterfaces[index].IP = &IPDataSourceModel{ + Address: types.StringValue(record.IP.Address), + Netmask: types.Int64Value(int64(intNetmask)), + } + data.IPInterfaces[index].Location = &LocationDataSourceModel{ + HomeNode: types.StringValue(record.Location.HomeNode.Name), + HomePort: types.StringValue(record.Location.HomePort.Name), } }