Skip to content

Commit

Permalink
Merge pull request #150 from NetApp/25-new-resource-name-servicesldap
Browse files Browse the repository at this point in the history
25 new resource name servicesldap
  • Loading branch information
carchi8py authored Mar 15, 2024
2 parents ff2c883 + 79876ba commit 61e4c19
Show file tree
Hide file tree
Showing 14 changed files with 778 additions and 27 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ FEATURES:
* **New Resource:** `netapp-ontap_protocols_cifs_user_group_privilege_resource` ([#58](https://github.com/NetApp/terraform-provider-netapp-ontap/issues/58))
* **New Resource:** `netapp-ontap_svm_peers_resource` ([#51](https://github.com/NetApp/terraform-provider-netapp-ontap/issues/51))
* **New Resource:** `netapp-ontap_protocols_cifs_user_group_member_resource` ([#123](https://github.com/NetApp/terraform-provider-netapp-ontap/issues/123))
* **New Resource:** `netapp-ontap_name_services_ldap_resource` ([#25](https://github.com/NetApp/terraform-provider-netapp-ontap/issues/25))


ENHANCEMENTS:
* **netapp-ontap_protocols_nfs_export_policy_resource**: Add support for import ([#34](https://github.com/NetApp/terraform-provider-netapp-ontap/issues/34))
Expand Down
74 changes: 74 additions & 0 deletions docs/resources/name_services_ldap_resource.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "netapp-ontap_name_services_ldap_resource Resource - terraform-provider-netapp-ontap"
subcategory: "name-services"
description: |-
Name Services LDAP resource
---

# Resource name services LDAP

Create/Modify/Delete an LDAP configuration for an SVM

## Supported Platforms
* On-perm ONTAP system 9.6 or higher

## Important notes
* Each SVM can have one LDAP configuration.
* The LDAP servers and Active Directory domain are mutually exclusive fields. These fields cannot be empty. At any point in time, either the LDAP servers or Active Directory domain must be populated.
* LDAP configuration with Active Directory domain cannot be created on an admin SVM.
* IPv6 must be enabled if IPv6 family addresses are specified.

## Example Usage

```terraform
resource "netapp-ontap_name_services_ldap_resource" "name_services_ldap_example1" {
# required to know which system to interface with
cx_profile_name = "cluster4"
svm_name = "testsvm1"
servers = ["2.4.6.9", "1.6.1.8"]
skip_config_validation = true
}
resource "netapp-ontap_name_services_ldap_resource" "name_services_ldap_examp2" {
# required to know which system to interface with
cx_profile_name = "cluster4"
svm_name = "testsvm2"
servers = ["ldap1.example.company.com", "ldap2.example.company.com"]
query_timeout = 5
skip_config_validation = true
}
```
<!-- schema generated by tfplugindocs -->
## Schema

### Required

- `cx_profile_name` (String) Connection profile name
- `svm_name` (String) NameServicesLDAP svm name

### Optional

- `ad_domain` (String) Specifies the name of the Active Directory domain used to discover LDAP servers for use by this client
- `base_dn` (String) Specifies the default base DN for all searches
- `base_scope` (String) Specifies the default search scope for LDAP queries
- `bind_as_cifs_server` (Boolean) Specifies whether or not CIFS server's credentials are used to bind to the LDAP server
- `bind_dn` (String) Specifies the user that binds to the LDAP servers
- `bind_password` (String, Sensitive) Specifies the bind password for the LDAP servers
- `ldaps_enabled` (Boolean) Specifies whether or not LDAPS is enabled
- `min_bind_level` (String) The minimum bind authentication level
- `port` (Number) The port used to connect to the LDAP Servers
- `preferred_ad_servers` (Set of String) This parameter specifies a list of LDAP servers preferred over discovered servers
- `query_timeout` (Number) Specifies the timeout for LDAP queries
- `referral_enabled` (Boolean) Specifies whether or not LDAP referral is enabled
- `schema` (String) The name of the schema template used by the SVM
- `servers` (Set of String) List of LDAP servers used for this client configuration
- `session_security` (String) Specifies the level of security to be used for LDAP communications
- `skip_config_validation` (Boolean) Specifies whether or not to skip the validation of the LDAP configuration. Only support ONTAP 9.9.1 or highter.
- `use_start_tls` (Boolean) Specifies whether or not to use Start TLS over LDAP connections

### Read-Only

- `id` (String) NameServicesLDAP ID


Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
resource "netapp-ontap_name_services_ldap_resource" "name_services_ldap" {
# required to know which system to interface with
cx_profile_name = "cluster1"
svm_name = "svm5"
servers = ["1.2.3.4", "5.6.7.8"]
query_timeout = 5
skip_config_validation = true
}
99 changes: 78 additions & 21 deletions internal/interfaces/name_services_ldap.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,27 +11,46 @@ import (

// NameServicesLDAPGetDataModelONTAP describes the GET record data model using go types for mapping.
type NameServicesLDAPGetDataModelONTAP struct {
SVM SvmDataModelONTAP `mapstructure:"svm"`
Servers []string `mapstructure:"servers"`
Schema string `mapstructure:"schema"`
AdDomain string `mapstructure:"ad_domain,omitempty"`
BaseDN string `mapstructure:"base_dn,omitempty"`
BaseScope string `mapstructure:"base_scope,omitempty"`
BindDN string `mapstructure:"bind_dn,omitempty"`
BindAsCIFSServer bool `mapstructure:"bind_as_cifs_server,omitempty"`
PreferredADServers []string `mapstructure:"preferred_ad_servers,omitempty"`
Port int64 `mapstructure:"port,omitempty"`
QueryTimeout int64 `mapstructure:"query_timeout,omitempty"`
MinBindLevel string `mapstructure:"min_bind_level,omitempty"`
UseStartTLS bool `mapstructure:"use_start_tls,omitempty"`
ReferralEnabled bool `mapstructure:"referral_enabled,omitempty"`
SessionSecurity string `mapstructure:"session_security,omitempty"`
LDAPSEnabled bool `mapstructure:"ldaps_enabled,omitempty"`
SVM SvmDataModelONTAP `mapstructure:"svm"`
Servers []string `mapstructure:"servers"`
Schema string `mapstructure:"schema"`
AdDomain string `mapstructure:"ad_domain,omitempty"`
BaseDN string `mapstructure:"base_dn"`
BaseScope string `mapstructure:"base_scope"`
BindDN string `mapstructure:"bind_dn,omitempty"`
BindAsCIFSServer bool `mapstructure:"bind_as_cifs_server"`
PreferredADServers []string `mapstructure:"preferred_ad_servers,omitempty"`
Port int64 `mapstructure:"port"`
QueryTimeout int64 `mapstructure:"query_timeout"`
MinBindLevel string `mapstructure:"min_bind_level"`
UseStartTLS bool `mapstructure:"use_start_tls"`
ReferralEnabled bool `mapstructure:"referral_enabled"`
SessionSecurity string `mapstructure:"session_security"`
LDAPSEnabled bool `mapstructure:"ldaps_enabled"`
BindPassword string `mapstructure:"bind_password,omitempty"`
SkipConfigValidation bool `mapstructure:"skip_config_validation,omitempty"`
}

// NameServicesLDAPResourceBodyDataModelONTAP describes the body data model using go types for mapping.
type NameServicesLDAPResourceBodyDataModelONTAP struct {
SVM svm `mapstructure:"svm"`
SVM svm `mapstructure:"svm"`
Servers []string `mapstructure:"servers,omitempty"`
Schema string `mapstructure:"schema,omitempty"`
AdDomain string `mapstructure:"ad_domain,omitempty"`
BaseDN string `mapstructure:"base_dn,omitempty"`
BaseScope string `mapstructure:"base_scope,omitempty"`
BindDN string `mapstructure:"bind_dn,omitempty"`
BindAsCIFSServer bool `mapstructure:"bind_as_cifs_server,omitempty"`
BindPassword string `mapstructure:"bind_password,omitempty"`
PreferredADServers []string `mapstructure:"preferred_ad_servers,omitempty"`
Port int64 `mapstructure:"port,omitempty"`
QueryTimeout int64 `mapstructure:"query_timeout,omitempty"`
MinBindLevel string `mapstructure:"min_bind_level,omitempty"`
UseStartTLS bool `mapstructure:"use_start_tls,omitempty"`
ReferralEnabled bool `mapstructure:"referral_enabled,omitempty"`
SessionSecurity string `mapstructure:"session_security,omitempty"`
LDAPSEnabled bool `mapstructure:"ldaps_enabled,omitempty"`
SkipConfigValidation bool `mapstructure:"skip_config_validation,omitempty"`
}

// NameServicesLDAPDataSourceFilterModel describes the data source data model for queries.
Expand Down Expand Up @@ -105,9 +124,31 @@ func GetNameServicesLDAPs(errorHandler *utils.ErrorHandler, r restclient.RestCli
return dataONTAP, nil
}

// GetNameServicesLDAPBySVMID to get name_services_ldap info
func GetNameServicesLDAPBySVMID(errorHandler *utils.ErrorHandler, r restclient.RestClient, svmID string) (*NameServicesLDAPGetDataModelONTAP, error) {
api := "name-services/ldap" + "/" + svmID

statusCode, response, err := r.GetNilOrOneRecord(api, nil, nil)

if err == nil && response == nil {
err = fmt.Errorf("no response for GET %s", api)
}
if err != nil {
return nil, errorHandler.MakeAndReportError("error reading name_services_ldap info", fmt.Sprintf("error on GET %s: %s, statusCode %d", api, err, statusCode))
}

var dataONTAP NameServicesLDAPGetDataModelONTAP
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 name_services_ldap data source: %#v", dataONTAP))
return &dataONTAP, nil
}

// CreateNameServicesLDAP to create name_services_ldap
func CreateNameServicesLDAP(errorHandler *utils.ErrorHandler, r restclient.RestClient, body NameServicesLDAPResourceBodyDataModelONTAP) (*NameServicesLDAPGetDataModelONTAP, error) {
api := "api_url"
api := "name-services/ldap"
var bodyMap map[string]interface{}
if err := mapstructure.Decode(body, &bodyMap); err != nil {
return nil, errorHandler.MakeAndReportError("error encoding name_services_ldap body", fmt.Sprintf("error on encoding %s body: %s, body: %#v", api, err, body))
Expand All @@ -128,11 +169,27 @@ func CreateNameServicesLDAP(errorHandler *utils.ErrorHandler, r restclient.RestC
}

// DeleteNameServicesLDAP to delete name_services_ldap
func DeleteNameServicesLDAP(errorHandler *utils.ErrorHandler, r restclient.RestClient, uuid string) error {
api := "api_url"
statusCode, _, err := r.CallDeleteMethod(api+"/"+uuid, nil, nil)
func DeleteNameServicesLDAP(errorHandler *utils.ErrorHandler, r restclient.RestClient, svmid string) error {
api := "name-services/ldap"
statusCode, _, err := r.CallDeleteMethod(api+"/"+svmid, nil, nil)
if err != nil {
return errorHandler.MakeAndReportError("error deleting name_services_ldap", fmt.Sprintf("error on DELETE %s: %s, statusCode %d", api, err, statusCode))
}
return nil
}

// UpdateNameServicesLDAP to update name_services_ldap
func UpdateNameServicesLDAP(errorHandler *utils.ErrorHandler, r restclient.RestClient, body NameServicesLDAPResourceBodyDataModelONTAP, svmid string) error {
api := "name-services/ldap"
var bodyMap map[string]interface{}
if err := mapstructure.Decode(body, &bodyMap); err != nil {
return errorHandler.MakeAndReportError("error encoding name_services_ldap body", fmt.Sprintf("error on encoding %s body: %s, body: %#v", api, err, body))
}
query := r.NewQuery()
query.Add("return_records", "true")
statusCode, _, err := r.CallUpdateMethod(api+"/"+svmid, query, bodyMap)
if err != nil {
return errorHandler.MakeAndReportError("error updating name_services_ldap", fmt.Sprintf("error on PUT %s: %s, statusCode %d", api, err, statusCode))
}
return nil
}
5 changes: 3 additions & 2 deletions internal/provider/cluster_licensing_license_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ package provider
import (
"context"
"fmt"
"github.com/hashicorp/terraform-plugin-framework/path"
"strings"

"github.com/hashicorp/terraform-plugin-framework/path"

"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
"github.com/hashicorp/terraform-plugin-framework/types"
Expand Down Expand Up @@ -261,7 +262,7 @@ func (r *ClusterLicensingLicenseResource) ImportState(ctx context.Context, req r
if len(idParts) != 2 || idParts[0] == "" || idParts[1] == "" {
resp.Diagnostics.AddError(
"Unexpected Import Identifier",
fmt.Sprintf("Expected import identifier with format: attr_one,attr_two. Got: %q", req.ID),
fmt.Sprintf("Expected import identifier with format: name,cx_profile_name. Got: %q", req.ID),
)
return
}
Expand Down
2 changes: 1 addition & 1 deletion internal/provider/name_services_dns_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ func (r *NameServicesDNSResource) ImportState(ctx context.Context, req resource.
if len(idParts) != 2 || idParts[0] == "" || idParts[1] == "" {
resp.Diagnostics.AddError(
"Unexpected Import Identifier",
fmt.Sprintf("Expected import identifier with format: attr_one,attr_two. Got: %q", req.ID),
fmt.Sprintf("Expected import identifier with format: svm_name,cx_profile_name. Got: %q", req.ID),
)
return
}
Expand Down
Loading

0 comments on commit 61e4c19

Please sign in to comment.