Skip to content

Commit

Permalink
Merge pull request #262 from NetApp/184-add-lambda-connector
Browse files Browse the repository at this point in the history
Add AWS Lambda.
  • Loading branch information
suhasbshekar authored Sep 10, 2024
2 parents c529e74 + 20d0db6 commit 00c5ab1
Show file tree
Hide file tree
Showing 9 changed files with 470 additions and 24 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# 1.2.0 ()

FEATURES:
* **provider**: add `aws_lambda` option. ([#262](https://github.com/NetApp/terraform-provider-netapp-ontap/issues/262))
* **New Data Source:** `netapp-ontap_volumes_files` ([#8](https://github.com/NetApp/terraform-provider-netapp-ontap/issues/8))
* **New Data Source:** `netapp-ontap_qos_policy` ([#77](https://github.com/NetApp/terraform-provider-netapp-ontap/issues/77))
* **New Data Source:** `netapp-ontap_qos_policies` ([#77](https://github.com/NetApp/terraform-provider-netapp-ontap/issues/77))
Expand Down
32 changes: 30 additions & 2 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ Use the navigation to the left to read about the available resources. These are

To learn the basics of Terraform using this provider, follow the hands-on [get started tutorials](https://developer.hashicorp.com/terraform/tutorials/aws-get-started/infrastructure-as-code)

## Supported Platforms
* On-perm ONTAP system 9.6 or higher
* Amazon FSx for NetApp ONTAP

## Example Usage

```terraform
Expand Down Expand Up @@ -45,6 +49,17 @@ provider "netapp-ontap" {
password = "Password"
validate_certs = false
},
{
name = "fsx"
hostname = "aws.management.endpoint.com"
username = "admin"
password = "Password"
aws = {
function_name = "lambda_func"
region = "aws_region"
shared_config_profile = "fsx_profile"
}
}
]
}
```
Expand All @@ -66,11 +81,24 @@ provider "netapp-ontap" {

Required:

- `hostname` (String) ONTAP management interface IP address or name
- `hostname` (String) ONTAP management interface IP address or name. For AWS Lambda, the management endpoints for the FSxN system.
- `name` (String) Profile name
- `password` (String, Sensitive) ONTAP management password for username
- `username` (String) ONTAP management user name (cluster or svm)

Optional:

- `validate_certs` (Boolean) Whether to enforce SSL certificate validation, defaults to true
- `aws_lambda` (Attributes) AWS configuration for Lambda (see [below for nested schema](#nestedatt--connection_profiles--aws_lambda))
- `validate_certs` (Boolean) Whether to enforce SSL certificate validation, defaults to true. Not applicable for AWS Lambda

<a id="nestedatt--connection_profiles--aws_lambda"></a>
### Nested Schema for `connection_profiles.aws_lambda`

Required:

- `shared_config_profile` (String) AWS shared config profile. Region set in the profile will be ignored it it's different from the region set in Terraform. aws_access_key_id and aws_secret_access_key are required to be set in credentials

Optional:

- `function_name` (String) AWS Lambda function name
- `region` (String) AWS region.
16 changes: 16 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ module github.com/netapp/terraform-provider-netapp-ontap
go 1.21

require (
github.com/aws/aws-sdk-go-v2 v1.30.3
github.com/aws/aws-sdk-go-v2/config v1.27.27
github.com/aws/aws-sdk-go-v2/service/lambda v1.56.3
github.com/hashicorp/terraform-plugin-docs v0.19.4
github.com/hashicorp/terraform-plugin-framework v1.8.0
github.com/hashicorp/terraform-plugin-go v0.23.0
Expand Down Expand Up @@ -67,10 +70,23 @@ require (
github.com/Kunde21/markdownfmt/v3 v3.1.0 // indirect
github.com/ProtonMail/go-crypto v1.1.0-alpha.2 // indirect
github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.3 // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.17.27 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.11 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.15 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.15 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.3 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.17 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.22.4 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.4 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.30.3 // indirect
github.com/aws/smithy-go v1.20.3 // indirect
github.com/bmatcuk/doublestar/v4 v4.6.1 // indirect
github.com/cloudflare/circl v1.3.7 // indirect
github.com/hashicorp/cli v1.1.6 // indirect
github.com/hashicorp/yamux v0.1.1 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-runewidth v0.0.9 // indirect
github.com/oklog/run v1.1.0 // indirect
Expand Down
35 changes: 35 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,36 @@ github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew
github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4=
github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI=
github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/aws/aws-sdk-go-v2 v1.30.3 h1:jUeBtG0Ih+ZIFH0F4UkmL9w3cSpaMv9tYYDbzILP8dY=
github.com/aws/aws-sdk-go-v2 v1.30.3/go.mod h1:nIQjQVp5sfpQcTc9mPSr1B0PaWK5ByX9MOoDadSN4lc=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.3 h1:tW1/Rkad38LA15X4UQtjXZXNKsCgkshC3EbmcUmghTg=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.3/go.mod h1:UbnqO+zjqk3uIt9yCACHJ9IVNhyhOCnYk8yA19SAWrM=
github.com/aws/aws-sdk-go-v2/config v1.27.27 h1:HdqgGt1OAP0HkEDDShEl0oSYa9ZZBSOmKpdpsDMdO90=
github.com/aws/aws-sdk-go-v2/config v1.27.27/go.mod h1:MVYamCg76dFNINkZFu4n4RjDixhVr51HLj4ErWzrVwg=
github.com/aws/aws-sdk-go-v2/credentials v1.17.27 h1:2raNba6gr2IfA0eqqiP2XiQ0UVOpGPgDSi0I9iAP+UI=
github.com/aws/aws-sdk-go-v2/credentials v1.17.27/go.mod h1:gniiwbGahQByxan6YjQUMcW4Aov6bLC3m+evgcoN4r4=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.11 h1:KreluoV8FZDEtI6Co2xuNk/UqI9iwMrOx/87PBNIKqw=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.11/go.mod h1:SeSUYBLsMYFoRvHE0Tjvn7kbxaUhl75CJi1sbfhMxkU=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.15 h1:SoNJ4RlFEQEbtDcCEt+QG56MY4fm4W8rYirAmq+/DdU=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.15/go.mod h1:U9ke74k1n2bf+RIgoX1SXFed1HLs51OgUSs+Ph0KJP8=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.15 h1:C6WHdGnTDIYETAm5iErQUiVNsclNx9qbJVPIt03B6bI=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.15/go.mod h1:ZQLZqhcu+JhSrA9/NXRm8SkDvsycE+JkV3WGY41e+IM=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 h1:hT8rVHwugYE2lEfdFE0QWVo81lF7jMrYJVDWI+f+VxU=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0/go.mod h1:8tu/lYfQfFe6IGnaOdrpVgEL2IrrDOf6/m9RQum4NkY=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.3 h1:dT3MqvGhSoaIhRseqw2I0yH81l7wiR2vjs57O51EAm8=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.3/go.mod h1:GlAeCkHwugxdHaueRr4nhPuY+WW+gR8UjlcqzPr1SPI=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.17 h1:HGErhhrxZlQ044RiM+WdoZxp0p+EGM62y3L6pwA4olE=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.17/go.mod h1:RkZEx4l0EHYDJpWppMJ3nD9wZJAa8/0lq9aVC+r2UII=
github.com/aws/aws-sdk-go-v2/service/lambda v1.56.3 h1:r/y4nQOln25cbjrD8Wmzhhvnvr2ObPjgcPvPdoU9yHs=
github.com/aws/aws-sdk-go-v2/service/lambda v1.56.3/go.mod h1:/4Vaddp+wJc1AA8ViAqwWKAcYykPV+ZplhmLQuq3RbQ=
github.com/aws/aws-sdk-go-v2/service/sso v1.22.4 h1:BXx0ZIxvrJdSgSvKTZ+yRBeSqqgPM89VPlulEcl37tM=
github.com/aws/aws-sdk-go-v2/service/sso v1.22.4/go.mod h1:ooyCOXjvJEsUw7x+ZDHeISPMhtwI3ZCB7ggFMcFfWLU=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.4 h1:yiwVzJW2ZxZTurVbYWA7QOrAaCYQR72t0wrSBfoesUE=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.4/go.mod h1:0oxfLkpz3rQ/CHlx5hB7H69YUpFiI1tql6Q6Ne+1bCw=
github.com/aws/aws-sdk-go-v2/service/sts v1.30.3 h1:ZsDKRLXGWHk8WdtyYMoGNO7bTudrvuKpDKgMVRlepGE=
github.com/aws/aws-sdk-go-v2/service/sts v1.30.3/go.mod h1:zwySh8fpFyXp9yOr/KVzxOl8SRqgf/IDw5aUt9UKFcQ=
github.com/aws/smithy-go v1.20.3 h1:ryHwveWzPV5BIof6fyDvor6V3iUL7nTfiTKXHiW05nE=
github.com/aws/smithy-go v1.20.3/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E=
github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/bmatcuk/doublestar/v4 v4.6.1 h1:FH9SifrbvJhnlQpztAx++wlkk70QBf0iBWDwNy7PA4I=
Expand Down Expand Up @@ -124,6 +154,10 @@ github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOl
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
github.com/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c=
github.com/jhump/protoreflect v1.15.1/go.mod h1:jD/2GMKKE6OqX8qTjhADU1e6DShO+gavG9e0Q693nKo=
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
Expand Down Expand Up @@ -275,6 +309,7 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
Expand Down
12 changes: 10 additions & 2 deletions internal/provider/connection/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ package connection

import (
"fmt"
"github.com/hashicorp/terraform-plugin-log/tflog"
"strings"

"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"
Expand All @@ -20,6 +21,14 @@ type Profile struct {
Password string
ValidateCerts bool
MaxConcurrentRequests int
UseAWSLambda bool
AWS AWSConfig `mapstructure:"aws,omitempty"`
}

type AWSConfig struct {
Region string
SharedConfigProfile string
FunctionName string
}

// Config is created by the provide configure method
Expand Down Expand Up @@ -63,7 +72,6 @@ func (c *Config) NewClient(errorHandler *utils.ErrorHandler, cxProfileName strin
fmt.Sprintf("decode error on ConnectionProfile %#v to restclient.ConnectionProfile", connectionProfile))
}
// the tag resource_name/version will be used for telemetry

tflog.Debug(errorHandler.Ctx, fmt.Sprintf("Version string is: %#v", strings.Join([]string{"TerrafromONTAP", resName, c.Version}, "/")))
client, err := restclient.NewClient(errorHandler.Ctx, profile, strings.Join([]string{"TerraformONTAP", resName, c.Version}, "/"), c.JobCompletionTimeOut)
if err != nil {
Expand Down
100 changes: 81 additions & 19 deletions internal/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"github.com/hashicorp/terraform-plugin-framework/provider/schema"
"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-framework/types/basetypes"
"github.com/hashicorp/terraform-plugin-log/tflog"
)

Expand All @@ -38,18 +39,25 @@ type ONTAPProvider struct {
// ConnectionProfileModel associate a connection profile with a name
// TODO: augment address with hostname, ...
type ConnectionProfileModel struct {
Name types.String `tfsdk:"name"`
Hostname types.String `tfsdk:"hostname"`
Username types.String `tfsdk:"username"`
Password types.String `tfsdk:"password"`
ValidateCerts types.Bool `tfsdk:"validate_certs"`
Name types.String `tfsdk:"name"`
Hostname types.String `tfsdk:"hostname"`
Username types.String `tfsdk:"username"`
Password types.String `tfsdk:"password"`
ValidateCerts types.Bool `tfsdk:"validate_certs"`
ONTAPProviderAWSModel types.Object `tfsdk:"aws_lambda"`
}

// ONTAPProviderModel describes the provider data model.
type ONTAPProviderModel struct {
Endpoint types.String `tfsdk:"endpoint"`
JobCompletionTimeOut types.Int64 `tfsdk:"job_completion_timeout"`
ConnectionProfiles []ConnectionProfileModel `tfsdk:"connection_profiles"`
Endpoint types.String `tfsdk:"endpoint"`
JobCompletionTimeOut types.Int64 `tfsdk:"job_completion_timeout"`
ConnectionProfiles types.List `tfsdk:"connection_profiles"`
}

type ONTAPProviderAWSLambdaModel struct {
Region types.String `tfsdk:"region"`
SharedConfigProfile types.String `tfsdk:"shared_config_profile"`
FunctionName types.String `tfsdk:"function_name"`
}

// Metadata defines the provider type name for inclusion in each data source and resource type name
Expand Down Expand Up @@ -81,7 +89,7 @@ func (p *ONTAPProvider) Schema(ctx context.Context, req provider.SchemaRequest,
Required: true,
},
"hostname": schema.StringAttribute{
MarkdownDescription: "ONTAP management interface IP address or name",
MarkdownDescription: "ONTAP management interface IP address or name. For AWS Lambda, the management endpoints for the FSxN system.",
Required: true,
},
"username": schema.StringAttribute{
Expand All @@ -94,8 +102,26 @@ func (p *ONTAPProvider) Schema(ctx context.Context, req provider.SchemaRequest,
Sensitive: true,
},
"validate_certs": schema.BoolAttribute{
MarkdownDescription: "Whether to enforce SSL certificate validation, defaults to true",
MarkdownDescription: "Whether to enforce SSL certificate validation, defaults to true. Not applicable for AWS Lambda",
Optional: true,
},
"aws_lambda": schema.SingleNestedAttribute{
MarkdownDescription: "AWS configuration for Lambda",
Optional: true,
Attributes: map[string]schema.Attribute{
"region": schema.StringAttribute{
MarkdownDescription: "AWS region.",
Optional: true,
},
"function_name": schema.StringAttribute{
MarkdownDescription: "AWS Lambda function name",
Optional: true,
},
"shared_config_profile": schema.StringAttribute{
MarkdownDescription: "AWS shared config profile. Region set in the profile will be ignored it it's different from the region set in Terraform. aws_access_key_id and aws_secret_access_key are required to be set in credentials",
Required: true,
},
},
},
},
},
Expand All @@ -115,25 +141,61 @@ func (p *ONTAPProvider) Configure(ctx context.Context, req provider.ConfigureReq
}
// Required attributes
// For optional values we can use data.Endpoint.IsNull(), ...
if len(data.ConnectionProfiles) == 0 {

if data.ConnectionProfiles.IsUnknown() {
resp.Diagnostics.AddError("no connection profiles", "At least one connection profile must be defined.")
return
}
if len(data.ConnectionProfiles.Elements()) == 0 {
resp.Diagnostics.AddError("no connection profile", "At least one connection profile must be defined.")
return
}
connectionProfiles := make(map[string]connection.Profile, len(data.ConnectionProfiles))
for _, profile := range data.ConnectionProfiles {
connectionProfilesElements := make([]types.Object, 0, len(data.ConnectionProfiles.Elements()))
diags := data.ConnectionProfiles.ElementsAs(ctx, &connectionProfilesElements, false)
if diags.HasError() {
resp.Diagnostics.Append(diags...)
return
}

connectionProfiles := make(map[string]connection.Profile, len(data.ConnectionProfiles.Elements()))

for _, profile := range connectionProfilesElements {
var connectionProfile ConnectionProfileModel
diags := profile.As(ctx, &connectionProfile, basetypes.ObjectAsOptions{})
if diags.HasError() {
resp.Diagnostics.Append(diags...)
return
}
var validateCerts bool
if profile.ValidateCerts.IsNull() {
if connectionProfile.ValidateCerts.IsNull() {
validateCerts = true
} else {
validateCerts = profile.ValidateCerts.ValueBool()
validateCerts = connectionProfile.ValidateCerts.ValueBool()
}
connectionProfiles[profile.Name.ValueString()] = connection.Profile{
Hostname: profile.Hostname.ValueString(),
Username: profile.Username.ValueString(),
Password: profile.Password.ValueString(),
connectionProfiles[connectionProfile.Name.ValueString()] = connection.Profile{
Hostname: connectionProfile.Hostname.ValueString(),
Username: connectionProfile.Username.ValueString(),
Password: connectionProfile.Password.ValueString(),
ValidateCerts: validateCerts,
MaxConcurrentRequests: 0,
}
if !connectionProfile.ONTAPProviderAWSModel.IsNull() {
var lambdaConfig ONTAPProviderAWSLambdaModel
diags := connectionProfile.ONTAPProviderAWSModel.As(ctx, &lambdaConfig, basetypes.ObjectAsOptions{})
if diags.HasError() {
resp.Diagnostics.Append(diags...)
return
}
currentProfile := connectionProfiles[connectionProfile.Name.ValueString()]
currentProfile.UseAWSLambda = true
currentProfile.AWS = connection.AWSConfig{
Region: lambdaConfig.Region.ValueString(),
SharedConfigProfile: lambdaConfig.SharedConfigProfile.ValueString(),
FunctionName: lambdaConfig.FunctionName.ValueString(),
}
connectionProfiles[connectionProfile.Name.ValueString()] = currentProfile

}
}
jobCompletionTimeOut := data.JobCompletionTimeOut.ValueInt64()
if data.JobCompletionTimeOut.IsNull() {
Expand Down
Loading

0 comments on commit 00c5ab1

Please sign in to comment.