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 Jul 26, 2023
1 parent 31d8825 commit 6204ff6
Show file tree
Hide file tree
Showing 9 changed files with 575 additions and 3 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<picture>
<source media="(prefers-color-scheme: dark)" srcset=".github/netapp-dark.png">
<source media="(prefers-color-scheme: light)" srcset=".github/netapp-light.png">
<img src=".github/netapp-light.png" alt="NetApp logo" title="NetApp" align="right" height="200">
<img src=".github/netapp-light.png" alt="NetApp logo" title="NetApp" align="right" height="400">
</picture>
</a>

Expand All @@ -14,4 +14,4 @@
The ONTAP Provider allows Terraform to Manage NetApp ONTAP resources.

- Contribuing Guide
- [Roadmap](https://github.com/orgs/NetApp/projects/7)
- [Roadmap](https://github.com/orgs/NetApp/projects/7)
44 changes: 44 additions & 0 deletions examples/resources/netapp-ontap_snapmiror_policy/provider.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
terraform {
required_providers {
netapp-ontap = {
source = "NetApp/netapp-ontap"
version = "0.0.1"
}
}
}


provider "netapp-ontap" {
# A connection profile defines how to interface with an ONTAP cluster or vserver.
# At least one is required.
connection_profiles = [
{
name = "cluster1"
hostname = "********219"
username = var.username
password = var.password
validate_certs = var.validate_certs
},
{
name = "cluster2"
hostname = "********222"
username = var.username
password = var.password
validate_certs = var.validate_certs
},
{
name = "cluster3"
hostname = "10.193.176.159"
username = var.username
password = var.password
validate_certs = var.validate_certs
},
{
name = "cluster4"
hostname = "10.193.180.108"
username = var.username
password = var.password
validate_certs = var.validate_certs
}
]
}
9 changes: 9 additions & 0 deletions examples/resources/netapp-ontap_snapmiror_policy/resource.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
resource "netapp-ontap_snapmirror_policy_resource" "snapmirror_policy" {
# required to know which system to interface with
cx_profile_name = "cluster4"
name = "carchitestme"
svm_name = "ansibleSVM"
identity_preservation = "full"
comment = "comment1"
type = "async"
}
11 changes: 11 additions & 0 deletions examples/resources/netapp-ontap_snapmiror_policy/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Terraform will prompt for values, unless a tfvars file is present.
variable "username" {
type = string
}
variable "password" {
type = string
sensitive = true
}
variable "validate_certs" {
type = bool
}
113 changes: 113 additions & 0 deletions internal/interfaces/snapmirror_policy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package interfaces

import (
"fmt"

"github.com/hashicorp/terraform-plugin-log/tflog"
"github.com/mitchellh/mapstructure"
"github.com/netapp/terraform-provider-netapp-ontap/internal/restclient"
"github.com/netapp/terraform-provider-netapp-ontap/internal/utils"
)

// SnapmirrorPolicyGetDataModelONTAP defines the resource get data model
type SnapmirrorPolicyGetDataModelONTAP struct {
Name string `mapstructure:"name"`
SVMName Vserver `mapstructure:"svm"`
Type string `mapstructure:"type"`
Comment string `mapstructure:"comment"`
TransferSchedule string `mapstructure:"transfer_schedule"`
NetworkCompressionEnabled bool `mapstructure:"network_compression_enabled"`
Retention []RetentionGetDataModel `mapstructure:"retention"`
IdentityPreservation string `mapstructure:"identity_preservation"`
CopyAllSourceSnapshots bool `mapstructure:"copy_all_source_snapshots"`
UUID string `mapstructure:"uuid"`
}

// RetentionGetDataModel defines the resource get retention model
type RetentionGetDataModel struct {
CreationSchedule CreationScheduleModel `json:"creation_schedule"`
Count int64 `json:"count"`
Label string `json:"label"`
Prefix string `json:"prefix"`
}

// CreationScheduleModel defines the resource creationschedule model
type CreationScheduleModel struct {
Name string `json:"name"`
}

// SnapmirrorPolicyResourceBodyDataModelONTAP defines the resource data model
type SnapmirrorPolicyResourceBodyDataModelONTAP struct {
Name string `mapstructure:"name"`
SVMName Vserver `mapstructure:"svm"`
Type string `mapstructure:"type,omitempty"`
Comment string `mapstructure:"comment,omitempty"`
TransferSchedule string `mapstructure:"transfer_schedule,omitempty"`
NetworkCompressionEnabled bool `mapstructure:"network_compression_enabled,omitempty"`
Retention []RetentionGetDataModel `mapstructure:"retention,omitempty"`
IdentityPreservation string `mapstructure:"identity_preservation,omitempty"`
CopyAllSourceSnapshots bool `mapstructure:"copy_all_source_snapshots,omitempty"`
}

// GetSnapmirrorPolicy to get snapmirror policy info
func GetSnapmirrorPolicy(errorHandler *utils.ErrorHandler, r restclient.RestClient, name string, svmName string) (*SnapmirrorPolicyGetDataModelONTAP, error) {
api := "snapmirror/policies"
query := r.NewQuery()
query.Set("name", name)
if svmName == "" {
query.Set("scope", "cluster")
} else {
query.Set("svm.name", svmName)
query.Set("scope", "svm")
}
// TODO: copy_all_source_snapshots is 9.10 and up
query.Fields(([]string{"name", "svm.name", "type", "comment", "transfer_schedule", "network_compression_enabled", "retention", "identity_preservation", "copy_all_source_snapshots", "uuid"}))
statusCode, response, err := r.GetNilOrOneRecord(api, query, nil)
if err == nil && response == nil {
err = fmt.Errorf("no response for GET %s", api)
}
if err != nil {
return nil, errorHandler.MakeAndReportError("error reading snapmirror/policies info", fmt.Sprintf("error on GET %s: %s, statusCode %d", api, err, statusCode))
}

var dataONTAP SnapmirrorPolicyGetDataModelONTAP
if err := mapstructure.Decode(response, &dataONTAP); err != nil {
return nil, errorHandler.MakeAndReportError(fmt.Sprintf("failed to decode response from GET %s", api),
fmt.Sprintf("error: %s, statusCode %d, response %#v", err, statusCode, response))
}
tflog.Debug(errorHandler.Ctx, fmt.Sprintf("Read snapmirror/policies data source: %#v", dataONTAP))
// If retention is [] we need to convert it to nil for Terrafrom to work correct
return &dataONTAP, nil
}

// CreateSnapmirrorPolicy to create snapmirror policy
func CreateSnapmirrorPolicy(errorHandler *utils.ErrorHandler, r restclient.RestClient, body SnapmirrorPolicyResourceBodyDataModelONTAP) (*SnapmirrorPolicyGetDataModelONTAP, error) {
api := "snapmirror/policies"
var bodyMap map[string]interface{}
if err := mapstructure.Decode(body, &bodyMap); err != nil {
return nil, errorHandler.MakeAndReportError("error encoding snapmirror/policies body", fmt.Sprintf("error on encoding %s body: %s, body: %#v", api, err, body))
}
query := r.NewQuery()
query.Add("return_records", "true")
statusCode, response, err := r.CallCreateMethod(api, query, bodyMap)
if err != nil {
return nil, errorHandler.MakeAndReportError("error creating snapmirror/policies", fmt.Sprintf("error on POST %s: %s, statusCode %d", api, err, statusCode))
}

var dataONTAP SnapmirrorPolicyGetDataModelONTAP
if err := mapstructure.Decode(response.Records[0], &dataONTAP); err != nil {
return nil, errorHandler.MakeAndReportError("error decoding snapmirror/policies info", fmt.Sprintf("error on decode snapmirror/policies info: %s, statusCode %d, response %#v", err, statusCode, response))
}
tflog.Debug(errorHandler.Ctx, fmt.Sprintf("Create snapmirror/policies source - udata: %#v", dataONTAP))
return &dataONTAP, nil
}

// DeleteSnapmirrorPolicy to delete ip_interface
func DeleteSnapmirrorPolicy(errorHandler *utils.ErrorHandler, r restclient.RestClient, uuid string) error {
api := "snapmirror/policies/"
statusCode, _, err := r.CallDeleteMethod(api+uuid, nil, nil)
if err != nil {
return errorHandler.MakeAndReportError("error deleting snapmirror/policies", fmt.Sprintf("error on DELETE %s: %s, statusCode %d", api, err, statusCode))
}
return nil
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package acceptancetests

import (
"fmt"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"os"
"regexp"
"testing"
)

func TestAccSnapmirrorPolicyResource(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
Steps: []resource.TestStep{
{
Config: testAccSnapmirrorPolicyResourceConfig("non-existant"),
ExpectError: regexp.MustCompile("2621462"),
},
{
Config: testAccSnapmirrorPolicyResourceConfig("ansibleSVM"),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("netapp-ontap_snapmirror_policy_resource.example", "name", "carchitestme4"),
),
},
},
})
}

func testAccSnapmirrorPolicyResourceConfig(svm string) string {
host := os.Getenv("TF_ACC_NETAPP_HOST")
admin := os.Getenv("TF_ACC_NETAPP_USER")
password := os.Getenv("TF_ACC_NETAPP_PASS")
if host == "" || admin == "" || password == "" {
fmt.Println("TF_ACC_NETAPP_HOST, TF_ACC_NETAPP_USER, and TF_ACC_NETAPP_PASS must be set for acceptance tests")
os.Exit(1)
}
return fmt.Sprintf(`
provider "netapp-ontap" {
connection_profiles = [
{
name = "cluster4"
hostname = "%s"
username = "%s"
password = "%s"
validate_certs = false
},
]
}
resource "netapp-ontap_snapmirror_policy_resource" "example" {
cx_profile_name = "cluster4"
name = "carchitestme4"
svm_name = "%s"
identity_preservation = "full"
comment = "comment1"
type = "async"
}`, host, admin, password, svm)
}
1 change: 1 addition & 0 deletions internal/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ func (p *ONTAPProvider) Resources(ctx context.Context) []func() resource.Resourc
NewIPRouteResource,
NewNameServicesDNSResource,
NewProtocolsNfsServiceResource,
NewSnapmirrorPolicyResource,
NewSnapshotPolicyResource,
NewStorageVolumeResource,
NewStorageVolumeSnapshotResource,
Expand Down
Loading

0 comments on commit 6204ff6

Please sign in to comment.