From 45158fbd4ada77fe98f7447b036e128c1ea72234 Mon Sep 17 00:00:00 2001 From: wenjun shen Date: Wed, 24 Jul 2024 15:28:45 -0700 Subject: [PATCH 1/5] fix set acl error. --- CHANGELOG.md | 6 + internal/interfaces/protocols_cifs_share.go | 6 +- .../interfaces/protocols_cifs_share_acl.go | 143 ++++++++++++++++++ .../provider/protocols_cifs_share_resource.go | 116 +++++++++++++- .../protocols_cifs_share_resource_test.go | 95 +++++++++++- 5 files changed, 361 insertions(+), 5 deletions(-) create mode 100644 internal/interfaces/protocols_cifs_share_acl.go diff --git a/CHANGELOG.md b/CHANGELOG.md index d9b1dea6..758c3990 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## 1.1.3 + +BUG FIXES: +* **netapp-ontap_protocols_cifs_share_resource** +`acls` unable to update acls ([#236](https://github.com/NetApp/terraform-provider-netapp-ontap/issues/236)) + ## 1.1.2 (2024-06-03) ENHANCEMENTS: diff --git a/internal/interfaces/protocols_cifs_share.go b/internal/interfaces/protocols_cifs_share.go index cf19e5c2..94ae2d01 100644 --- a/internal/interfaces/protocols_cifs_share.go +++ b/internal/interfaces/protocols_cifs_share.go @@ -159,14 +159,14 @@ func CreateProtocolsCIFSShare(errorHandler *utils.ErrorHandler, r restclient.Res // UpdateProtocolsCIFSShare to update protocols_cifs_share func UpdateProtocolsCIFSShare(errorHandler *utils.ErrorHandler, r restclient.RestClient, body ProtocolsCIFSShareResourceBodyDataModelONTAP, name string, svmUUID string) error { - api := "/protocols/cifs/shares/" + api := fmt.Sprintf("/protocols/cifs/shares/%s/%s", svmUUID, name) var bodyMap map[string]interface{} if err := mapstructure.Decode(body, &bodyMap); err != nil { return errorHandler.MakeAndReportError("error encoding protocols_cifs_share body", fmt.Sprintf("error on encoding %s body: %s, body: %#v", api, err, body)) } - statusCode, _, err := r.CallUpdateMethod(api+"/"+svmUUID+"/"+name, nil, bodyMap) + statusCode, _, err := r.CallUpdateMethod(api, nil, bodyMap) if err != nil { - return errorHandler.MakeAndReportError("error updating protocols_cifs_share", fmt.Sprintf("error on POST %s: %s, statusCode %d", api, err, statusCode)) + return errorHandler.MakeAndReportError("error updating protocols_cifs_share", fmt.Sprintf("error on PATCH %s: %s, statusCode %d", api, err, statusCode)) } return nil } diff --git a/internal/interfaces/protocols_cifs_share_acl.go b/internal/interfaces/protocols_cifs_share_acl.go new file mode 100644 index 00000000..a7daf0a5 --- /dev/null +++ b/internal/interfaces/protocols_cifs_share_acl.go @@ -0,0 +1,143 @@ +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" +) + +// ProtocolsCIFSShareAclGetDataModelONTAP describes the GET record data model using go types for mapping. +type ProtocolsCIFSShareAclGetDataModelONTAP struct { + Name string `mapstructure:"name"` + UUID string `mapstructure:"uuid"` + UserOrGroup string `mapstructure:"user_or_group"` +} + +// ProtocolsCIFSShareAclResourceBodyDataModelONTAP describes the body data model using go types for mapping. +type ProtocolsCIFSShareAclResourceBodyDataModelONTAP struct { + // Name string `mapstructure:"name"` + // SVM svm `mapstructure:"svm"` + Permission string `mapstructure:"permission"` + UserOrGroup string `mapstructure:"user_or_group"` + Type string `mapstructure:"type"` +} + +// ProtocolsCIFSShareAclDataSourceFilterModel describes the data source data model for queries. +type ProtocolsCIFSShareAclDataSourceFilterModel struct { + Name string `mapstructure:"name"` + SVMName string `mapstructure:"svm.name"` + UserOrGroup string `mapstructure:"user_or_group"` +} + +// GetProtocolsCIFSShareAclByName to get protocols_cifs_share_acl info +func GetProtocolsCIFSShareAclByName(errorHandler *utils.ErrorHandler, r restclient.RestClient, name string, svmName string) (*ProtocolsCIFSShareAclGetDataModelONTAP, error) { + api := "api_url" + query := r.NewQuery() + 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", "ip", "scope"}) + 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_acl info", fmt.Sprintf("error on GET %s: %s, statusCode %d", api, err, statusCode)) + } + + var dataONTAP ProtocolsCIFSShareAclGetDataModelONTAP + 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_acl data source: %#v", dataONTAP)) + return &dataONTAP, nil +} + +// GetProtocolsCIFSShareAcls to get protocols_cifs_share_acl info for all resources matching a filter +func GetProtocolsCIFSShareAcls(errorHandler *utils.ErrorHandler, r restclient.RestClient, filter *ProtocolsCIFSShareAclDataSourceFilterModel, svmName string, shareName string) ([]ProtocolsCIFSShareAclGetDataModelONTAP, error) { + api := fmt.Sprintf("/protocols/cifs/shares/%s/%s/acls", svmName, shareName) + query := r.NewQuery() + query.Fields([]string{"name", "svm.name", "scope"}) + if filter != nil { + var filterMap map[string]interface{} + if err := mapstructure.Decode(filter, &filterMap); err != nil { + return nil, errorHandler.MakeAndReportError("error encoding protocols_cifs_share_acls 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_share_acls info", fmt.Sprintf("error on GET %s: %s, statusCode %d", api, err, statusCode)) + } + + var dataONTAP []ProtocolsCIFSShareAclGetDataModelONTAP + for _, info := range response { + var record ProtocolsCIFSShareAclGetDataModelONTAP + 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_share_acls data source: %#v", dataONTAP)) + return dataONTAP, nil +} + +// CreateProtocolsCIFSShareAcl to create protocols_cifs_share_acl +func CreateProtocolsCIFSShareAcl(errorHandler *utils.ErrorHandler, r restclient.RestClient, body ProtocolsCIFSShareAclResourceBodyDataModelONTAP, svmID string, shareName string) (*ProtocolsCIFSShareAclGetDataModelONTAP, error) { + api := fmt.Sprintf("/protocols/cifs/shares/%s/%s/acls", svmID, shareName) + var bodyMap map[string]interface{} + if err := mapstructure.Decode(body, &bodyMap); err != nil { + return nil, errorHandler.MakeAndReportError("error encoding protocols_cifs_share_acl 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_acl", fmt.Sprintf("error on POST %s: %s, statusCode %d", api, err, statusCode)) + } + + var dataONTAP ProtocolsCIFSShareAclGetDataModelONTAP + if err := mapstructure.Decode(response.Records[0], &dataONTAP); err != nil { + return nil, errorHandler.MakeAndReportError("error decoding protocols_cifs_share_acl info", fmt.Sprintf("error on decode storage/protocols_cifs_share_acls info: %s, statusCode %d, response %#v", err, statusCode, response)) + } + tflog.Debug(errorHandler.Ctx, fmt.Sprintf("Create protocols_cifs_share_acl source - udata: %#v", dataONTAP)) + return &dataONTAP, nil +} + +// UpdateProtocolsCIFSShareAcl to update protocols_cifs_share_acl +func UpdateProtocolsCIFSShareAcl(errorHandler *utils.ErrorHandler, r restclient.RestClient, body ProtocolsCIFSShareAclResourceBodyDataModelONTAP, svmID string, shareName string, userOrGroup string, aclType string) error { + api := fmt.Sprintf("/protocols/cifs/shares/%s/%s/acls/%s/%s", svmID, shareName, userOrGroup, aclType) + var bodyMap map[string]interface{} + if err := mapstructure.Decode(body, &bodyMap); err != nil { + return errorHandler.MakeAndReportError("error encoding protocols_cifs_share_acl body", fmt.Sprintf("error on encoding %s body: %s, body: %#v", api, err, body)) + } + delete(bodyMap, "type") // type is not returned in the response + delete(bodyMap, "user_or_group") // user_or_group is not returned in the response + statusCode, _, err := r.CallUpdateMethod(api, nil, bodyMap) + if err != nil { + return errorHandler.MakeAndReportError("error creating protocols_cifs_share_acl", fmt.Sprintf("error on POST %s: %s, statusCode %d", api, err, statusCode)) + } + return nil +} + +// DeleteProtocolsCIFSShareAcl to delete protocols_cifs_share_acl +func DeleteProtocolsCIFSShareAcl(errorHandler *utils.ErrorHandler, r restclient.RestClient, svmID string, shareName string, userOrGroup string, aclType string) error { + api := fmt.Sprintf("/protocols/cifs/shares/%s/%s/acls/%s/%s", svmID, shareName, userOrGroup, aclType) + statusCode, _, err := r.CallDeleteMethod(api, nil, nil) + if err != nil { + return errorHandler.MakeAndReportError("error deleting protocols_cifs_share_acl", fmt.Sprintf("error on DELETE %s: %s, statusCode %d", api, err, statusCode)) + } + return nil +} diff --git a/internal/provider/protocols_cifs_share_resource.go b/internal/provider/protocols_cifs_share_resource.go index 21be1f6e..e6f7d5b4 100644 --- a/internal/provider/protocols_cifs_share_resource.go +++ b/internal/provider/protocols_cifs_share_resource.go @@ -432,6 +432,7 @@ func (r *ProtocolsCIFSShareResource) Create(ctx context.Context, req resource.Cr body.SVM.Name = data.SVMName.ValueString() body.Path = data.Path.ValueString() + configHasDefaultAcl := false if !data.Acls.IsUnknown() { aclsList := []interfaces.Acls{} elements := make([]types.Object, 0, len(data.Acls.Elements())) @@ -451,7 +452,9 @@ func (r *ProtocolsCIFSShareResource) Create(ctx context.Context, req resource.Cr interfacesAcls.Permission = acls.Permission interfacesAcls.Type = acls.Type interfacesAcls.UserOrGroup = acls.UserOrGroup - + if acls.UserOrGroup == "Everyone" && acls.Permission == "full_control" { + configHasDefaultAcl = true + } aclsList = append(aclsList, interfacesAcls) } body.Acls = aclsList @@ -553,6 +556,20 @@ func (r *ProtocolsCIFSShareResource) Create(ctx context.Context, req resource.Cr data.Acls = setValue } else { for _, acls := range restInfo.Acls { + //If the config file does not have acl set user_or_group as "Everyone / Full Control", the API will create one by default. Need to delete it if user does not want one. + if acls.UserOrGroup == "Everyone" && acls.Permission == "full_control" && !configHasDefaultAcl { + svm, err := interfaces.GetSvmByName(errorHandler, *client, data.SVMName.ValueString()) + if err != nil { + return + } + err = interfaces.DeleteProtocolsCIFSShareAcl(errorHandler, *client, svm.UUID, data.Name.ValueString(), acls.UserOrGroup, acls.Type) + if err != nil { + // error reporting done inside DeleteProtocolsCIFSShareAcl + return + } + continue + } + elementType := map[string]attr.Type{ "permission": types.StringType, "type": types.StringType, @@ -696,6 +713,103 @@ func (r *ProtocolsCIFSShareResource) Update(ctx context.Context, req resource.Up return } + // have no luck updating acls using PATCH cifs/shares API sucessfully, so we have to use the acls set of API. + if !plan.Acls.IsUnknown() { + // reading acls from plan + planeAcls := make([]types.Object, 0, len(plan.Acls.Elements())) + diags := plan.Acls.ElementsAs(ctx, &planeAcls, false) + if diags.HasError() { + resp.Diagnostics.Append(diags...) + return + } + // reading acls from state + stateAcls := make([]types.Object, 0, len(state.Acls.Elements())) + diags = state.Acls.ElementsAs(ctx, &stateAcls, false) + if diags.HasError() { + resp.Diagnostics.Append(diags...) + return + } + // iterate over plan acls and compare with state acls. Make create or update or delete calls accordingly. + for _, element := range stateAcls { + var stateAclElement ProtocolsCIFSShareResourceAcls + diags := element.As(ctx, &stateAclElement, basetypes.ObjectAsOptions{}) + if diags.HasError() { + resp.Diagnostics.Append(diags...) + return + } + for index, planAcl := range planeAcls { + var planAclElement ProtocolsCIFSShareResourceAcls + diags := planAcl.As(ctx, &planAclElement, basetypes.ObjectAsOptions{}) + if diags.HasError() { + resp.Diagnostics.Append(diags...) + return + } + // if 'userOrGroup' and 'type' matches, then we know it's not a create action. If permission is same, then break the loop because nothing to update. + if stateAclElement.UserOrGroup == planAclElement.UserOrGroup && stateAclElement.Type == planAclElement.Type { + if stateAclElement.Permission == planAclElement.Permission { + break + } else { + // update the acls since permission is different + interfacesAcls := interfaces.ProtocolsCIFSShareAclResourceBodyDataModelONTAP{} + interfacesAcls.Permission = stateAclElement.Permission + err = interfaces.UpdateProtocolsCIFSShareAcl(errorHandler, *client, interfacesAcls, svm.UUID, plan.Name.ValueString(), stateAclElement.UserOrGroup, stateAclElement.Type) + if err != nil { + return + } + } + } + // if we reach the end of stateAcls, then we know it's a delete action because it was not found in plan acls. + if index == len(planeAcls)-1 { + err = interfaces.DeleteProtocolsCIFSShareAcl(errorHandler, *client, svm.UUID, plan.Name.ValueString(), stateAclElement.UserOrGroup, stateAclElement.Type) + if err != nil { + return + } + + } + } + + } + // now handle create action + for _, planAcl := range planeAcls { + var planAclElement ProtocolsCIFSShareResourceAcls + diags := planAcl.As(ctx, &planAclElement, basetypes.ObjectAsOptions{}) + if diags.HasError() { + resp.Diagnostics.Append(diags...) + return + } + + for index, element := range stateAcls { + var stateAclElement ProtocolsCIFSShareResourceAcls + diags := element.As(ctx, &stateAclElement, basetypes.ObjectAsOptions{}) + if diags.HasError() { + resp.Diagnostics.Append(diags...) + return + } + if stateAclElement.UserOrGroup == planAclElement.UserOrGroup && stateAclElement.Type == planAclElement.Type { + if stateAclElement.Permission == planAclElement.Permission { + break + } else { + // update is already handled by above logic, so continue + continue + } + } + // if we reach the end of planAcls, then we know it's a create action because it was not found in state acls. + if index == len(stateAcls)-1 { + interfacesAcls := interfaces.ProtocolsCIFSShareAclResourceBodyDataModelONTAP{} + interfacesAcls.Permission = planAclElement.Permission + interfacesAcls.Type = planAclElement.Type + interfacesAcls.UserOrGroup = planAclElement.UserOrGroup + _, err = interfaces.CreateProtocolsCIFSShareAcl(errorHandler, *client, interfacesAcls, svm.UUID, plan.Name.ValueString()) + if err != nil { + return + } + } + } + + } + + } + err = interfaces.UpdateProtocolsCIFSShare(errorHandler, *client, body, plan.Name.ValueString(), svm.UUID) if err != nil { return diff --git a/internal/provider/protocols_cifs_share_resource_test.go b/internal/provider/protocols_cifs_share_resource_test.go index af48d597..41f2c313 100644 --- a/internal/provider/protocols_cifs_share_resource_test.go +++ b/internal/provider/protocols_cifs_share_resource_test.go @@ -36,6 +36,18 @@ func TestAccProtocolsCIFSShareResource(t *testing.T) { resource.TestCheckResourceAttr("netapp-ontap_protocols_cifs_share_resource.example", "continuously_available", "true"), ), }, + { + Config: testAccProtocolsCIFSShareResourceConfigUpdateAddAcl("tfsvm", "acc_test_cifs_share"), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("netapp-ontap_protocols_cifs_share_resource.example", "name", "acc_test_cifs_share"), + ), + }, + { + Config: testAccProtocolsCIFSShareResourceConfigUpdateDeleteAcl("tfsvm", "acc_test_cifs_share"), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("netapp-ontap_protocols_cifs_share_resource.example", "name", "acc_test_cifs_share"), + ), + }, // Test importing a resource { ResourceName: "netapp-ontap_protocols_cifs_share_resource.example", @@ -80,7 +92,7 @@ resource "netapp-ontap_protocols_cifs_share_resource" "example" { { "permission": "read", "type": "windows", - "user_or_group": "Everyone" + "user_or_group": "BUILTIN\\Administrators" } ] comment = "this is a comment" @@ -108,6 +120,87 @@ provider "netapp-ontap" { ] } +resource "netapp-ontap_protocols_cifs_share_resource" "example" { + cx_profile_name = "clustercifs" + name = "%s" + svm_name = "%s" + path = "/acc_test_cifs_share_volume" + acls = [ + { + "permission": "full_control", + "type": "windows", + "user_or_group": "BUILTIN\\Administrators" + } + ] + comment = "update comment" + continuously_available = true +}`, host, admin, password, volName, svm) +} + +func testAccProtocolsCIFSShareResourceConfigUpdateAddAcl(svm, volName string) string { + host := os.Getenv("TF_ACC_NETAPP_HOST_CIFS") + admin := os.Getenv("TF_ACC_NETAPP_USER") + password := os.Getenv("TF_ACC_NETAPP_PASS2") + if host == "" || admin == "" || password == "" { + fmt.Println("TF_ACC_NETAPP_HOST_CIFS, TF_ACC_NETAPP_USER, and TF_ACC_NETAPP_PASS2 must be set for acceptance tests") + os.Exit(1) + } + return fmt.Sprintf(` +provider "netapp-ontap" { + connection_profiles = [ + { + name = "clustercifs" + hostname = "%s" + username = "%s" + password = "%s" + validate_certs = false + }, + ] +} + +resource "netapp-ontap_protocols_cifs_share_resource" "example" { + cx_profile_name = "clustercifs" + name = "%s" + svm_name = "%s" + path = "/acc_test_cifs_share_volume" + acls = [ + { + "permission": "read", + "type": "windows", + "user_or_group": "Everyone" + }, + { + "permission": "full_control", + "type": "windows", + "user_or_group": "BUILTIN\\Administrators" + } + ] + comment = "update comment" + continuously_available = true +}`, host, admin, password, volName, svm) +} + +func testAccProtocolsCIFSShareResourceConfigUpdateDeleteAcl(svm, volName string) string { + host := os.Getenv("TF_ACC_NETAPP_HOST_CIFS") + admin := os.Getenv("TF_ACC_NETAPP_USER") + password := os.Getenv("TF_ACC_NETAPP_PASS2") + if host == "" || admin == "" || password == "" { + fmt.Println("TF_ACC_NETAPP_HOST_CIFS, TF_ACC_NETAPP_USER, and TF_ACC_NETAPP_PASS2 must be set for acceptance tests") + os.Exit(1) + } + return fmt.Sprintf(` +provider "netapp-ontap" { + connection_profiles = [ + { + name = "clustercifs" + hostname = "%s" + username = "%s" + password = "%s" + validate_certs = false + }, + ] +} + resource "netapp-ontap_protocols_cifs_share_resource" "example" { cx_profile_name = "clustercifs" name = "%s" From e009d166b839424888c44b0fd333e32494d35a52 Mon Sep 17 00:00:00 2001 From: wenjun shen Date: Wed, 24 Jul 2024 17:11:14 -0700 Subject: [PATCH 2/5] fix acc test. --- internal/interfaces/protocols_cifs_share.go | 20 +++++++++---------- .../interfaces/protocols_cifs_share_acl.go | 2 +- .../provider/protocols_cifs_share_resource.go | 15 ++++++++++---- 3 files changed, 22 insertions(+), 15 deletions(-) diff --git a/internal/interfaces/protocols_cifs_share.go b/internal/interfaces/protocols_cifs_share.go index 94ae2d01..4892d69c 100644 --- a/internal/interfaces/protocols_cifs_share.go +++ b/internal/interfaces/protocols_cifs_share.go @@ -52,20 +52,20 @@ type ProtocolsCIFSShareResourceBodyDataModelONTAP struct { Name string `mapstructure:"name,omitempty"` // can't be present in update, so omit empty. SVM svm `mapstructure:"svm"` Acls []Acls `mapstructure:"acls,omitempty"` // API complains if this is not omit empty - ChangeNotify bool `mapstructure:"change_notify"` + ChangeNotify bool `mapstructure:"change_notify,omitempty"` Comment string `mapstructure:"comment,omitempty"` // API complains if this is not omit empty - 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"` + ContinuouslyAvailable bool `mapstructure:"continuously_available,omitempty"` + DirUmask int64 `mapstructure:"dir_umask,omitempty"` + Encryption bool `mapstructure:"encryption,omitempty"` + FileUmask int64 `mapstructure:"file_umask,omitempty"` + ForceGroupForCreate string `mapstructure:"force_group_for_create,omitempty"` HomeDirectory bool `mapstructure:"home_directory,omitempty"` // can't be present in update, so omit empty. - NamespaceCaching bool `mapstructure:"namespace_caching"` - NoStrictSecurity bool `mapstructure:"no_strict_security"` + NamespaceCaching bool `mapstructure:"namespace_caching,omitempty"` + NoStrictSecurity bool `mapstructure:"no_strict_security,omitempty"` OfflineFiles string `mapstructure:"offline_files,omitempty"` // API complains if this is not omit empty - Oplocks bool `mapstructure:"oplocks"` + Oplocks bool `mapstructure:"oplocks,omitempty"` Path string `mapstructure:"path,omitempty"` // can't be present in update, so omit empty. - ShowSnapshot bool `mapstructure:"show_snapshot"` + ShowSnapshot bool `mapstructure:"show_snapshot,omitempty"` UnixSymlink string `mapstructure:"unix_symlink,omitempty"` // API complains if this is not omit empty VscanProfile string `mapstructure:"vscan_profile,omitempty"` // API complains if this is not omit empty } diff --git a/internal/interfaces/protocols_cifs_share_acl.go b/internal/interfaces/protocols_cifs_share_acl.go index a7daf0a5..363655e2 100644 --- a/internal/interfaces/protocols_cifs_share_acl.go +++ b/internal/interfaces/protocols_cifs_share_acl.go @@ -127,7 +127,7 @@ func UpdateProtocolsCIFSShareAcl(errorHandler *utils.ErrorHandler, r restclient. delete(bodyMap, "user_or_group") // user_or_group is not returned in the response statusCode, _, err := r.CallUpdateMethod(api, nil, bodyMap) if err != nil { - return errorHandler.MakeAndReportError("error creating protocols_cifs_share_acl", fmt.Sprintf("error on POST %s: %s, statusCode %d", api, err, statusCode)) + return errorHandler.MakeAndReportError("error updating protocols_cifs_share_acl", fmt.Sprintf("error on PATCH %s: %s, statusCode %d", api, err, statusCode)) } return nil } diff --git a/internal/provider/protocols_cifs_share_resource.go b/internal/provider/protocols_cifs_share_resource.go index e6f7d5b4..15d4cade 100644 --- a/internal/provider/protocols_cifs_share_resource.go +++ b/internal/provider/protocols_cifs_share_resource.go @@ -708,6 +708,12 @@ func (r *ProtocolsCIFSShareResource) Update(ctx context.Context, req resource.Up } } + if !plan.ContinuouslyAvailable.IsUnknown() { + if plan.ContinuouslyAvailable != state.ContinuouslyAvailable { + body.ContinuouslyAvailable = plan.ContinuouslyAvailable.ValueBool() + } + } + svm, err := interfaces.GetSvmByName(errorHandler, *client, plan.SVMName.ValueString()) if err != nil { return @@ -751,11 +757,12 @@ func (r *ProtocolsCIFSShareResource) Update(ctx context.Context, req resource.Up } else { // update the acls since permission is different interfacesAcls := interfaces.ProtocolsCIFSShareAclResourceBodyDataModelONTAP{} - interfacesAcls.Permission = stateAclElement.Permission - err = interfaces.UpdateProtocolsCIFSShareAcl(errorHandler, *client, interfacesAcls, svm.UUID, plan.Name.ValueString(), stateAclElement.UserOrGroup, stateAclElement.Type) + interfacesAcls.Permission = planAclElement.Permission + err = interfaces.UpdateProtocolsCIFSShareAcl(errorHandler, *client, interfacesAcls, svm.UUID, plan.Name.ValueString(), planAclElement.UserOrGroup, planAclElement.Type) if err != nil { return } + break } } // if we reach the end of stateAcls, then we know it's a delete action because it was not found in plan acls. @@ -789,8 +796,8 @@ func (r *ProtocolsCIFSShareResource) Update(ctx context.Context, req resource.Up if stateAclElement.Permission == planAclElement.Permission { break } else { - // update is already handled by above logic, so continue - continue + // update is already handled by above logic, so break + break } } // if we reach the end of planAcls, then we know it's a create action because it was not found in state acls. From 4f23cbc68af3bdcab924eaf0b3811c38e09cda7e Mon Sep 17 00:00:00 2001 From: wenjun shen Date: Wed, 24 Jul 2024 20:49:09 -0700 Subject: [PATCH 3/5] Fix build. --- .../interfaces/protocols_cifs_share_acl.go | 38 +++++++-------- .../provider/protocols_cifs_share_resource.go | 44 +++++++++--------- .../protocols_cifs_share_resource_test.go | 46 ++++++++++++------- 3 files changed, 71 insertions(+), 57 deletions(-) diff --git a/internal/interfaces/protocols_cifs_share_acl.go b/internal/interfaces/protocols_cifs_share_acl.go index 363655e2..4d4eeeda 100644 --- a/internal/interfaces/protocols_cifs_share_acl.go +++ b/internal/interfaces/protocols_cifs_share_acl.go @@ -9,15 +9,15 @@ import ( "github.com/netapp/terraform-provider-netapp-ontap/internal/utils" ) -// ProtocolsCIFSShareAclGetDataModelONTAP describes the GET record data model using go types for mapping. -type ProtocolsCIFSShareAclGetDataModelONTAP struct { +// ProtocolsCIFSShareACLGetDataModelONTAP describes the GET record data model using go types for mapping. +type ProtocolsCIFSShareACLGetDataModelONTAP struct { Name string `mapstructure:"name"` UUID string `mapstructure:"uuid"` UserOrGroup string `mapstructure:"user_or_group"` } -// ProtocolsCIFSShareAclResourceBodyDataModelONTAP describes the body data model using go types for mapping. -type ProtocolsCIFSShareAclResourceBodyDataModelONTAP struct { +// ProtocolsCIFSShareACLResourceBodyDataModelONTAP describes the body data model using go types for mapping. +type ProtocolsCIFSShareACLResourceBodyDataModelONTAP struct { // Name string `mapstructure:"name"` // SVM svm `mapstructure:"svm"` Permission string `mapstructure:"permission"` @@ -25,15 +25,15 @@ type ProtocolsCIFSShareAclResourceBodyDataModelONTAP struct { Type string `mapstructure:"type"` } -// ProtocolsCIFSShareAclDataSourceFilterModel describes the data source data model for queries. -type ProtocolsCIFSShareAclDataSourceFilterModel struct { +// ProtocolsCIFSShareACLDataSourceFilterModel describes the data source data model for queries. +type ProtocolsCIFSShareACLDataSourceFilterModel struct { Name string `mapstructure:"name"` SVMName string `mapstructure:"svm.name"` UserOrGroup string `mapstructure:"user_or_group"` } -// GetProtocolsCIFSShareAclByName to get protocols_cifs_share_acl info -func GetProtocolsCIFSShareAclByName(errorHandler *utils.ErrorHandler, r restclient.RestClient, name string, svmName string) (*ProtocolsCIFSShareAclGetDataModelONTAP, error) { +// GetProtocolsCIFSShareACLByName to get protocols_cifs_share_acl info +func GetProtocolsCIFSShareACLByName(errorHandler *utils.ErrorHandler, r restclient.RestClient, name string, svmName string) (*ProtocolsCIFSShareACLGetDataModelONTAP, error) { api := "api_url" query := r.NewQuery() query.Set("name", name) @@ -52,7 +52,7 @@ func GetProtocolsCIFSShareAclByName(errorHandler *utils.ErrorHandler, r restclie return nil, errorHandler.MakeAndReportError("error reading protocols_cifs_share_acl info", fmt.Sprintf("error on GET %s: %s, statusCode %d", api, err, statusCode)) } - var dataONTAP ProtocolsCIFSShareAclGetDataModelONTAP + var dataONTAP ProtocolsCIFSShareACLGetDataModelONTAP 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)) @@ -62,7 +62,7 @@ func GetProtocolsCIFSShareAclByName(errorHandler *utils.ErrorHandler, r restclie } // GetProtocolsCIFSShareAcls to get protocols_cifs_share_acl info for all resources matching a filter -func GetProtocolsCIFSShareAcls(errorHandler *utils.ErrorHandler, r restclient.RestClient, filter *ProtocolsCIFSShareAclDataSourceFilterModel, svmName string, shareName string) ([]ProtocolsCIFSShareAclGetDataModelONTAP, error) { +func GetProtocolsCIFSShareAcls(errorHandler *utils.ErrorHandler, r restclient.RestClient, filter *ProtocolsCIFSShareACLDataSourceFilterModel, svmName string, shareName string) ([]ProtocolsCIFSShareACLGetDataModelONTAP, error) { api := fmt.Sprintf("/protocols/cifs/shares/%s/%s/acls", svmName, shareName) query := r.NewQuery() query.Fields([]string{"name", "svm.name", "scope"}) @@ -81,9 +81,9 @@ func GetProtocolsCIFSShareAcls(errorHandler *utils.ErrorHandler, r restclient.Re return nil, errorHandler.MakeAndReportError("error reading protocols_cifs_share_acls info", fmt.Sprintf("error on GET %s: %s, statusCode %d", api, err, statusCode)) } - var dataONTAP []ProtocolsCIFSShareAclGetDataModelONTAP + var dataONTAP []ProtocolsCIFSShareACLGetDataModelONTAP for _, info := range response { - var record ProtocolsCIFSShareAclGetDataModelONTAP + var record ProtocolsCIFSShareACLGetDataModelONTAP 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)) @@ -94,8 +94,8 @@ func GetProtocolsCIFSShareAcls(errorHandler *utils.ErrorHandler, r restclient.Re return dataONTAP, nil } -// CreateProtocolsCIFSShareAcl to create protocols_cifs_share_acl -func CreateProtocolsCIFSShareAcl(errorHandler *utils.ErrorHandler, r restclient.RestClient, body ProtocolsCIFSShareAclResourceBodyDataModelONTAP, svmID string, shareName string) (*ProtocolsCIFSShareAclGetDataModelONTAP, error) { +// CreateProtocolsCIFSShareACL to create protocols_cifs_share_acl +func CreateProtocolsCIFSShareACL(errorHandler *utils.ErrorHandler, r restclient.RestClient, body ProtocolsCIFSShareACLResourceBodyDataModelONTAP, svmID string, shareName string) (*ProtocolsCIFSShareACLGetDataModelONTAP, error) { api := fmt.Sprintf("/protocols/cifs/shares/%s/%s/acls", svmID, shareName) var bodyMap map[string]interface{} if err := mapstructure.Decode(body, &bodyMap); err != nil { @@ -108,7 +108,7 @@ func CreateProtocolsCIFSShareAcl(errorHandler *utils.ErrorHandler, r restclient. return nil, errorHandler.MakeAndReportError("error creating protocols_cifs_share_acl", fmt.Sprintf("error on POST %s: %s, statusCode %d", api, err, statusCode)) } - var dataONTAP ProtocolsCIFSShareAclGetDataModelONTAP + var dataONTAP ProtocolsCIFSShareACLGetDataModelONTAP if err := mapstructure.Decode(response.Records[0], &dataONTAP); err != nil { return nil, errorHandler.MakeAndReportError("error decoding protocols_cifs_share_acl info", fmt.Sprintf("error on decode storage/protocols_cifs_share_acls info: %s, statusCode %d, response %#v", err, statusCode, response)) } @@ -116,8 +116,8 @@ func CreateProtocolsCIFSShareAcl(errorHandler *utils.ErrorHandler, r restclient. return &dataONTAP, nil } -// UpdateProtocolsCIFSShareAcl to update protocols_cifs_share_acl -func UpdateProtocolsCIFSShareAcl(errorHandler *utils.ErrorHandler, r restclient.RestClient, body ProtocolsCIFSShareAclResourceBodyDataModelONTAP, svmID string, shareName string, userOrGroup string, aclType string) error { +// UpdateProtocolsCIFSShareACL to update protocols_cifs_share_acl +func UpdateProtocolsCIFSShareACL(errorHandler *utils.ErrorHandler, r restclient.RestClient, body ProtocolsCIFSShareACLResourceBodyDataModelONTAP, svmID string, shareName string, userOrGroup string, aclType string) error { api := fmt.Sprintf("/protocols/cifs/shares/%s/%s/acls/%s/%s", svmID, shareName, userOrGroup, aclType) var bodyMap map[string]interface{} if err := mapstructure.Decode(body, &bodyMap); err != nil { @@ -132,8 +132,8 @@ func UpdateProtocolsCIFSShareAcl(errorHandler *utils.ErrorHandler, r restclient. return nil } -// DeleteProtocolsCIFSShareAcl to delete protocols_cifs_share_acl -func DeleteProtocolsCIFSShareAcl(errorHandler *utils.ErrorHandler, r restclient.RestClient, svmID string, shareName string, userOrGroup string, aclType string) error { +// DeleteProtocolsCIFSShareACL to delete protocols_cifs_share_acl +func DeleteProtocolsCIFSShareACL(errorHandler *utils.ErrorHandler, r restclient.RestClient, svmID string, shareName string, userOrGroup string, aclType string) error { api := fmt.Sprintf("/protocols/cifs/shares/%s/%s/acls/%s/%s", svmID, shareName, userOrGroup, aclType) statusCode, _, err := r.CallDeleteMethod(api, nil, nil) if err != nil { diff --git a/internal/provider/protocols_cifs_share_resource.go b/internal/provider/protocols_cifs_share_resource.go index 15d4cade..65edba8b 100644 --- a/internal/provider/protocols_cifs_share_resource.go +++ b/internal/provider/protocols_cifs_share_resource.go @@ -562,7 +562,7 @@ func (r *ProtocolsCIFSShareResource) Create(ctx context.Context, req resource.Cr if err != nil { return } - err = interfaces.DeleteProtocolsCIFSShareAcl(errorHandler, *client, svm.UUID, data.Name.ValueString(), acls.UserOrGroup, acls.Type) + err = interfaces.DeleteProtocolsCIFSShareACL(errorHandler, *client, svm.UUID, data.Name.ValueString(), acls.UserOrGroup, acls.Type) if err != nil { // error reporting done inside DeleteProtocolsCIFSShareAcl return @@ -737,28 +737,28 @@ func (r *ProtocolsCIFSShareResource) Update(ctx context.Context, req resource.Up } // iterate over plan acls and compare with state acls. Make create or update or delete calls accordingly. for _, element := range stateAcls { - var stateAclElement ProtocolsCIFSShareResourceAcls - diags := element.As(ctx, &stateAclElement, basetypes.ObjectAsOptions{}) + var stateACLElement ProtocolsCIFSShareResourceAcls + diags := element.As(ctx, &stateACLElement, basetypes.ObjectAsOptions{}) if diags.HasError() { resp.Diagnostics.Append(diags...) return } - for index, planAcl := range planeAcls { + for index, planACL := range planeAcls { var planAclElement ProtocolsCIFSShareResourceAcls - diags := planAcl.As(ctx, &planAclElement, basetypes.ObjectAsOptions{}) + diags := planACL.As(ctx, &planAclElement, basetypes.ObjectAsOptions{}) if diags.HasError() { resp.Diagnostics.Append(diags...) return } // if 'userOrGroup' and 'type' matches, then we know it's not a create action. If permission is same, then break the loop because nothing to update. - if stateAclElement.UserOrGroup == planAclElement.UserOrGroup && stateAclElement.Type == planAclElement.Type { - if stateAclElement.Permission == planAclElement.Permission { + if stateACLElement.UserOrGroup == planAclElement.UserOrGroup && stateACLElement.Type == planAclElement.Type { + if stateACLElement.Permission == planAclElement.Permission { break } else { // update the acls since permission is different - interfacesAcls := interfaces.ProtocolsCIFSShareAclResourceBodyDataModelONTAP{} + interfacesAcls := interfaces.ProtocolsCIFSShareACLResourceBodyDataModelONTAP{} interfacesAcls.Permission = planAclElement.Permission - err = interfaces.UpdateProtocolsCIFSShareAcl(errorHandler, *client, interfacesAcls, svm.UUID, plan.Name.ValueString(), planAclElement.UserOrGroup, planAclElement.Type) + err = interfaces.UpdateProtocolsCIFSShareACL(errorHandler, *client, interfacesAcls, svm.UUID, plan.Name.ValueString(), planAclElement.UserOrGroup, planAclElement.Type) if err != nil { return } @@ -767,7 +767,7 @@ func (r *ProtocolsCIFSShareResource) Update(ctx context.Context, req resource.Up } // if we reach the end of stateAcls, then we know it's a delete action because it was not found in plan acls. if index == len(planeAcls)-1 { - err = interfaces.DeleteProtocolsCIFSShareAcl(errorHandler, *client, svm.UUID, plan.Name.ValueString(), stateAclElement.UserOrGroup, stateAclElement.Type) + err = interfaces.DeleteProtocolsCIFSShareACL(errorHandler, *client, svm.UUID, plan.Name.ValueString(), stateACLElement.UserOrGroup, stateACLElement.Type) if err != nil { return } @@ -777,23 +777,23 @@ func (r *ProtocolsCIFSShareResource) Update(ctx context.Context, req resource.Up } // now handle create action - for _, planAcl := range planeAcls { - var planAclElement ProtocolsCIFSShareResourceAcls - diags := planAcl.As(ctx, &planAclElement, basetypes.ObjectAsOptions{}) + for _, planACL := range planeAcls { + var planACLElement ProtocolsCIFSShareResourceAcls + diags := planACL.As(ctx, &planACLElement, basetypes.ObjectAsOptions{}) if diags.HasError() { resp.Diagnostics.Append(diags...) return } for index, element := range stateAcls { - var stateAclElement ProtocolsCIFSShareResourceAcls - diags := element.As(ctx, &stateAclElement, basetypes.ObjectAsOptions{}) + var stateACLElement ProtocolsCIFSShareResourceAcls + diags := element.As(ctx, &stateACLElement, basetypes.ObjectAsOptions{}) if diags.HasError() { resp.Diagnostics.Append(diags...) return } - if stateAclElement.UserOrGroup == planAclElement.UserOrGroup && stateAclElement.Type == planAclElement.Type { - if stateAclElement.Permission == planAclElement.Permission { + if stateACLElement.UserOrGroup == planACLElement.UserOrGroup && stateACLElement.Type == planACLElement.Type { + if stateACLElement.Permission == planACLElement.Permission { break } else { // update is already handled by above logic, so break @@ -802,11 +802,11 @@ func (r *ProtocolsCIFSShareResource) Update(ctx context.Context, req resource.Up } // if we reach the end of planAcls, then we know it's a create action because it was not found in state acls. if index == len(stateAcls)-1 { - interfacesAcls := interfaces.ProtocolsCIFSShareAclResourceBodyDataModelONTAP{} - interfacesAcls.Permission = planAclElement.Permission - interfacesAcls.Type = planAclElement.Type - interfacesAcls.UserOrGroup = planAclElement.UserOrGroup - _, err = interfaces.CreateProtocolsCIFSShareAcl(errorHandler, *client, interfacesAcls, svm.UUID, plan.Name.ValueString()) + interfacesAcls := interfaces.ProtocolsCIFSShareACLResourceBodyDataModelONTAP{} + interfacesAcls.Permission = planACLElement.Permission + interfacesAcls.Type = planACLElement.Type + interfacesAcls.UserOrGroup = planACLElement.UserOrGroup + _, err = interfaces.CreateProtocolsCIFSShareACL(errorHandler, *client, interfacesAcls, svm.UUID, plan.Name.ValueString()) if err != nil { return } diff --git a/internal/provider/protocols_cifs_share_resource_test.go b/internal/provider/protocols_cifs_share_resource_test.go index 41f2c313..19bf8433 100644 --- a/internal/provider/protocols_cifs_share_resource_test.go +++ b/internal/provider/protocols_cifs_share_resource_test.go @@ -37,13 +37,13 @@ func TestAccProtocolsCIFSShareResource(t *testing.T) { ), }, { - Config: testAccProtocolsCIFSShareResourceConfigUpdateAddAcl("tfsvm", "acc_test_cifs_share"), + Config: testAccProtocolsCIFSShareResourceConfigUpdateAddACL("tfsvm", "acc_test_cifs_share"), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("netapp-ontap_protocols_cifs_share_resource.example", "name", "acc_test_cifs_share"), ), }, { - Config: testAccProtocolsCIFSShareResourceConfigUpdateDeleteAcl("tfsvm", "acc_test_cifs_share"), + Config: testAccProtocolsCIFSShareResourceConfigUpdateDeleteACL("tfsvm", "acc_test_cifs_share"), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("netapp-ontap_protocols_cifs_share_resource.example", "name", "acc_test_cifs_share"), ), @@ -62,9 +62,12 @@ func TestAccProtocolsCIFSShareResource(t *testing.T) { } func testAccProtocolsCIFSShareResourceConfig(svm, shareName string) string { - host := os.Getenv("TF_ACC_NETAPP_HOST_CIFS") - admin := os.Getenv("TF_ACC_NETAPP_USER") - password := os.Getenv("TF_ACC_NETAPP_PASS2") + // host := os.Getenv("TF_ACC_NETAPP_HOST_CIFS") + // admin := os.Getenv("TF_ACC_NETAPP_USER") + // password := os.Getenv("TF_ACC_NETAPP_PASS2") + host := "10.193.73.2" + admin := "admin" + password := "Netapp1!" if host == "" || admin == "" || password == "" { fmt.Println("TF_ACC_NETAPP_HOST_CIFS, TF_ACC_NETAPP_USER, and TF_ACC_NETAPP_PASS2 must be set for acceptance tests") @@ -100,9 +103,13 @@ resource "netapp-ontap_protocols_cifs_share_resource" "example" { } func testAccProtocolsCIFSShareResourceConfigUpdate(svm, volName string) string { - host := os.Getenv("TF_ACC_NETAPP_HOST_CIFS") - admin := os.Getenv("TF_ACC_NETAPP_USER") - password := os.Getenv("TF_ACC_NETAPP_PASS2") + // host := os.Getenv("TF_ACC_NETAPP_HOST_CIFS") + // admin := os.Getenv("TF_ACC_NETAPP_USER") + // password := os.Getenv("TF_ACC_NETAPP_PASS2") + host := "10.193.73.2" + admin := "admin" + password := "Netapp1!" + if host == "" || admin == "" || password == "" { fmt.Println("TF_ACC_NETAPP_HOST_CIFS, TF_ACC_NETAPP_USER, and TF_ACC_NETAPP_PASS2 must be set for acceptance tests") os.Exit(1) @@ -137,10 +144,14 @@ resource "netapp-ontap_protocols_cifs_share_resource" "example" { }`, host, admin, password, volName, svm) } -func testAccProtocolsCIFSShareResourceConfigUpdateAddAcl(svm, volName string) string { - host := os.Getenv("TF_ACC_NETAPP_HOST_CIFS") - admin := os.Getenv("TF_ACC_NETAPP_USER") - password := os.Getenv("TF_ACC_NETAPP_PASS2") +func testAccProtocolsCIFSShareResourceConfigUpdateAddACL(svm, volName string) string { + // host := os.Getenv("TF_ACC_NETAPP_HOST_CIFS") + // admin := os.Getenv("TF_ACC_NETAPP_USER") + // password := os.Getenv("TF_ACC_NETAPP_PASS2") + host := "10.193.73.2" + admin := "admin" + password := "Netapp1!" + if host == "" || admin == "" || password == "" { fmt.Println("TF_ACC_NETAPP_HOST_CIFS, TF_ACC_NETAPP_USER, and TF_ACC_NETAPP_PASS2 must be set for acceptance tests") os.Exit(1) @@ -180,10 +191,13 @@ resource "netapp-ontap_protocols_cifs_share_resource" "example" { }`, host, admin, password, volName, svm) } -func testAccProtocolsCIFSShareResourceConfigUpdateDeleteAcl(svm, volName string) string { - host := os.Getenv("TF_ACC_NETAPP_HOST_CIFS") - admin := os.Getenv("TF_ACC_NETAPP_USER") - password := os.Getenv("TF_ACC_NETAPP_PASS2") +func testAccProtocolsCIFSShareResourceConfigUpdateDeleteACL(svm, volName string) string { + // host := os.Getenv("TF_ACC_NETAPP_HOST_CIFS") + // admin := os.Getenv("TF_ACC_NETAPP_USER") + // password := os.Getenv("TF_ACC_NETAPP_PASS2") + host := "10.193.73.2" + admin := "admin" + password := "Netapp1!" if host == "" || admin == "" || password == "" { fmt.Println("TF_ACC_NETAPP_HOST_CIFS, TF_ACC_NETAPP_USER, and TF_ACC_NETAPP_PASS2 must be set for acceptance tests") os.Exit(1) From 78ab2330141d97c02c7e7a0ef4d7fc2153d5623d Mon Sep 17 00:00:00 2001 From: wenjun shen Date: Fri, 2 Aug 2024 12:28:41 -0700 Subject: [PATCH 4/5] Fix Lint. --- .../provider/protocols_cifs_share_resource.go | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/internal/provider/protocols_cifs_share_resource.go b/internal/provider/protocols_cifs_share_resource.go index 65edba8b..d0aa185c 100644 --- a/internal/provider/protocols_cifs_share_resource.go +++ b/internal/provider/protocols_cifs_share_resource.go @@ -432,7 +432,7 @@ func (r *ProtocolsCIFSShareResource) Create(ctx context.Context, req resource.Cr body.SVM.Name = data.SVMName.ValueString() body.Path = data.Path.ValueString() - configHasDefaultAcl := false + configHasDefaultACL := false if !data.Acls.IsUnknown() { aclsList := []interfaces.Acls{} elements := make([]types.Object, 0, len(data.Acls.Elements())) @@ -453,7 +453,7 @@ func (r *ProtocolsCIFSShareResource) Create(ctx context.Context, req resource.Cr interfacesAcls.Type = acls.Type interfacesAcls.UserOrGroup = acls.UserOrGroup if acls.UserOrGroup == "Everyone" && acls.Permission == "full_control" { - configHasDefaultAcl = true + configHasDefaultACL = true } aclsList = append(aclsList, interfacesAcls) } @@ -557,7 +557,7 @@ func (r *ProtocolsCIFSShareResource) Create(ctx context.Context, req resource.Cr } else { for _, acls := range restInfo.Acls { //If the config file does not have acl set user_or_group as "Everyone / Full Control", the API will create one by default. Need to delete it if user does not want one. - if acls.UserOrGroup == "Everyone" && acls.Permission == "full_control" && !configHasDefaultAcl { + if acls.UserOrGroup == "Everyone" && acls.Permission == "full_control" && !configHasDefaultACL { svm, err := interfaces.GetSvmByName(errorHandler, *client, data.SVMName.ValueString()) if err != nil { return @@ -744,21 +744,21 @@ func (r *ProtocolsCIFSShareResource) Update(ctx context.Context, req resource.Up return } for index, planACL := range planeAcls { - var planAclElement ProtocolsCIFSShareResourceAcls - diags := planACL.As(ctx, &planAclElement, basetypes.ObjectAsOptions{}) + var planACLElement ProtocolsCIFSShareResourceAcls + diags := planACL.As(ctx, &planACLElement, basetypes.ObjectAsOptions{}) if diags.HasError() { resp.Diagnostics.Append(diags...) return } // if 'userOrGroup' and 'type' matches, then we know it's not a create action. If permission is same, then break the loop because nothing to update. - if stateACLElement.UserOrGroup == planAclElement.UserOrGroup && stateACLElement.Type == planAclElement.Type { - if stateACLElement.Permission == planAclElement.Permission { + if stateACLElement.UserOrGroup == planACLElement.UserOrGroup && stateACLElement.Type == planACLElement.Type { + if stateACLElement.Permission == planACLElement.Permission { break } else { // update the acls since permission is different interfacesAcls := interfaces.ProtocolsCIFSShareACLResourceBodyDataModelONTAP{} - interfacesAcls.Permission = planAclElement.Permission - err = interfaces.UpdateProtocolsCIFSShareACL(errorHandler, *client, interfacesAcls, svm.UUID, plan.Name.ValueString(), planAclElement.UserOrGroup, planAclElement.Type) + interfacesAcls.Permission = planACLElement.Permission + err = interfaces.UpdateProtocolsCIFSShareACL(errorHandler, *client, interfacesAcls, svm.UUID, plan.Name.ValueString(), planACLElement.UserOrGroup, planACLElement.Type) if err != nil { return } From 1f2b5914e739582250e83cf093cebb78ed956e1a Mon Sep 17 00:00:00 2001 From: wenjun shen Date: Tue, 6 Aug 2024 14:48:48 -0700 Subject: [PATCH 5/5] remove vsim info. --- .../protocols_cifs_share_resource_test.go | 37 +++++++------------ 1 file changed, 13 insertions(+), 24 deletions(-) diff --git a/internal/provider/protocols_cifs_share_resource_test.go b/internal/provider/protocols_cifs_share_resource_test.go index 19bf8433..465e729e 100644 --- a/internal/provider/protocols_cifs_share_resource_test.go +++ b/internal/provider/protocols_cifs_share_resource_test.go @@ -62,12 +62,9 @@ func TestAccProtocolsCIFSShareResource(t *testing.T) { } func testAccProtocolsCIFSShareResourceConfig(svm, shareName string) string { - // host := os.Getenv("TF_ACC_NETAPP_HOST_CIFS") - // admin := os.Getenv("TF_ACC_NETAPP_USER") - // password := os.Getenv("TF_ACC_NETAPP_PASS2") - host := "10.193.73.2" - admin := "admin" - password := "Netapp1!" + host := os.Getenv("TF_ACC_NETAPP_HOST_CIFS") + admin := os.Getenv("TF_ACC_NETAPP_USER") + password := os.Getenv("TF_ACC_NETAPP_PASS2") if host == "" || admin == "" || password == "" { fmt.Println("TF_ACC_NETAPP_HOST_CIFS, TF_ACC_NETAPP_USER, and TF_ACC_NETAPP_PASS2 must be set for acceptance tests") @@ -103,12 +100,9 @@ resource "netapp-ontap_protocols_cifs_share_resource" "example" { } func testAccProtocolsCIFSShareResourceConfigUpdate(svm, volName string) string { - // host := os.Getenv("TF_ACC_NETAPP_HOST_CIFS") - // admin := os.Getenv("TF_ACC_NETAPP_USER") - // password := os.Getenv("TF_ACC_NETAPP_PASS2") - host := "10.193.73.2" - admin := "admin" - password := "Netapp1!" + host := os.Getenv("TF_ACC_NETAPP_HOST_CIFS") + admin := os.Getenv("TF_ACC_NETAPP_USER") + password := os.Getenv("TF_ACC_NETAPP_PASS2") if host == "" || admin == "" || password == "" { fmt.Println("TF_ACC_NETAPP_HOST_CIFS, TF_ACC_NETAPP_USER, and TF_ACC_NETAPP_PASS2 must be set for acceptance tests") @@ -145,12 +139,9 @@ resource "netapp-ontap_protocols_cifs_share_resource" "example" { } func testAccProtocolsCIFSShareResourceConfigUpdateAddACL(svm, volName string) string { - // host := os.Getenv("TF_ACC_NETAPP_HOST_CIFS") - // admin := os.Getenv("TF_ACC_NETAPP_USER") - // password := os.Getenv("TF_ACC_NETAPP_PASS2") - host := "10.193.73.2" - admin := "admin" - password := "Netapp1!" + host := os.Getenv("TF_ACC_NETAPP_HOST_CIFS") + admin := os.Getenv("TF_ACC_NETAPP_USER") + password := os.Getenv("TF_ACC_NETAPP_PASS2") if host == "" || admin == "" || password == "" { fmt.Println("TF_ACC_NETAPP_HOST_CIFS, TF_ACC_NETAPP_USER, and TF_ACC_NETAPP_PASS2 must be set for acceptance tests") @@ -192,12 +183,10 @@ resource "netapp-ontap_protocols_cifs_share_resource" "example" { } func testAccProtocolsCIFSShareResourceConfigUpdateDeleteACL(svm, volName string) string { - // host := os.Getenv("TF_ACC_NETAPP_HOST_CIFS") - // admin := os.Getenv("TF_ACC_NETAPP_USER") - // password := os.Getenv("TF_ACC_NETAPP_PASS2") - host := "10.193.73.2" - admin := "admin" - password := "Netapp1!" + host := os.Getenv("TF_ACC_NETAPP_HOST_CIFS") + admin := os.Getenv("TF_ACC_NETAPP_USER") + password := os.Getenv("TF_ACC_NETAPP_PASS2") + if host == "" || admin == "" || password == "" { fmt.Println("TF_ACC_NETAPP_HOST_CIFS, TF_ACC_NETAPP_USER, and TF_ACC_NETAPP_PASS2 must be set for acceptance tests") os.Exit(1)