Skip to content

Commit

Permalink
Sync bitbucket and GitHub
Browse files Browse the repository at this point in the history
  • Loading branch information
carchi8py committed Oct 20, 2023
1 parent e1d2649 commit b9d1941
Show file tree
Hide file tree
Showing 8 changed files with 390 additions and 50 deletions.
35 changes: 31 additions & 4 deletions docs/data-sources/networking_ip_interface_data_source.md
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
```


<!-- schema generated by tfplugindocs -->
Expand All @@ -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

<a id="nestedatt--ip"></a>
### Nested Schema for `ip`

Read-Only:

- `address` (String) IPInterface IP address
- `netmask` (Number) IPInterface IP netmask


<a id="nestedatt--location"></a>
### Nested Schema for `location`

Read-Only:

- `home_node` (String) IPInterface home node
- `home_port` (String) IPInterface home port


41 changes: 33 additions & 8 deletions docs/data-sources/networking_ip_interfaces_data_source.md
Original file line number Diff line number Diff line change
@@ -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"
}
}
```


<!-- schema generated by tfplugindocs -->
Expand Down Expand Up @@ -40,17 +52,30 @@ Optional:
<a id="nestedatt--ip_interfaces"></a>
### 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:
<a id="nestedatt--ip_interfaces--ip"></a>
### Nested Schema for `ip_interfaces.ip`

- `svm_name` (String) IPInterface svm name
Read-Only:

- `address` (String) IPInterface IP address
- `netmask` (Number) IPInterface IP netmask


<a id="nestedatt--ip_interfaces--location"></a>
### Nested Schema for `ip_interfaces.location`

Read-Only:

- `scope` (String) IPInterface scope
- `home_node` (String) IPInterface home node
- `home_port` (String) IPInterface home port


Original file line number Diff line number Diff line change
@@ -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"
}
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
}
}
28 changes: 20 additions & 8 deletions internal/interfaces/networking_ip_interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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"`
Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -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)
Expand Down
179 changes: 179 additions & 0 deletions internal/interfaces/networking_ip_interface_test.go
Original file line number Diff line number Diff line change
@@ -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)
}
})
}
}
Loading

0 comments on commit b9d1941

Please sign in to comment.