From dd48e5e16f7860575b339e179012f6a563982324 Mon Sep 17 00:00:00 2001 From: swenjun Date: Tue, 26 Mar 2024 14:40:31 -0700 Subject: [PATCH 1/7] Add new data source for cifs share and shares --- .../protocols_cifs_share_data_source.md | 89 +++++ .../protocols_cifs_shares_data_source.md | 113 ++++++ .../data-source.tf | 6 + .../provider.tf | 1 + .../terraform.tfvars | 1 + .../variables.tf | 1 + .../data-source.tf | 7 + .../provider.tf | 1 + .../terraform.tfvars | 1 + .../variables.tf | 1 + internal/interfaces/protocols_cifs_share.go | 156 ++++++++ .../protocols_cifs_share_data_source.go | 329 ++++++++++++++++ .../protocols_cifs_shares_data_source.go | 370 ++++++++++++++++++ 13 files changed, 1076 insertions(+) create mode 100644 docs/data-sources/protocols_cifs_share_data_source.md create mode 100644 docs/data-sources/protocols_cifs_shares_data_source.md create mode 100644 examples/data-sources/netapp-ontap_protocols_cifs_share/data-source.tf create mode 120000 examples/data-sources/netapp-ontap_protocols_cifs_share/provider.tf create mode 120000 examples/data-sources/netapp-ontap_protocols_cifs_share/terraform.tfvars create mode 120000 examples/data-sources/netapp-ontap_protocols_cifs_share/variables.tf create mode 100644 examples/data-sources/netapp-ontap_protocols_cifs_shares/data-source.tf create mode 120000 examples/data-sources/netapp-ontap_protocols_cifs_shares/provider.tf create mode 120000 examples/data-sources/netapp-ontap_protocols_cifs_shares/terraform.tfvars create mode 120000 examples/data-sources/netapp-ontap_protocols_cifs_shares/variables.tf create mode 100644 internal/interfaces/protocols_cifs_share.go create mode 100644 internal/provider/protocols_cifs_share_data_source.go create mode 100644 internal/provider/protocols_cifs_shares_data_source.go diff --git a/docs/data-sources/protocols_cifs_share_data_source.md b/docs/data-sources/protocols_cifs_share_data_source.md new file mode 100644 index 00000000..06a1dd6d --- /dev/null +++ b/docs/data-sources/protocols_cifs_share_data_source.md @@ -0,0 +1,89 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "netapp-ontap_protocols_cifs_share_data_source Data Source - terraform-provider-netapp-ontap" +subcategory: "nas" +description: |- + ProtocolsCIFSShare data source +--- + +# netapp-ontap_protocols_cifs_share_data_source (Data Source) + +ProtocolsCIFSShare data source + + + + +## Schema + +### Required + +- `cx_profile_name` (String) Connection profile name +- `name` (String) Specifies the name of the CIFS share that you want to create. If this + is a home directory share then the share name includes the pattern as + %w (Windows user name), %u (UNIX user name) and %d (Windows domain name) + variables in any combination with this parameter to generate shares dynamically. + +### Optional + +- `svm_name` (String) IPInterface svm name + +### Read-Only + +- `acls` (Attributes Set) The permissions that users and groups have on a CIFS share. (see [below for nested schema](#nestedatt--acls)) +- `change_notify` (Boolean) Specifies whether CIFS clients can request for change notifications for directories on this share. +- `comment` (String) Specify the CIFS share descriptions. +- `continuously_available` (Boolean) Specifies whether or not the clients connecting to this share can open files in a persistent manner.Files opened in this way are protected from disruptive events, such as, failover and giveback. +- `dir_umask` (Number) Directory Mode Creation Mask to be viewed as an octal number. +- `encryption` (Boolean) Specifies that SMB encryption must be used when accessing this share. Clients that do not support encryption are not able to access this share. +- `file_umask` (Number) File Mode Creation Mask to be viewed as an octal number. +- `force_group_for_create` (String) Specifies that all files that CIFS users create in a specific share belong to the same group + (also called the force-group). The force-group must be a predefined group in the UNIX group + database. This setting has no effect unless the security style of the volume is UNIX or mixed + security style. +- `home_directory` (Boolean) Specifies whether or not the share is a home directory share, where the share and path names are dynamic. + ONTAP home directory functionality automatically offer each user a dynamic share to their home directory without creating an + individual SMB share for each user. + The ONTAP CIFS home directory feature enable us to configure a share that maps to + different directories based on the user that connects to it. Instead of creating a separate shares for each user, + a single share with a home directory parameters can be created. + In a home directory share, ONTAP dynamically generates the share-name and share-path by substituting + %w, %u, and %d variables with the corresponding Windows user name, UNIX user name, and domain name, respectively. +- `namespace_caching` (Boolean) Specifies whether or not the SMB clients connecting to this share can cache the directory enumeration + results returned by the CIFS servers. +- `no_strict_security` (Boolean) Specifies whether or not CIFS clients can follow a unix symlinks outside the share boundaries. +- `offline_files` (String) Offline Files. The supported values are: + none - Clients are not permitted to cache files for offline access. + manual - Clients may cache files that are explicitly selected by the user for offline access. + documents - Clients may automatically cache files that are used by the user for offline access. + programs - Clients may automatically cache files that are used by the user for offline access + and may use those files in an offline mode even if the share is available. +- `oplocks` (Boolean) Specify whether opportunistic locks are enabled on this share. "Oplocks" allow clients to lock files and cache content locally, + which can increase performance for file operations. +- `path` (String) The fully-qualified pathname in the owning SVM namespace that is shared through this share. + If this is a home directory share then the path should be dynamic by specifying the pattern + %w (Windows user name), %u (UNIX user name), or %d (domain name) variables in any combination. + ONTAP generates the path dynamically for the connected user and this path is appended to each + search path to find the full Home Directory path. +- `show_snapshot` (Boolean) Specifies whether or not the Snapshot copies can be viewed and traversed by clients. +- `unix_symlink` (String) Controls the access of UNIX symbolic links to CIFS clients. + The supported values are: + * local - Enables only local symbolic links which is within the same CIFS share. + * widelink - Enables both local symlinks and widelinks. + * disable - Disables local symlinks and widelinks. +- `vscan_profile` (String) Vscan File-Operations Profile + The supported values are: + no_scan - Virus scans are never triggered for accesses to this share. + standard - Virus scans can be triggered by open, close, and rename operations. + strict - Virus scans can be triggered by open, read, close, and rename operations. + writes_only - Virus scans can be triggered only when a file that has been modified is closed. + + +### Nested Schema for `acls` + +Read-Only: + +- `permission` (String) Specifies the access rights that a user or group has on the defined CIFS Share. +- `type` (String) string Specifies the type of the user or group to add to the access control list of a CIFS share. +- `user_or_group` (String) Specifies the user or group name to add to the access control list of a CIFS share. + + diff --git a/docs/data-sources/protocols_cifs_shares_data_source.md b/docs/data-sources/protocols_cifs_shares_data_source.md new file mode 100644 index 00000000..a4fe9974 --- /dev/null +++ b/docs/data-sources/protocols_cifs_shares_data_source.md @@ -0,0 +1,113 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "netapp-ontap_protocols_cifs_shares_data_source Data Source - terraform-provider-netapp-ontap" +subcategory: "nas" +description: |- + ProtocolsCIFSShares data source +--- + +# netapp-ontap_protocols_cifs_shares_data_source (Data Source) + +ProtocolsCIFSShares data source + + + + +## Schema + +### Required + +- `cx_profile_name` (String) Connection profile name + +### Optional + +- `filter` (Attributes) (see [below for nested schema](#nestedatt--filter)) + +### Read-Only + +- `protocols_cifs_shares` (Attributes List) (see [below for nested schema](#nestedatt--protocols_cifs_shares)) + + +### Nested Schema for `filter` + +Optional: + +- `name` (String) ProtocolsCIFSShare name +- `svm_name` (String) ProtocolsCIFSShare svm name + + + +### Nested Schema for `protocols_cifs_shares` + +Required: + +- `cx_profile_name` (String) Connection profile name +- `name` (String) Specifies the name of the CIFS share that you want to create. If this + is a home directory share then the share name includes the pattern as + %w (Windows user name), %u (UNIX user name) and %d (Windows domain name) + variables in any combination with this parameter to generate shares dynamically. + +Optional: + +- `svm_name` (String) IPInterface svm name + +Read-Only: + +- `acls` (Attributes Set) The permissions that users and groups have on a CIFS share. (see [below for nested schema](#nestedatt--protocols_cifs_shares--acls)) +- `change_notify` (Boolean) Specifies whether CIFS clients can request for change notifications for directories on this share. +- `comment` (String) Specify the CIFS share descriptions. +- `continuously_available` (Boolean) Specifies whether or not the clients connecting to this share can open files in a persistent manner.Files opened in this way are protected from disruptive events, such as, failover and giveback. +- `dir_umask` (Number) Directory Mode Creation Mask to be viewed as an octal number. +- `encryption` (Boolean) Specifies that SMB encryption must be used when accessing this share. Clients that do not support encryption are not able to access this share. +- `file_umask` (Number) File Mode Creation Mask to be viewed as an octal number. +- `force_group_for_create` (String) Specifies that all files that CIFS users create in a specific share belong to the same group + (also called the force-group). The force-group must be a predefined group in the UNIX group + database. This setting has no effect unless the security style of the volume is UNIX or mixed + security style. +- `home_directory` (Boolean) Specifies whether or not the share is a home directory share, where the share and path names are dynamic. + ONTAP home directory functionality automatically offer each user a dynamic share to their home directory without creating an + individual SMB share for each user. + The ONTAP CIFS home directory feature enable us to configure a share that maps to + different directories based on the user that connects to it. Instead of creating a separate shares for each user, + a single share with a home directory parameters can be created. + In a home directory share, ONTAP dynamically generates the share-name and share-path by substituting + %w, %u, and %d variables with the corresponding Windows user name, UNIX user name, and domain name, respectively. +- `namespace_caching` (Boolean) Specifies whether or not the SMB clients connecting to this share can cache the directory enumeration + results returned by the CIFS servers. +- `no_strict_security` (Boolean) Specifies whether or not CIFS clients can follow a unix symlinks outside the share boundaries. +- `offline_files` (String) Offline Files. The supported values are: + none - Clients are not permitted to cache files for offline access. + manual - Clients may cache files that are explicitly selected by the user for offline access. + documents - Clients may automatically cache files that are used by the user for offline access. + programs - Clients may automatically cache files that are used by the user for offline access + and may use those files in an offline mode even if the share is available. +- `oplocks` (Boolean) Specify whether opportunistic locks are enabled on this share. "Oplocks" allow clients to lock files and cache content locally, + which can increase performance for file operations. +- `path` (String) The fully-qualified pathname in the owning SVM namespace that is shared through this share. + If this is a home directory share then the path should be dynamic by specifying the pattern + %w (Windows user name), %u (UNIX user name), or %d (domain name) variables in any combination. + ONTAP generates the path dynamically for the connected user and this path is appended to each + search path to find the full Home Directory path. +- `show_snapshot` (Boolean) Specifies whether or not the Snapshot copies can be viewed and traversed by clients. +- `unix_symlink` (String) Controls the access of UNIX symbolic links to CIFS clients. + The supported values are: + * local - Enables only local symbolic links which is within the same CIFS share. + * widelink - Enables both local symlinks and widelinks. + * disable - Disables local symlinks and widelinks. +- `vscan_profile` (String) Vscan File-Operations Profile + The supported values are: + no_scan - Virus scans are never triggered for accesses to this share. + standard - Virus scans can be triggered by open, close, and rename operations. + strict - Virus scans can be triggered by open, read, close, and rename operations. + writes_only - Virus scans can be triggered only when a file that has been modified is closed. + + +### Nested Schema for `protocols_cifs_shares.acls` + +Read-Only: + +- `permission` (String) Specifies the access rights that a user or group has on the defined CIFS Share. +- `type` (String) string Specifies the type of the user or group to add to the access control list of a CIFS share. +- `user_or_group` (String) Specifies the user or group name to add to the access control list of a CIFS share. + + diff --git a/examples/data-sources/netapp-ontap_protocols_cifs_share/data-source.tf b/examples/data-sources/netapp-ontap_protocols_cifs_share/data-source.tf new file mode 100644 index 00000000..9c6a170d --- /dev/null +++ b/examples/data-sources/netapp-ontap_protocols_cifs_share/data-source.tf @@ -0,0 +1,6 @@ +data "netapp-ontap_protocols_cifs_share_data_source" "protocols_cifs_share" { + # required to know which system to interface with + cx_profile_name = "cluster5" + name = "share1" + svm_name = "testSVM" +} diff --git a/examples/data-sources/netapp-ontap_protocols_cifs_share/provider.tf b/examples/data-sources/netapp-ontap_protocols_cifs_share/provider.tf new file mode 120000 index 00000000..c6b7138f --- /dev/null +++ b/examples/data-sources/netapp-ontap_protocols_cifs_share/provider.tf @@ -0,0 +1 @@ +../../provider/provider.tf \ No newline at end of file diff --git a/examples/data-sources/netapp-ontap_protocols_cifs_share/terraform.tfvars b/examples/data-sources/netapp-ontap_protocols_cifs_share/terraform.tfvars new file mode 120000 index 00000000..8d9d1c96 --- /dev/null +++ b/examples/data-sources/netapp-ontap_protocols_cifs_share/terraform.tfvars @@ -0,0 +1 @@ +../../provider/terraform.tfvars \ No newline at end of file diff --git a/examples/data-sources/netapp-ontap_protocols_cifs_share/variables.tf b/examples/data-sources/netapp-ontap_protocols_cifs_share/variables.tf new file mode 120000 index 00000000..395ce618 --- /dev/null +++ b/examples/data-sources/netapp-ontap_protocols_cifs_share/variables.tf @@ -0,0 +1 @@ +../../provider/variables.tf \ No newline at end of file diff --git a/examples/data-sources/netapp-ontap_protocols_cifs_shares/data-source.tf b/examples/data-sources/netapp-ontap_protocols_cifs_shares/data-source.tf new file mode 100644 index 00000000..e625495a --- /dev/null +++ b/examples/data-sources/netapp-ontap_protocols_cifs_shares/data-source.tf @@ -0,0 +1,7 @@ +data "netapp-ontap_protocols_cifs_shares_data_source" "protocols_cifs_shares" { + # required to know which system to interface with + cx_profile_name = "cluster5" + filter = { + svm_name = "testSVM" + } +} diff --git a/examples/data-sources/netapp-ontap_protocols_cifs_shares/provider.tf b/examples/data-sources/netapp-ontap_protocols_cifs_shares/provider.tf new file mode 120000 index 00000000..c6b7138f --- /dev/null +++ b/examples/data-sources/netapp-ontap_protocols_cifs_shares/provider.tf @@ -0,0 +1 @@ +../../provider/provider.tf \ No newline at end of file diff --git a/examples/data-sources/netapp-ontap_protocols_cifs_shares/terraform.tfvars b/examples/data-sources/netapp-ontap_protocols_cifs_shares/terraform.tfvars new file mode 120000 index 00000000..8d9d1c96 --- /dev/null +++ b/examples/data-sources/netapp-ontap_protocols_cifs_shares/terraform.tfvars @@ -0,0 +1 @@ +../../provider/terraform.tfvars \ No newline at end of file diff --git a/examples/data-sources/netapp-ontap_protocols_cifs_shares/variables.tf b/examples/data-sources/netapp-ontap_protocols_cifs_shares/variables.tf new file mode 120000 index 00000000..395ce618 --- /dev/null +++ b/examples/data-sources/netapp-ontap_protocols_cifs_shares/variables.tf @@ -0,0 +1 @@ +../../provider/variables.tf \ No newline at end of file diff --git a/internal/interfaces/protocols_cifs_share.go b/internal/interfaces/protocols_cifs_share.go new file mode 100644 index 00000000..e52b64a4 --- /dev/null +++ b/internal/interfaces/protocols_cifs_share.go @@ -0,0 +1,156 @@ +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" +) + +// TODO: +// copy this file to match you data source (should match internal/interfaces/protocols_cifs_share.go) +// replace ProtocolsCIFSShare with the name of the resource, following go conventions, eg IPInterface +// replace protocols_cifs_share with the name of the resource, for logging purposes, eg ip_interface +// replace api_url with API, eg ip/interfaces +// delete these 5 lines + +// ProtocolsCIFSShareGetDataModelONTAP describes the GET record data model using go types for mapping. +type ProtocolsCIFSShareGetDataModelONTAP struct { + Name string `mapstructure:"name"` + UUID string `mapstructure:"uuid"` + + Acls []Acls `mapstructure:"acls"` + ChangeNotify bool `mapstructure:"change_notify"` + Comment string `mapstructure:"comment"` + ContinuouslyAvailable bool `mapstructure:"continuously_available"` + DirUmask int64 `mapstructure:"dir_umask"` + Encryption bool `mapstructure:"encryption"` + FileUmask int64 `mapstructure:"file_umask"` + ForceGroupForCreate string `mapstructure:"force_group_for_create"` + HomeDirectory bool `mapstructure:"home_directory"` + NamespaceCaching bool `mapstructure:"namespace_caching"` + NoStrictSecurity bool `mapstructure:"no_strict_security"` + OfflineFiles string `mapstructure:"offline_files"` + Oplocks bool `mapstructure:"oplocks"` + Path string `mapstructure:"path"` + ShowSnapshot bool `mapstructure:"show_snapshot"` + UnixSymlink string `mapstructure:"unix_symlink"` + VscanProfile string `mapstructure:"vscan_profile"` +} + +type Acls struct { + Permission string `mapstructure:"permission"` + Type string `mapstructure:"type"` + UserOrGroup string `mapstructure:"user_or_group"` +} + +// ProtocolsCIFSShareResourceBodyDataModelONTAP describes the body data model using go types for mapping. +type ProtocolsCIFSShareResourceBodyDataModelONTAP struct { + Name string `mapstructure:"name"` + SVM svm `mapstructure:"svm"` +} + +// ProtocolsCIFSShareDataSourceFilterModel describes the data source data model for queries. +type ProtocolsCIFSShareDataSourceFilterModel struct { + Name string `mapstructure:"name"` + SVMName string `mapstructure:"svm.name"` +} + +// GetProtocolsCIFSShareByName to get protocols_cifs_share info +func GetProtocolsCIFSShareByName(errorHandler *utils.ErrorHandler, r restclient.RestClient, name string, svmName string) (*ProtocolsCIFSShareGetDataModelONTAP, error) { + // api := fmt.Sprintf("protocols/cifs/shares/%s/%s", svmName, name) + api := "protocols/cifs/shares" + query := r.NewQuery() + query.Add("name", name) + query.Add("svm.name", svmName) + // query.Set("name", name) + // if svmName == "" { + // query.Set("scope", "cluster") + // } else { + // query.Set("svm.name", svmName) + // query.Set("scope", "svm") + // } + query.Fields([]string{"name", "svm.name", "unix_symlink", "dir_umask", "file_umask", "acls", "home_directory", "force_group_for_create", "no_strict_security", "oplocks", "volume", "change_notify", "path", "encryption", "vscan_profile", "offline_files", "comment", "show_snapshot", "continuously_available", "namespace_caching"}) + 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 protocols_cifs_share info", fmt.Sprintf("error on GET %s: %s, statusCode %d", api, err, statusCode)) + } + + var dataONTAP ProtocolsCIFSShareGetDataModelONTAP + 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 protocols_cifs_share data source: %#v", dataONTAP)) + return &dataONTAP, nil +} + +// GetProtocolsCIFSShares to get protocols_cifs_share info for all resources matching a filter +func GetProtocolsCIFSShares(errorHandler *utils.ErrorHandler, r restclient.RestClient, filter *ProtocolsCIFSShareDataSourceFilterModel) ([]ProtocolsCIFSShareGetDataModelONTAP, error) { + api := "protocols/cifs/shares" + query := r.NewQuery() + query.Fields([]string{"name", "svm.name", "unix_symlink", "dir_umask", "file_umask", "acls", "home_directory", "force_group_for_create", "no_strict_security", "oplocks", "volume", "change_notify", "path", "encryption", "vscan_profile", "offline_files", "comment", "show_snapshot", "continuously_available", "namespace_caching"}) + if filter != nil { + var filterMap map[string]interface{} + if err := mapstructure.Decode(filter, &filterMap); err != nil { + return nil, errorHandler.MakeAndReportError("error encoding protocols_cifs_shares filter info", fmt.Sprintf("error on filter %#v: %s", filter, err)) + } + 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) + } + if err != nil { + return nil, errorHandler.MakeAndReportError("error reading protocols_cifs_shares info", fmt.Sprintf("error on GET %s: %s, statusCode %d", api, err, statusCode)) + } + + var dataONTAP []ProtocolsCIFSShareGetDataModelONTAP + for _, info := range response { + var record ProtocolsCIFSShareGetDataModelONTAP + if err := mapstructure.Decode(info, &record); err != nil { + return nil, errorHandler.MakeAndReportError(fmt.Sprintf("failed to decode response from GET %s", api), + fmt.Sprintf("error: %s, statusCode %d, info %#v", err, statusCode, info)) + } + dataONTAP = append(dataONTAP, record) + } + tflog.Debug(errorHandler.Ctx, fmt.Sprintf("Read protocols_cifs_shares data source: %#v", dataONTAP)) + return dataONTAP, nil +} + +// CreateProtocolsCIFSShare to create protocols_cifs_share +func CreateProtocolsCIFSShare(errorHandler *utils.ErrorHandler, r restclient.RestClient, body ProtocolsCIFSShareResourceBodyDataModelONTAP) (*ProtocolsCIFSShareGetDataModelONTAP, error) { + api := "api_url" + var bodyMap map[string]interface{} + if err := mapstructure.Decode(body, &bodyMap); err != nil { + return nil, errorHandler.MakeAndReportError("error encoding protocols_cifs_share 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 protocols_cifs_share", fmt.Sprintf("error on POST %s: %s, statusCode %d", api, err, statusCode)) + } + + var dataONTAP ProtocolsCIFSShareGetDataModelONTAP + if err := mapstructure.Decode(response.Records[0], &dataONTAP); err != nil { + return nil, errorHandler.MakeAndReportError("error decoding protocols_cifs_share info", fmt.Sprintf("error on decode storage/protocols_cifs_shares info: %s, statusCode %d, response %#v", err, statusCode, response)) + } + tflog.Debug(errorHandler.Ctx, fmt.Sprintf("Create protocols_cifs_share source - udata: %#v", dataONTAP)) + return &dataONTAP, nil +} + +// DeleteProtocolsCIFSShare to delete protocols_cifs_share +func DeleteProtocolsCIFSShare(errorHandler *utils.ErrorHandler, r restclient.RestClient, uuid string) error { + api := "api_url" + statusCode, _, err := r.CallDeleteMethod(api+"/"+uuid, nil, nil) + if err != nil { + return errorHandler.MakeAndReportError("error deleting protocols_cifs_share", fmt.Sprintf("error on DELETE %s: %s, statusCode %d", api, err, statusCode)) + } + return nil +} diff --git a/internal/provider/protocols_cifs_share_data_source.go b/internal/provider/protocols_cifs_share_data_source.go new file mode 100644 index 00000000..f9c2ac54 --- /dev/null +++ b/internal/provider/protocols_cifs_share_data_source.go @@ -0,0 +1,329 @@ +package provider + +import ( + "context" + "fmt" + + "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" + "github.com/hashicorp/terraform-plugin-framework/attr" + "github.com/hashicorp/terraform-plugin-framework/datasource" + "github.com/hashicorp/terraform-plugin-framework/datasource/schema" + "github.com/hashicorp/terraform-plugin-framework/schema/validator" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/netapp/terraform-provider-netapp-ontap/internal/interfaces" + "github.com/netapp/terraform-provider-netapp-ontap/internal/utils" +) + +// TODO: +// copy this file to match you data source (should match internal/provider/protocols_cifs_share_data_source.go) +// replace ProtocolsCIFSShare with the name of the resource, following go conventions, eg IPInterface +// replace protocols_cifs_share with the name of the resource, for logging purposes, eg ip_interface +// make sure to create internal/interfaces/protocols_cifs_share.go too) +// delete these 5 lines + +// Ensure provider defined types fully satisfy framework interfaces +var _ datasource.DataSource = &ProtocolsCIFSShareDataSource{} + +// NewProtocolsCIFSShareDataSource is a helper function to simplify the provider implementation. +func NewProtocolsCIFSShareDataSource() datasource.DataSource { + return &ProtocolsCIFSShareDataSource{ + config: resourceOrDataSourceConfig{ + name: "protocols_cifs_share_data_source", + }, + } +} + +// ProtocolsCIFSShareDataSource defines the data source implementation. +type ProtocolsCIFSShareDataSource struct { + config resourceOrDataSourceConfig +} + +// ProtocolsCIFSShareDataSourceModel describes the data source data model. +type ProtocolsCIFSShareDataSourceModel struct { + CxProfileName types.String `tfsdk:"cx_profile_name"` + Name types.String `tfsdk:"name"` + SVMName types.String `tfsdk:"svm_name"` + + Acls types.Set `tfsdk:"acls"` + ChangeNotify types.Bool `tfsdk:"change_notify"` + Comment types.String `tfsdk:"comment"` + ContinuouslyAvailable types.Bool `tfsdk:"continuously_available"` + DirUmask types.Int64 `tfsdk:"dir_umask"` + Encryption types.Bool `tfsdk:"encryption"` + FileUmask types.Int64 `tfsdk:"file_umask"` + ForceGroupForCreate types.String `tfsdk:"force_group_for_create"` + HomeDirectory types.Bool `tfsdk:"home_directory"` + NamespaceCaching types.Bool `tfsdk:"namespace_caching"` + NoStrictSecurity types.Bool `tfsdk:"no_strict_security"` + OfflineFiles types.String `tfsdk:"offline_files"` + Oplocks types.Bool `tfsdk:"oplocks"` + Path types.String `tfsdk:"path"` + ShowSnapshot types.Bool `tfsdk:"show_snapshot"` + UnixSymlink types.String `tfsdk:"unix_symlink"` + VscanProfile types.String `tfsdk:"vscan_profile"` +} + +// Metadata returns the data source type name. +func (d *ProtocolsCIFSShareDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_" + d.config.name +} + +// Schema defines the schema for the data source. +func (d *ProtocolsCIFSShareDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) { + resp.Schema = schema.Schema{ + // This description is used by the documentation generator and the language server. + MarkdownDescription: "ProtocolsCIFSShare data source", + + Attributes: map[string]schema.Attribute{ + "cx_profile_name": schema.StringAttribute{ + MarkdownDescription: "Connection profile name", + Required: true, + }, + "name": schema.StringAttribute{ + MarkdownDescription: `Specifies the name of the CIFS share that you want to create. If this + is a home directory share then the share name includes the pattern as + %w (Windows user name), %u (UNIX user name) and %d (Windows domain name) + variables in any combination with this parameter to generate shares dynamically. + `, + Required: true, + }, + "svm_name": schema.StringAttribute{ + MarkdownDescription: "IPInterface svm name", + Optional: true, + }, + "acls": schema.SetNestedAttribute{ + Computed: true, + Description: "The permissions that users and groups have on a CIFS share.", + NestedObject: schema.NestedAttributeObject{ + Attributes: map[string]schema.Attribute{ + "permission": schema.StringAttribute{ + MarkdownDescription: "Specifies the access rights that a user or group has on the defined CIFS Share.", + Computed: true, + Validators: []validator.String{ + stringvalidator.OneOf("full_control", "read", "change", "no_access"), + }, + }, + "type": schema.StringAttribute{ + MarkdownDescription: "string Specifies the type of the user or group to add to the access control list of a CIFS share.", + Computed: true, + Validators: []validator.String{ + stringvalidator.OneOf("windows", "unix_user", "unix_group"), + }, + }, + "user_or_group": schema.StringAttribute{ + MarkdownDescription: "Specifies the user or group name to add to the access control list of a CIFS share.", + Computed: true, + }, + }, + }, + }, + "change_notify": schema.BoolAttribute{ + MarkdownDescription: "Specifies whether CIFS clients can request for change notifications for directories on this share.", + Computed: true, + }, + "comment": schema.StringAttribute{ + MarkdownDescription: "Specify the CIFS share descriptions.", + Computed: true, + }, + "continuously_available": schema.BoolAttribute{ + MarkdownDescription: "Specifies whether or not the clients connecting to this share can open files in a persistent manner.Files opened in this way are protected from disruptive events, such as, failover and giveback.", + Computed: true, + }, + "dir_umask": schema.Int64Attribute{ + MarkdownDescription: "Directory Mode Creation Mask to be viewed as an octal number.", + Computed: true, + }, + "encryption": schema.BoolAttribute{ + MarkdownDescription: "Specifies that SMB encryption must be used when accessing this share. Clients that do not support encryption are not able to access this share.", + Computed: true, + }, + "file_umask": schema.Int64Attribute{ + MarkdownDescription: "File Mode Creation Mask to be viewed as an octal number.", + Computed: true, + }, + "force_group_for_create": schema.StringAttribute{ + MarkdownDescription: `Specifies that all files that CIFS users create in a specific share belong to the same group + (also called the force-group). The force-group must be a predefined group in the UNIX group + database. This setting has no effect unless the security style of the volume is UNIX or mixed + security style.`, + Computed: true, + }, + "home_directory": schema.BoolAttribute{ + MarkdownDescription: `Specifies whether or not the share is a home directory share, where the share and path names are dynamic. + ONTAP home directory functionality automatically offer each user a dynamic share to their home directory without creating an + individual SMB share for each user. + The ONTAP CIFS home directory feature enable us to configure a share that maps to + different directories based on the user that connects to it. Instead of creating a separate shares for each user, + a single share with a home directory parameters can be created. + In a home directory share, ONTAP dynamically generates the share-name and share-path by substituting + %w, %u, and %d variables with the corresponding Windows user name, UNIX user name, and domain name, respectively.`, + Computed: true, + }, + "namespace_caching": schema.BoolAttribute{ + MarkdownDescription: `Specifies whether or not the SMB clients connecting to this share can cache the directory enumeration + results returned by the CIFS servers.`, + Computed: true, + }, + "no_strict_security": schema.BoolAttribute{ + MarkdownDescription: "Specifies whether or not CIFS clients can follow a unix symlinks outside the share boundaries.", + Computed: true, + }, + "offline_files": schema.StringAttribute{ + MarkdownDescription: `Offline Files. The supported values are: + none - Clients are not permitted to cache files for offline access. + manual - Clients may cache files that are explicitly selected by the user for offline access. + documents - Clients may automatically cache files that are used by the user for offline access. + programs - Clients may automatically cache files that are used by the user for offline access + and may use those files in an offline mode even if the share is available. + `, + Computed: true, + Validators: []validator.String{ + stringvalidator.OneOf("none", "manual", "documents", "programs"), + }, + }, + "oplocks": schema.BoolAttribute{ + MarkdownDescription: `Specify whether opportunistic locks are enabled on this share. "Oplocks" allow clients to lock files and cache content locally, + which can increase performance for file operations. + `, + Computed: true, + }, + "path": schema.StringAttribute{ + MarkdownDescription: `The fully-qualified pathname in the owning SVM namespace that is shared through this share. + If this is a home directory share then the path should be dynamic by specifying the pattern + %w (Windows user name), %u (UNIX user name), or %d (domain name) variables in any combination. + ONTAP generates the path dynamically for the connected user and this path is appended to each + search path to find the full Home Directory path. + `, + Computed: true, + }, + "show_snapshot": schema.BoolAttribute{ + MarkdownDescription: `Specifies whether or not the Snapshot copies can be viewed and traversed by clients.`, + Computed: true, + }, + "unix_symlink": schema.StringAttribute{ + MarkdownDescription: `Controls the access of UNIX symbolic links to CIFS clients. + The supported values are: + * local - Enables only local symbolic links which is within the same CIFS share. + * widelink - Enables both local symlinks and widelinks. + * disable - Disables local symlinks and widelinks.`, + Computed: true, + Validators: []validator.String{ + stringvalidator.OneOf("local", "widelink", "disable"), + }, + }, + "vscan_profile": schema.StringAttribute{ + MarkdownDescription: ` Vscan File-Operations Profile + The supported values are: + no_scan - Virus scans are never triggered for accesses to this share. + standard - Virus scans can be triggered by open, close, and rename operations. + strict - Virus scans can be triggered by open, read, close, and rename operations. + writes_only - Virus scans can be triggered only when a file that has been modified is closed.`, + Computed: true, + Validators: []validator.String{ + stringvalidator.OneOf("no_scan", "standard", "strict", "writes_only"), + }, + }, + }, + } +} + +// Configure adds the provider configured client to the data source. +func (d *ProtocolsCIFSShareDataSource) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) { + // Prevent panic if the provider has not been configured. + if req.ProviderData == nil { + return + } + config, ok := req.ProviderData.(Config) + if !ok { + resp.Diagnostics.AddError( + "Unexpected Data Source Configure Type", + fmt.Sprintf("Expected Config, got: %T. Please report this issue to the provider developers.", req.ProviderData), + ) + } + d.config.providerConfig = config +} + +// Read refreshes the Terraform state with the latest data. +func (d *ProtocolsCIFSShareDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { + var data ProtocolsCIFSShareDataSourceModel + + // Read Terraform configuration data into the model + resp.Diagnostics.Append(req.Config.Get(ctx, &data)...) + + if resp.Diagnostics.HasError() { + return + } + + errorHandler := utils.NewErrorHandler(ctx, &resp.Diagnostics) + // we need to defer setting the client until we can read the connection profile name + client, err := getRestClient(errorHandler, d.config, data.CxProfileName) + if err != nil { + // error reporting done inside NewClient + return + } + + restInfo, err := interfaces.GetProtocolsCIFSShareByName(errorHandler, *client, data.Name.ValueString(), data.SVMName.ValueString()) + if err != nil { + // error reporting done inside GetProtocolsCIFSShare + return + } + + data.Name = types.StringValue(restInfo.Name) + data.ChangeNotify = types.BoolValue(restInfo.ChangeNotify) + data.Comment = types.StringValue(restInfo.Comment) + data.ContinuouslyAvailable = types.BoolValue(restInfo.ContinuouslyAvailable) + data.DirUmask = types.Int64Value(restInfo.DirUmask) + data.Encryption = types.BoolValue(restInfo.Encryption) + data.FileUmask = types.Int64Value(restInfo.FileUmask) + data.ForceGroupForCreate = types.StringValue(restInfo.ForceGroupForCreate) + data.HomeDirectory = types.BoolValue(restInfo.HomeDirectory) + data.NamespaceCaching = types.BoolValue(restInfo.NamespaceCaching) + data.NoStrictSecurity = types.BoolValue(restInfo.NoStrictSecurity) + data.OfflineFiles = types.StringValue(restInfo.OfflineFiles) + data.Oplocks = types.BoolValue(restInfo.Oplocks) + data.Path = types.StringValue(restInfo.Path) + data.ShowSnapshot = types.BoolValue(restInfo.ShowSnapshot) + data.UnixSymlink = types.StringValue(restInfo.UnixSymlink) + data.VscanProfile = types.StringValue(restInfo.VscanProfile) + + // Acls + setElements := []attr.Value{} + for _, acls := range restInfo.Acls { + elementType := map[string]attr.Type{ + "permission": types.StringType, + "type": types.StringType, + "user_or_group": types.StringType, + } + elementValue := map[string]attr.Value{ + "permission": types.StringValue(acls.Permission), + "type": types.StringValue(acls.Type), + "user_or_group": types.StringValue(acls.UserOrGroup), + } + objectValue, diags := types.ObjectValue(elementType, elementValue) + if diags.HasError() { + resp.Diagnostics.Append(diags...) + return + } + setElements = append(setElements, objectValue) + setValue, diags := types.SetValue(types.ObjectType{ + AttrTypes: map[string]attr.Type{ + "permission": types.StringType, + "type": types.StringType, + "user_or_group": types.StringType, + }, + }, setElements) + if diags.HasError() { + resp.Diagnostics.Append(diags...) + return + } + data.Acls = setValue + } + + // Write logs using the tflog package + // Documentation: https://terraform.io/plugin/log + tflog.Debug(ctx, fmt.Sprintf("read a data source: %#v", data)) + + // Save data into Terraform state + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} diff --git a/internal/provider/protocols_cifs_shares_data_source.go b/internal/provider/protocols_cifs_shares_data_source.go new file mode 100644 index 00000000..472b8f44 --- /dev/null +++ b/internal/provider/protocols_cifs_shares_data_source.go @@ -0,0 +1,370 @@ +package provider + +import ( + "context" + "fmt" + "log" + + "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" + "github.com/hashicorp/terraform-plugin-framework/attr" + "github.com/hashicorp/terraform-plugin-framework/datasource" + "github.com/hashicorp/terraform-plugin-framework/datasource/schema" + "github.com/hashicorp/terraform-plugin-framework/schema/validator" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/netapp/terraform-provider-netapp-ontap/internal/interfaces" + "github.com/netapp/terraform-provider-netapp-ontap/internal/utils" +) + +// TODO: +// copy this file to match you data source (should match internal/provider/protocols_cifs_share_data_source.go) +// replace ProtocolsCIFSShares with the name of the resource, following go conventions, eg IPInterfaces +// replace protocols_cifs_shares with the name of the resource, for logging purposes, eg ip_interfaces +// make sure to create internal/interfaces/protocols_cifs_share.go too) +// delete these 5 lines + +// Ensure provider defined types fully satisfy framework interfaces +var _ datasource.DataSource = &ProtocolsCIFSSharesDataSource{} + +// NewProtocolsCIFSSharesDataSource is a helper function to simplify the provider implementation. +func NewProtocolsCIFSSharesDataSource() datasource.DataSource { + return &ProtocolsCIFSSharesDataSource{ + config: resourceOrDataSourceConfig{ + name: "protocols_cifs_shares_data_source", + }, + } +} + +// ProtocolsCIFSSharesDataSource defines the data source implementation. +type ProtocolsCIFSSharesDataSource struct { + config resourceOrDataSourceConfig +} + +// ProtocolsCIFSSharesDataSourceModel describes the data source data model. +type ProtocolsCIFSSharesDataSourceModel struct { + CxProfileName types.String `tfsdk:"cx_profile_name"` + ProtocolsCIFSShares []ProtocolsCIFSShareDataSourceModel `tfsdk:"protocols_cifs_shares"` + Filter *ProtocolsCIFSSharesDataSourceFilterModel `tfsdk:"filter"` +} + +// ProtocolsCIFSSharesDataSourceFilterModel describes the data source data model for queries. +type ProtocolsCIFSSharesDataSourceFilterModel struct { + Name types.String `tfsdk:"name"` + SVMName types.String `tfsdk:"svm_name"` +} + +// Metadata returns the data source type name. +func (d *ProtocolsCIFSSharesDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_" + d.config.name +} + +// Schema defines the schema for the data source. +func (d *ProtocolsCIFSSharesDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) { + resp.Schema = schema.Schema{ + // This description is used by the documentation generator and the language server. + MarkdownDescription: "ProtocolsCIFSShares data source", + + Attributes: map[string]schema.Attribute{ + "cx_profile_name": schema.StringAttribute{ + MarkdownDescription: "Connection profile name", + Required: true, + }, + "filter": schema.SingleNestedAttribute{ + Attributes: map[string]schema.Attribute{ + "name": schema.StringAttribute{ + MarkdownDescription: "ProtocolsCIFSShare name", + Optional: true, + }, + "svm_name": schema.StringAttribute{ + MarkdownDescription: "ProtocolsCIFSShare svm name", + Optional: true, + }, + }, + Optional: true, + }, + "protocols_cifs_shares": schema.ListNestedAttribute{ + NestedObject: schema.NestedAttributeObject{ + Attributes: map[string]schema.Attribute{ + "cx_profile_name": schema.StringAttribute{ + MarkdownDescription: "Connection profile name", + Required: true, + }, + "name": schema.StringAttribute{ + MarkdownDescription: `Specifies the name of the CIFS share that you want to create. If this + is a home directory share then the share name includes the pattern as + %w (Windows user name), %u (UNIX user name) and %d (Windows domain name) + variables in any combination with this parameter to generate shares dynamically. + `, + Required: true, + }, + "svm_name": schema.StringAttribute{ + MarkdownDescription: "IPInterface svm name", + Optional: true, + }, + "acls": schema.SetNestedAttribute{ + Computed: true, + Description: "The permissions that users and groups have on a CIFS share.", + NestedObject: schema.NestedAttributeObject{ + Attributes: map[string]schema.Attribute{ + "permission": schema.StringAttribute{ + MarkdownDescription: "Specifies the access rights that a user or group has on the defined CIFS Share.", + Computed: true, + Validators: []validator.String{ + stringvalidator.OneOf("full_control", "read", "change", "no_access"), + }, + }, + "type": schema.StringAttribute{ + MarkdownDescription: "string Specifies the type of the user or group to add to the access control list of a CIFS share.", + Computed: true, + Validators: []validator.String{ + stringvalidator.OneOf("windows", "unix_user", "unix_group"), + }, + }, + "user_or_group": schema.StringAttribute{ + MarkdownDescription: "Specifies the user or group name to add to the access control list of a CIFS share.", + Computed: true, + }, + }, + }, + }, + "change_notify": schema.BoolAttribute{ + MarkdownDescription: "Specifies whether CIFS clients can request for change notifications for directories on this share.", + Computed: true, + }, + "comment": schema.StringAttribute{ + MarkdownDescription: "Specify the CIFS share descriptions.", + Computed: true, + }, + "continuously_available": schema.BoolAttribute{ + MarkdownDescription: "Specifies whether or not the clients connecting to this share can open files in a persistent manner.Files opened in this way are protected from disruptive events, such as, failover and giveback.", + Computed: true, + }, + "dir_umask": schema.Int64Attribute{ + MarkdownDescription: "Directory Mode Creation Mask to be viewed as an octal number.", + Computed: true, + }, + "encryption": schema.BoolAttribute{ + MarkdownDescription: "Specifies that SMB encryption must be used when accessing this share. Clients that do not support encryption are not able to access this share.", + Computed: true, + }, + "file_umask": schema.Int64Attribute{ + MarkdownDescription: "File Mode Creation Mask to be viewed as an octal number.", + Computed: true, + }, + "force_group_for_create": schema.StringAttribute{ + MarkdownDescription: `Specifies that all files that CIFS users create in a specific share belong to the same group + (also called the force-group). The force-group must be a predefined group in the UNIX group + database. This setting has no effect unless the security style of the volume is UNIX or mixed + security style.`, + Computed: true, + }, + "home_directory": schema.BoolAttribute{ + MarkdownDescription: `Specifies whether or not the share is a home directory share, where the share and path names are dynamic. + ONTAP home directory functionality automatically offer each user a dynamic share to their home directory without creating an + individual SMB share for each user. + The ONTAP CIFS home directory feature enable us to configure a share that maps to + different directories based on the user that connects to it. Instead of creating a separate shares for each user, + a single share with a home directory parameters can be created. + In a home directory share, ONTAP dynamically generates the share-name and share-path by substituting + %w, %u, and %d variables with the corresponding Windows user name, UNIX user name, and domain name, respectively.`, + Computed: true, + }, + "namespace_caching": schema.BoolAttribute{ + MarkdownDescription: `Specifies whether or not the SMB clients connecting to this share can cache the directory enumeration + results returned by the CIFS servers.`, + Computed: true, + }, + "no_strict_security": schema.BoolAttribute{ + MarkdownDescription: "Specifies whether or not CIFS clients can follow a unix symlinks outside the share boundaries.", + Computed: true, + }, + "offline_files": schema.StringAttribute{ + MarkdownDescription: `Offline Files. The supported values are: + none - Clients are not permitted to cache files for offline access. + manual - Clients may cache files that are explicitly selected by the user for offline access. + documents - Clients may automatically cache files that are used by the user for offline access. + programs - Clients may automatically cache files that are used by the user for offline access + and may use those files in an offline mode even if the share is available. + `, + Computed: true, + Validators: []validator.String{ + stringvalidator.OneOf("none", "manual", "documents", "programs"), + }, + }, + "oplocks": schema.BoolAttribute{ + MarkdownDescription: `Specify whether opportunistic locks are enabled on this share. "Oplocks" allow clients to lock files and cache content locally, + which can increase performance for file operations. + `, + Computed: true, + }, + "path": schema.StringAttribute{ + MarkdownDescription: `The fully-qualified pathname in the owning SVM namespace that is shared through this share. + If this is a home directory share then the path should be dynamic by specifying the pattern + %w (Windows user name), %u (UNIX user name), or %d (domain name) variables in any combination. + ONTAP generates the path dynamically for the connected user and this path is appended to each + search path to find the full Home Directory path. + `, + Computed: true, + }, + "show_snapshot": schema.BoolAttribute{ + MarkdownDescription: `Specifies whether or not the Snapshot copies can be viewed and traversed by clients.`, + Computed: true, + }, + "unix_symlink": schema.StringAttribute{ + MarkdownDescription: `Controls the access of UNIX symbolic links to CIFS clients. + The supported values are: + * local - Enables only local symbolic links which is within the same CIFS share. + * widelink - Enables both local symlinks and widelinks. + * disable - Disables local symlinks and widelinks.`, + Computed: true, + Validators: []validator.String{ + stringvalidator.OneOf("local", "widelink", "disable"), + }, + }, + "vscan_profile": schema.StringAttribute{ + MarkdownDescription: ` Vscan File-Operations Profile + The supported values are: + no_scan - Virus scans are never triggered for accesses to this share. + standard - Virus scans can be triggered by open, close, and rename operations. + strict - Virus scans can be triggered by open, read, close, and rename operations. + writes_only - Virus scans can be triggered only when a file that has been modified is closed.`, + Computed: true, + Validators: []validator.String{ + stringvalidator.OneOf("no_scan", "standard", "strict", "writes_only"), + }, + }, + }, + }, + Computed: true, + MarkdownDescription: "", + }, + }, + } +} + +// Configure adds the provider configured client to the data source. +func (d *ProtocolsCIFSSharesDataSource) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) { + // Prevent panic if the provider has not been configured. + if req.ProviderData == nil { + return + } + config, ok := req.ProviderData.(Config) + if !ok { + resp.Diagnostics.AddError( + "Unexpected Data Source Configure Type", + fmt.Sprintf("Expected Config, got: %T. Please report this issue to the provider developers.", req.ProviderData), + ) + } + d.config.providerConfig = config +} + +// Read refreshes the Terraform state with the latest data. +func (d *ProtocolsCIFSSharesDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { + var data ProtocolsCIFSSharesDataSourceModel + + // Read Terraform configuration data into the model + resp.Diagnostics.Append(req.Config.Get(ctx, &data)...) + + if resp.Diagnostics.HasError() { + return + } + + errorHandler := utils.NewErrorHandler(ctx, &resp.Diagnostics) + // we need to defer setting the client until we can read the connection profile name + client, err := getRestClient(errorHandler, d.config, data.CxProfileName) + if err != nil { + // error reporting done inside NewClient + return + } + + var filter *interfaces.ProtocolsCIFSShareDataSourceFilterModel = nil + if data.Filter != nil { + filter = &interfaces.ProtocolsCIFSShareDataSourceFilterModel{ + Name: data.Filter.Name.ValueString(), + } + } + restInfo, err := interfaces.GetProtocolsCIFSShares(errorHandler, *client, filter) + if err != nil { + // error reporting done inside GetProtocolsCIFSShares + return + } + data.ProtocolsCIFSShares = make([]ProtocolsCIFSShareDataSourceModel, len(restInfo)) + log.Printf("restInfo is: %#v", len(restInfo)) + for index, record := range restInfo { + data.ProtocolsCIFSShares[index] = ProtocolsCIFSShareDataSourceModel{ + CxProfileName: types.String(data.CxProfileName), + Name: types.StringValue(record.Name), + } + // data.ProtocolsCIFSShares[index].Name = types.StringValue(restInfo.Name) + data.ProtocolsCIFSShares[index].ChangeNotify = types.BoolValue(record.ChangeNotify) + data.ProtocolsCIFSShares[index].Comment = types.StringValue(record.Comment) + data.ProtocolsCIFSShares[index].ContinuouslyAvailable = types.BoolValue(record.ContinuouslyAvailable) + data.ProtocolsCIFSShares[index].DirUmask = types.Int64Value(record.DirUmask) + data.ProtocolsCIFSShares[index].Encryption = types.BoolValue(record.Encryption) + data.ProtocolsCIFSShares[index].FileUmask = types.Int64Value(record.FileUmask) + data.ProtocolsCIFSShares[index].ForceGroupForCreate = types.StringValue(record.ForceGroupForCreate) + data.ProtocolsCIFSShares[index].HomeDirectory = types.BoolValue(record.HomeDirectory) + data.ProtocolsCIFSShares[index].NamespaceCaching = types.BoolValue(record.NamespaceCaching) + data.ProtocolsCIFSShares[index].NoStrictSecurity = types.BoolValue(record.NoStrictSecurity) + data.ProtocolsCIFSShares[index].OfflineFiles = types.StringValue(record.OfflineFiles) + data.ProtocolsCIFSShares[index].Oplocks = types.BoolValue(record.Oplocks) + data.ProtocolsCIFSShares[index].Path = types.StringValue(record.Path) + data.ProtocolsCIFSShares[index].ShowSnapshot = types.BoolValue(record.ShowSnapshot) + data.ProtocolsCIFSShares[index].UnixSymlink = types.StringValue(record.UnixSymlink) + data.ProtocolsCIFSShares[index].VscanProfile = types.StringValue(record.VscanProfile) + + if len(record.Acls) == 0 { + setValue, diags := types.SetValue(types.ObjectType{ + AttrTypes: map[string]attr.Type{ + "permission": types.StringType, + "type": types.StringType, + "user_or_group": types.StringType, + }, + }, []attr.Value{}) + if diags.HasError() { + resp.Diagnostics.Append(diags...) + return + } + data.ProtocolsCIFSShares[index].Acls = setValue + } else { + setElements := []attr.Value{} + for _, acls := range record.Acls { + log.Printf("acls is: %#v", acls) + elementType := map[string]attr.Type{ + "permission": types.StringType, + "type": types.StringType, + "user_or_group": types.StringType, + } + elementValue := map[string]attr.Value{ + "permission": types.StringValue(acls.Permission), + "type": types.StringValue(acls.Type), + "user_or_group": types.StringValue(acls.UserOrGroup), + } + objectValue, diags := types.ObjectValue(elementType, elementValue) + if diags.HasError() { + resp.Diagnostics.Append(diags...) + return + } + setElements = append(setElements, objectValue) + setValue, diags := types.SetValue(types.ObjectType{ + AttrTypes: map[string]attr.Type{ + "permission": types.StringType, + "type": types.StringType, + "user_or_group": types.StringType, + }, + }, setElements) + if diags.HasError() { + resp.Diagnostics.Append(diags...) + return + } + data.ProtocolsCIFSShares[index].Acls = setValue + } + } + } + // Write logs using the tflog package + // Documentation: https://terraform.io/plugin/log + tflog.Debug(ctx, fmt.Sprintf("read a data source: %#v", data)) + + // Save data into Terraform state + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} From d1dd40408fb005eba57ac8bdc6c123b7a7da175f Mon Sep 17 00:00:00 2001 From: swenjun Date: Tue, 26 Mar 2024 14:47:09 -0700 Subject: [PATCH 2/7] added missing files. --- internal/provider/provider.go | 2 ++ scripts/generate_docs.py | 2 ++ 2 files changed, 4 insertions(+) diff --git a/internal/provider/provider.go b/internal/provider/provider.go index f9b61fa4..5ae42c71 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -199,6 +199,8 @@ func (p *ONTAPProvider) DataSources(ctx context.Context) []func() datasource.Dat NewIPRoutesDataSource, NewNameServicesDNSDataSource, NewNameServicesDNSsDataSource, + NewProtocolsCIFSShareDataSource, + NewProtocolsCIFSSharesDataSource, NewProtocolsNfsServiceDataSource, NewProtocolsNfsServicesDataSource, NewProtocolsSanIgroupDataSource, diff --git a/scripts/generate_docs.py b/scripts/generate_docs.py index f273afc7..13e53815 100755 --- a/scripts/generate_docs.py +++ b/scripts/generate_docs.py @@ -20,6 +20,8 @@ "protocols_cifs_local_user_data_source.md", "protocols_cifs_local_user_resource.md", "protocols_cifs_service_data_source.md", + "protocols_cifs_share_data_source.md", + "protocols_cifs_shares_data_source.md", "protocols_cifs_user_group_privilege_data_source.md", "protocols_cifs_user_group_privilege_resource.md", "protocols_nfs_service_data_source.md", From 8cd299d3e8c5b1a0b28c78a71bddf69852d207fd Mon Sep 17 00:00:00 2001 From: swenjun Date: Wed, 3 Apr 2024 16:26:12 -0700 Subject: [PATCH 3/7] Lint. --- internal/interfaces/protocols_cifs_share.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/interfaces/protocols_cifs_share.go b/internal/interfaces/protocols_cifs_share.go index e52b64a4..70d78840 100644 --- a/internal/interfaces/protocols_cifs_share.go +++ b/internal/interfaces/protocols_cifs_share.go @@ -40,6 +40,7 @@ type ProtocolsCIFSShareGetDataModelONTAP struct { VscanProfile string `mapstructure:"vscan_profile"` } +// Acls describes the acls data model using go types for mapping. type Acls struct { Permission string `mapstructure:"permission"` Type string `mapstructure:"type"` From 7fd05c45306ae1e43825acdf07d654bb76197591 Mon Sep 17 00:00:00 2001 From: swenjun Date: Thu, 4 Apr 2024 14:12:23 -0700 Subject: [PATCH 4/7] Added example in docs. --- .../protocols_cifs_share_data_source.md | 18 +++++++++++++++--- .../protocols_cifs_shares_data_source.md | 18 ++++++++++++++++-- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/docs/data-sources/protocols_cifs_share_data_source.md b/docs/data-sources/protocols_cifs_share_data_source.md index 06a1dd6d..c420320e 100644 --- a/docs/data-sources/protocols_cifs_share_data_source.md +++ b/docs/data-sources/protocols_cifs_share_data_source.md @@ -8,9 +8,21 @@ description: |- # netapp-ontap_protocols_cifs_share_data_source (Data Source) -ProtocolsCIFSShare data source - - +Retrieves the details of a cifs share + +### Related ONTAP commands +* vserver cifs share show +* vserver cifs share properties show + +## Example Usage +```terraform +data "netapp-ontap_protocols_cifs_share_data_source" "protocols_cifs_share" { + # required to know which system to interface with + cx_profile_name = "cluster5" + name = "cifs_share" + svm_name = "testSVM" +} +``` ## Schema diff --git a/docs/data-sources/protocols_cifs_shares_data_source.md b/docs/data-sources/protocols_cifs_shares_data_source.md index a4fe9974..d15b5d15 100644 --- a/docs/data-sources/protocols_cifs_shares_data_source.md +++ b/docs/data-sources/protocols_cifs_shares_data_source.md @@ -8,8 +8,22 @@ description: |- # netapp-ontap_protocols_cifs_shares_data_source (Data Source) -ProtocolsCIFSShares data source - +Retrieves the details of one or more cifs shares by filter + +### Related ONTAP commands +* vserver cifs share show +* vserver cifs share properties show + +## Example Usage +```terraform +data "netapp-ontap_protocols_cifs_shares_data_source" "protocols_cifs_shares" { + # required to know which system to interface with + cx_profile_name = "cluster5" + filter = { + svm_name = "testSVM" + } +} +``` From ddda63bddbc869e751dca15b04e91a8ecbfdf076 Mon Sep 17 00:00:00 2001 From: swenjun Date: Thu, 4 Apr 2024 14:56:59 -0700 Subject: [PATCH 5/7] remove TODO comments. --- internal/interfaces/protocols_cifs_share.go | 7 ------- internal/provider/protocols_cifs_share_data_source.go | 7 ------- internal/provider/protocols_cifs_shares_data_source.go | 7 ------- 3 files changed, 21 deletions(-) diff --git a/internal/interfaces/protocols_cifs_share.go b/internal/interfaces/protocols_cifs_share.go index 70d78840..20d6c07b 100644 --- a/internal/interfaces/protocols_cifs_share.go +++ b/internal/interfaces/protocols_cifs_share.go @@ -9,13 +9,6 @@ import ( "github.com/netapp/terraform-provider-netapp-ontap/internal/utils" ) -// TODO: -// copy this file to match you data source (should match internal/interfaces/protocols_cifs_share.go) -// replace ProtocolsCIFSShare with the name of the resource, following go conventions, eg IPInterface -// replace protocols_cifs_share with the name of the resource, for logging purposes, eg ip_interface -// replace api_url with API, eg ip/interfaces -// delete these 5 lines - // ProtocolsCIFSShareGetDataModelONTAP describes the GET record data model using go types for mapping. type ProtocolsCIFSShareGetDataModelONTAP struct { Name string `mapstructure:"name"` diff --git a/internal/provider/protocols_cifs_share_data_source.go b/internal/provider/protocols_cifs_share_data_source.go index f9c2ac54..412791e5 100644 --- a/internal/provider/protocols_cifs_share_data_source.go +++ b/internal/provider/protocols_cifs_share_data_source.go @@ -15,13 +15,6 @@ import ( "github.com/netapp/terraform-provider-netapp-ontap/internal/utils" ) -// TODO: -// copy this file to match you data source (should match internal/provider/protocols_cifs_share_data_source.go) -// replace ProtocolsCIFSShare with the name of the resource, following go conventions, eg IPInterface -// replace protocols_cifs_share with the name of the resource, for logging purposes, eg ip_interface -// make sure to create internal/interfaces/protocols_cifs_share.go too) -// delete these 5 lines - // Ensure provider defined types fully satisfy framework interfaces var _ datasource.DataSource = &ProtocolsCIFSShareDataSource{} diff --git a/internal/provider/protocols_cifs_shares_data_source.go b/internal/provider/protocols_cifs_shares_data_source.go index 472b8f44..cce0fc48 100644 --- a/internal/provider/protocols_cifs_shares_data_source.go +++ b/internal/provider/protocols_cifs_shares_data_source.go @@ -16,13 +16,6 @@ import ( "github.com/netapp/terraform-provider-netapp-ontap/internal/utils" ) -// TODO: -// copy this file to match you data source (should match internal/provider/protocols_cifs_share_data_source.go) -// replace ProtocolsCIFSShares with the name of the resource, following go conventions, eg IPInterfaces -// replace protocols_cifs_shares with the name of the resource, for logging purposes, eg ip_interfaces -// make sure to create internal/interfaces/protocols_cifs_share.go too) -// delete these 5 lines - // Ensure provider defined types fully satisfy framework interfaces var _ datasource.DataSource = &ProtocolsCIFSSharesDataSource{} From 31593d3214aa9a6f1f0b45e4b64f14b1c132bedf Mon Sep 17 00:00:00 2001 From: swenjun Date: Thu, 4 Apr 2024 16:11:18 -0700 Subject: [PATCH 6/7] removed unwanted comment. --- internal/interfaces/protocols_cifs_share.go | 7 ------- 1 file changed, 7 deletions(-) diff --git a/internal/interfaces/protocols_cifs_share.go b/internal/interfaces/protocols_cifs_share.go index 20d6c07b..63cd5d2c 100644 --- a/internal/interfaces/protocols_cifs_share.go +++ b/internal/interfaces/protocols_cifs_share.go @@ -59,13 +59,6 @@ func GetProtocolsCIFSShareByName(errorHandler *utils.ErrorHandler, r restclient. query := r.NewQuery() query.Add("name", name) query.Add("svm.name", svmName) - // query.Set("name", name) - // if svmName == "" { - // query.Set("scope", "cluster") - // } else { - // query.Set("svm.name", svmName) - // query.Set("scope", "svm") - // } query.Fields([]string{"name", "svm.name", "unix_symlink", "dir_umask", "file_umask", "acls", "home_directory", "force_group_for_create", "no_strict_security", "oplocks", "volume", "change_notify", "path", "encryption", "vscan_profile", "offline_files", "comment", "show_snapshot", "continuously_available", "namespace_caching"}) statusCode, response, err := r.GetNilOrOneRecord(api, query, nil) if err == nil && response == nil { From 8b99ae1fbceef80f5dff5112e6586074346b5444 Mon Sep 17 00:00:00 2001 From: swenjun Date: Thu, 4 Apr 2024 16:17:39 -0700 Subject: [PATCH 7/7] Edit CHANGELOG.md --- CHANGELOG.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d7fd247d..d0f76cac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,8 +7,8 @@ FEATURES: * **New Data Source:** `netapp_ontap_cluster_peers_data_source` ([#50](https://github.com/NetApp/terraform-provider-netapp-ontap/issues/50)) * **New Data Source:** `netapp-ontap_protocols_cifs_local_user_data_source` ([#55](https://github.com/NetApp/terraform-provider-netapp-ontap/issues/55)) * **New Data Source:** `netapp-ontap_protocols_cifs_local_users_data_source` ([#55](https://github.com/NetApp/terraform-provider-netapp-ontap/issues/55)) -* **New Data Source** `netapp-ontap_security_account_data_source` ([#22](https://github.com/NetApp/terraform-provider-netapp-ontap/issues/22)) -* **New Data Source** `netapp-ontap_security_accounts_data_source` ([#22](https://github.com/NetApp/terraform-provider-netapp-ontap/issues/22)) +* **New Data Source:** `netapp-ontap_security_account_data_source` ([#22](https://github.com/NetApp/terraform-provider-netapp-ontap/issues/22)) +* **New Data Source:** `netapp-ontap_security_accounts_data_source` ([#22](https://github.com/NetApp/terraform-provider-netapp-ontap/issues/22)) * **New Data Source:** `netapp-ontap_protocols_cifs_user_group_privilege_data_source` ([#57](https://github.com/NetApp/terraform-provider-netapp-ontap/issues/57)) * **New Data Source:** `netapp-ontap_protocols_cifs_user_group_privileges_data_source` ([#57](https://github.com/NetApp/terraform-provider-netapp-ontap/issues/57)) * **New Data Source:** `netapp-ontap_storage_lun_data_source` ([#12](https://github.com/NetApp/terraform-provider-netapp-ontap/issues/12)) @@ -19,8 +19,12 @@ FEATURES: * **New Data Source:** `netapp-ontap_svm_peers_data_source` ([#52](https://github.com/NetApp/terraform-provider-netapp-ontap/issues/52)) * **New Data Source:** `netapp_ontap_protocols_cifs_server_data_source` ([#24](https://github.com/NetApp/terraform-provider-netapp-ontap/issues/24)) * **New Data Source:** `netapp_ontap_protocols_cifs_servers_data_source` ([#24](https://github.com/NetApp/terraform-provider-netapp-ontap/issues/24)) +* **New Data Source:** `netapp_ontap_storage_flexcache_data_source` ([#47](https://github.com/NetApp/terraform-provider-netapp-ontap/issues/47)) +* **New Data Source:** `netapp_ontap_storage_flexcaches_data_source` ([#47](https://github.com/NetApp/terraform-provider-netapp-ontap/issues/47)) * **New Data Source:** `netapp-ontap_name_services_ldap_data_source` ([#26](https://github.com/NetApp/terraform-provider-netapp-ontap/issues/26)) * **New Data Source:** `netapp-ontap_name_services_ldaps_data_source` ([#26](https://github.com/NetApp/terraform-provider-netapp-ontap/issues/26)) +* **New Data Source:** `netapp-ontap_protocols_cifs_share_data_source` ([#28](https://github.com/NetApp/terraform-provider-netapp-ontap/issues/28)) +* **New Data Source:** `netapp-ontap_protocols_cifs_shares_data_source` ([#28](https://github.com/NetApp/terraform-provider-netapp-ontap/issues/28)) * **New Data Source:** `netapp-ontap_protocols_san_lun-map_data_source` ([#14](https://github.com/NetApp/terraform-provider-netapp-ontap/issues/14)) * **New Data Source:** `netapp-ontap_protocols_san_lun-maps_data_source` ([#14](https://github.com/NetApp/terraform-provider-netapp-ontap/issues/14)) * **New Resource:** `netapp-ontap_protocols_cifs_local_group_resource` ([#53](https://github.com/NetApp/terraform-provider-netapp-ontap/issues/53)) @@ -28,6 +32,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_storage_flexcache_resource` ([#46](https://github.com/NetApp/terraform-provider-netapp-ontap/issues/46)) +* **New Resource:** `netapp-protocols_san_lun-maps_resource` ([#13](https://github.com/NetApp/terraform-provider-netapp-ontap/issues/13)) * **New Resource:** `netapp-ontap_protocols_san_lun-maps_resource` ([#13](https://github.com/NetApp/terraform-provider-netapp-ontap/issues/13)) * **New Resource:** `netapp-ontap_name_services_ldap_resource` ([#25](https://github.com/NetApp/terraform-provider-netapp-ontap/issues/25)) * **New Resource:** `netapp-ontap_protocols_cifs_service_resource` ([#23](https://github.com/NetApp/terraform-provider-netapp-ontap/issues/23))