From 0d2295e8f72f6f411da98b38b6d3fa69c247303f Mon Sep 17 00:00:00 2001 From: Tanmay Jain Date: Wed, 10 Apr 2024 14:48:33 +0530 Subject: [PATCH 1/8] atom-2 and atom-38 --- accesscontrol/access_control.go | 512 ++++++++++++++++++++++++++++++++ accesscontrol/constants.go | 33 ++ asconfig/as_getconfig.go | 47 +-- asconfig/as_setconfig.go | 117 +++++++- asconfig/confdiff.go | 10 +- asconfig/constants.go | 10 +- asconfig/schema.go | 2 +- asconfig/utils.go | 2 +- 8 files changed, 695 insertions(+), 38 deletions(-) create mode 100644 accesscontrol/access_control.go create mode 100644 accesscontrol/constants.go diff --git a/accesscontrol/access_control.go b/accesscontrol/access_control.go new file mode 100644 index 0000000..c05fef1 --- /dev/null +++ b/accesscontrol/access_control.go @@ -0,0 +1,512 @@ +package accesscontrol + +// Aerospike access control reconciliation of access control. + +import ( + "bytes" + "fmt" + "reflect" + "strings" + + "github.com/go-logr/logr" + + as "github.com/aerospike/aerospike-client-go/v7" +) + +// logger type alias. +type logger = logr.Logger + +const ( + + // Error marker for user not found errors. + userNotFoundErr = "Invalid user" + + // Error marker for role not found errors. + roleNotFoundErr = "Invalid role" +) + +// privilegeStringToAerospikePrivilege converts privilegeString to an Aerospike privilege. +func privilegeStringToAerospikePrivilege(privilegeStrings []string) ( + []as.Privilege, error, +) { + aerospikePrivileges := make([]as.Privilege, 0, len(privilegeStrings)) + + for _, privilege := range privilegeStrings { + parts := strings.Split(privilege, ".") + if _, ok := Privileges[parts[0]]; !ok { + // First part of the privilege is not part of defined privileges. + return nil, fmt.Errorf("invalid privilege %s", privilege) + } + + privilegeCode := parts[0] + namespaceName := "" + setName := "" + nParts := len(parts) + + switch nParts { + case 2: + namespaceName = parts[1] + + case 3: + namespaceName = parts[1] + setName = parts[2] + } + + var code = as.Read //nolint:ineffassign // type is a private type in the pkg + + switch privilegeCode { + case "read": + code = as.Read + + case "write": + code = as.Write + + case "read-write": + code = as.ReadWrite + + case "read-write-udf": + code = as.ReadWriteUDF + + case "data-admin": + code = as.DataAdmin + + case "sys-admin": + code = as.SysAdmin + + case "user-admin": + code = as.UserAdmin + + case "truncate": + code = as.Truncate + + case "sindex-admin": + code = as.SIndexAdmin + + case "udf-admin": + code = as.UDFAdmin + + default: + return nil, fmt.Errorf("unknown privilege %s", privilegeCode) + } + + aerospikePrivilege := as.Privilege{ + Code: code, Namespace: namespaceName, SetName: setName, + } + aerospikePrivileges = append(aerospikePrivileges, aerospikePrivilege) + } + + return aerospikePrivileges, nil +} + +// AerospikePrivilegeToPrivilegeString converts aerospikePrivilege to controller spec privilege string. +func AerospikePrivilegeToPrivilegeString(aerospikePrivileges []as.Privilege) ( + []string, error, +) { + privileges := make([]string, 0, len(aerospikePrivileges)) + + for _, aerospikePrivilege := range aerospikePrivileges { + var buffer bytes.Buffer + + switch aerospikePrivilege.Code { + case as.Read: + buffer.WriteString("read") + + case as.Write: + buffer.WriteString("write") + + case as.ReadWrite: + buffer.WriteString("read-write") + + case as.ReadWriteUDF: + buffer.WriteString("read-write-udf") + + case as.DataAdmin: + buffer.WriteString("data-admin") + + case as.SysAdmin: + buffer.WriteString("sys-admin") + + case as.UserAdmin: + buffer.WriteString("user-admin") + + case as.Truncate: + buffer.WriteString("truncate") + + case as.SIndexAdmin: + buffer.WriteString("sindex-admin") + + case as.UDFAdmin: + buffer.WriteString("udf-admin") + + default: + return nil, fmt.Errorf( + "unknown privilege code %v", aerospikePrivilege.Code, + ) + } + + if aerospikePrivilege.Namespace != "" { + buffer.WriteString(".") + buffer.WriteString(aerospikePrivilege.Namespace) + + if aerospikePrivilege.SetName != "" { + buffer.WriteString(".") + buffer.WriteString(aerospikePrivilege.SetName) + } + } + + privileges = append(privileges, buffer.String()) + } + + return privileges, nil +} + +// AerospikeAccessControlReconcileCmd commands needed to Reconcile a single access control entry, +// for example a role or a user. +type AerospikeAccessControlReconcileCmd interface { + // Execute executes the command. The implementation should be idempotent. + Execute( + client *as.Client, adminPolicy *as.AdminPolicy, logger logger, + ) error +} + +// AerospikeRoleCreateUpdate creates or updates an Aerospike role. +type AerospikeRoleCreateUpdate struct { + // The role's name. + Name string + + // The privileges to set for the role. These privileges and only these privileges will be granted to the role + // after this operation. + Privileges []string + + // The whitelist to set for the role. These whitelist addresses and only these whitelist addresses will be + // granted to the role after this operation. + Whitelist []string + + // The readQuota specifies the read query rate that is permitted for the current role. + ReadQuota uint32 + + // The writeQuota specifies the write rate that is permitted for the current role. + WriteQuota uint32 +} + +// Execute creates a new Aerospike role or updates an existing one. +func (roleCreate AerospikeRoleCreateUpdate) Execute( + client *as.Client, adminPolicy *as.AdminPolicy, logger logger, +) error { + role, err := client.QueryRole(adminPolicy, roleCreate.Name) + isCreate := false + + if err != nil { + if strings.Contains(err.Error(), roleNotFoundErr) { + isCreate = true + } else { + // Failure to query for the role. + return fmt.Errorf( + "error querying role %s: %v", roleCreate.Name, err, + ) + } + } + + if isCreate { + return roleCreate.CreateRole(client, adminPolicy, logger) + } + + return roleCreate.UpdateRole( + client, adminPolicy, role, logger, + ) +} + +// CreateRole creates a new Aerospike role. +func (roleCreate AerospikeRoleCreateUpdate) CreateRole( + client *as.Client, adminPolicy *as.AdminPolicy, logger logger, +) error { + logger.Info("Creating role", "role name", roleCreate.Name) + + aerospikePrivileges, err := privilegeStringToAerospikePrivilege(roleCreate.Privileges) + if err != nil { + return fmt.Errorf("could not create role %s: %v", roleCreate.Name, err) + } + + if err = client.CreateRole( + adminPolicy, roleCreate.Name, aerospikePrivileges, roleCreate.Whitelist, + roleCreate.ReadQuota, roleCreate.WriteQuota, + ); err != nil { + return fmt.Errorf("could not create role %s: %v", roleCreate.Name, err) + } + + logger.Info("Created role", "role name", roleCreate.Name) + + return nil +} + +// UpdateRole updates an existing Aerospike role. +func (roleCreate AerospikeRoleCreateUpdate) UpdateRole( + client *as.Client, adminPolicy *as.AdminPolicy, role *as.Role, + logger logger, +) error { + // Update the role. + logger.Info("Updating role", "role name", roleCreate.Name) + + // Find the privileges to drop. + currentPrivileges, err := AerospikePrivilegeToPrivilegeString(role.Privileges) + if err != nil { + return fmt.Errorf("could not update role %s: %v", roleCreate.Name, err) + } + + desiredPrivileges := roleCreate.Privileges + privilegesToRevoke := SliceSubtract(currentPrivileges, desiredPrivileges) + privilegesToGrant := SliceSubtract(desiredPrivileges, currentPrivileges) + + if len(privilegesToRevoke) > 0 { + aerospikePrivileges, err := privilegeStringToAerospikePrivilege(privilegesToRevoke) + if err != nil { + return fmt.Errorf( + "could not update role %s: %v", roleCreate.Name, err, + ) + } + + if err := client.RevokePrivileges( + adminPolicy, roleCreate.Name, aerospikePrivileges, + ); err != nil { + return fmt.Errorf( + "error revoking privileges for role %s: %v", roleCreate.Name, + err, + ) + } + + logger.Info( + "Revoked privileges for role", "role name", roleCreate.Name, + "privileges", privilegesToRevoke, + ) + } + + if len(privilegesToGrant) > 0 { + aerospikePrivileges, err := privilegeStringToAerospikePrivilege(privilegesToGrant) + if err != nil { + return fmt.Errorf( + "could not update role %s: %v", roleCreate.Name, err, + ) + } + + if err := client.GrantPrivileges( + adminPolicy, roleCreate.Name, aerospikePrivileges, + ); err != nil { + return fmt.Errorf( + "error granting privileges for role %s: %v", roleCreate.Name, + err, + ) + } + + logger.Info( + "Granted privileges to role", "role name", roleCreate.Name, + "privileges", privilegesToGrant, + ) + } + + if !reflect.DeepEqual(role.Whitelist, roleCreate.Whitelist) { + // Set whitelist. + if err := client.SetWhitelist( + adminPolicy, roleCreate.Name, roleCreate.Whitelist, + ); err != nil { + return fmt.Errorf( + "error setting whitelist for role %s: %v", roleCreate.Name, err, + ) + } + } + + logger.Info("Updated role", "role name", roleCreate.Name) + + return nil +} + +// AerospikeUserCreateUpdate creates or updates an Aerospike user. +type AerospikeUserCreateUpdate struct { + // The user's name. + Name string + + // The password to set. Required for create. Optional for update. + Password *string + + // The roles to set for the user. These roles and only these roles will be granted to the user after this operation. + Roles []string +} + +// Execute creates a new Aerospike user or updates an existing one. +func (userCreate AerospikeUserCreateUpdate) Execute( + client *as.Client, adminPolicy *as.AdminPolicy, logger logger, +) error { + user, err := client.QueryUser(adminPolicy, userCreate.Name) + isCreate := false + + if err != nil { + if strings.Contains(err.Error(), userNotFoundErr) { + isCreate = true + } else { + // Failure to query for the user. + return fmt.Errorf( + "error querying user %s: %v", userCreate.Name, err, + ) + } + } + + if isCreate { + return userCreate.CreateUser(client, adminPolicy, logger) + } + + return userCreate.UpdateUser( + client, adminPolicy, user, logger, + ) +} + +// CreateUser creates a new Aerospike user. +func (userCreate AerospikeUserCreateUpdate) CreateUser( + client *as.Client, adminPolicy *as.AdminPolicy, logger logger, +) error { + logger.Info("Creating user", "username", userCreate.Name) + + if userCreate.Password == nil { + return fmt.Errorf( + "error creating user %s. Password not specified", userCreate.Name, + ) + } + + if err := client.CreateUser( + adminPolicy, userCreate.Name, *userCreate.Password, userCreate.Roles, + ); err != nil { + return fmt.Errorf("could not create user %s: %v", userCreate.Name, err) + } + + logger.Info("Created user", "username", userCreate.Name) + + return nil +} + +// UpdateUser updates an existing Aerospike user. +func (userCreate AerospikeUserCreateUpdate) UpdateUser( + client *as.Client, adminPolicy *as.AdminPolicy, user *as.UserRoles, + logger logger, +) error { + // Update the user. + logger.Info("Updating user", "username", userCreate.Name) + + if userCreate.Password != nil { + logger.Info("Updating password for user", "username", userCreate.Name) + + if err := client.ChangePassword( + adminPolicy, userCreate.Name, *userCreate.Password, + ); err != nil { + return fmt.Errorf( + "error updating password for user %s: %v", userCreate.Name, err, + ) + } + + logger.Info("Updated password for user", "username", userCreate.Name) + } + + // Find the roles to grant and revoke. + currentRoles := user.Roles + desiredRoles := userCreate.Roles + rolesToRevoke := SliceSubtract(currentRoles, desiredRoles) + rolesToGrant := SliceSubtract(desiredRoles, currentRoles) + + if len(rolesToRevoke) > 0 { + if err := client.RevokeRoles(adminPolicy, userCreate.Name, rolesToRevoke); err != nil { + return fmt.Errorf( + "error revoking roles for user %s: %v", userCreate.Name, err, + ) + } + + logger.Info( + "Revoked roles for user", "username", userCreate.Name, "roles", + rolesToRevoke, + ) + } + + if len(rolesToGrant) > 0 { + if err := client.GrantRoles(adminPolicy, userCreate.Name, rolesToGrant); err != nil { + return fmt.Errorf( + "error granting roles for user %s: %v", userCreate.Name, err, + ) + } + + logger.Info( + "Granted roles to user", "username", userCreate.Name, "roles", + rolesToGrant, + ) + } + + logger.Info("Updated user", "username", userCreate.Name) + + return nil +} + +// AerospikeUserDrop drops an Aerospike user. +type AerospikeUserDrop struct { + // The user's name. + Name string +} + +// Execute implements dropping the user. +func (userDrop AerospikeUserDrop) Execute( + client *as.Client, adminPolicy *as.AdminPolicy, logger logger, +) error { + logger.Info("Dropping user", "username", userDrop.Name) + + if err := client.DropUser(adminPolicy, userDrop.Name); err != nil { + if !strings.Contains(err.Error(), userNotFoundErr) { + // Failure to drop for the user. + return fmt.Errorf("error dropping user %s: %v", userDrop.Name, err) + } + } + + logger.Info("Dropped user", "username", userDrop.Name) + + return nil +} + +// AerospikeRoleDrop drops an Aerospike role. +type AerospikeRoleDrop struct { + // The role's name. + Name string +} + +// Execute implements dropping the role. +func (roleDrop AerospikeRoleDrop) Execute( + client *as.Client, adminPolicy *as.AdminPolicy, logger logger, +) error { + logger.Info("Dropping role", "role", roleDrop.Name) + + if err := client.DropRole(adminPolicy, roleDrop.Name); err != nil { + if !strings.Contains(err.Error(), roleNotFoundErr) { + // Failure to drop for the role. + return fmt.Errorf("error dropping role %s: %v", roleDrop.Name, err) + } + } + + logger.Info("Dropped role", "role", roleDrop.Name) + + return nil +} + +// SliceSubtract removes elements of slice2 from slice1 and returns the result. +func SliceSubtract(slice1, slice2 []string) []string { + var result []string + + for _, s1 := range slice1 { + found := false + + for _, toSubtract := range slice2 { + if s1 == toSubtract { + found = true + break + } + } + + if !found { + // s1 not found. Should be retained. + result = append(result, s1) + } + } + + return result +} diff --git a/accesscontrol/constants.go b/accesscontrol/constants.go new file mode 100644 index 0000000..a90eb83 --- /dev/null +++ b/accesscontrol/constants.go @@ -0,0 +1,33 @@ +package accesscontrol + +// PrivilegeScope enumerates valid scopes for privileges. +type PrivilegeScope int + +const ( + // Global scoped privileges. + Global PrivilegeScope = iota + + // NamespaceSet is namespace and optional set scoped privilege. + NamespaceSet +) + +// Privileges are all privilege string allowed in the spec and associated scopes. +var Privileges = map[string][]PrivilegeScope{ + "read": {Global, NamespaceSet}, + "write": {Global, NamespaceSet}, + "read-write": {Global, NamespaceSet}, + "read-write-udf": {Global, NamespaceSet}, + "data-admin": {Global}, + "sys-admin": {Global}, + "user-admin": {Global}, + "truncate": {Global, NamespaceSet}, + "sindex-admin": {Global}, + "udf-admin": {Global}, +} + +// Post6Privileges are post version 6.0 privilege strings allowed in the spec and associated scopes. +var Post6Privileges = map[string][]PrivilegeScope{ + "truncate": {Global, NamespaceSet}, + "sindex-admin": {Global}, + "udf-admin": {Global}, +} diff --git a/asconfig/as_getconfig.go b/asconfig/as_getconfig.go index 6cb4bfe..11628de 100644 --- a/asconfig/as_getconfig.go +++ b/asconfig/as_getconfig.go @@ -4,6 +4,7 @@ import ( "fmt" "strings" + sets "github.com/deckarep/golang-set/v2" "github.com/go-logr/logr" aero "github.com/aerospike/aerospike-client-go/v7" @@ -13,44 +14,54 @@ import ( ) // GetASConfig returns the value of the given path from the aerospike config from given host. -func GetASConfig(path *string, conn *deployment.ASConn, aerospikePolicy *aero.ClientPolicy) ( - confToReturn interface{}, err error) { +func GetASConfig(paths []string, conn *deployment.ASConn, aerospikePolicy *aero.ClientPolicy) ( + confToReturn map[string]interface{}, err error) { h := aero.Host{ Name: conn.AerospikeHostName, Port: conn.AerospikePort, TLSName: conn.AerospikeTLSName, } asinfo := info.NewAsInfo(conn.Log, &h, aerospikePolicy) + ctxs := sets.NewSet[string]() - var ctxs []string - if path != nil { + for _, path := range paths { // Get the corresponding sets info also if context is namespace. - ctxs = []string{ContextKey(*path)} - if ctxs[0] == info.ConfigNamespaceContext { - ctxs = append(ctxs, info.ConfigSetContext) + ctx := ContextKey(path) + ctxs.Add(ctx) + + if ctx == info.ConfigNamespaceContext { + ctxs.Add(info.ConfigSetContext) } } - conf, err := asinfo.GetAsConfig(ctxs...) + conf, err := asinfo.GetAsConfig(ctxs.ToSlice()...) if err != nil { conn.Log.Error(err, "failed to get asconfig") return nil, err } - if path == nil { + if len(paths) == 0 { return conf, nil } - confToReturn = conf[ctxs[0]] - if confToReturn == nil { - conn.Log.Info("Config is nil", "context", ctxs[0]) - return nil, nil - } + confToReturn = make(map[string]interface{}) - confToReturn, err = traverseConfig(conn.Log, confToReturn, *path, ctxs[0]) - if err != nil { - conn.Log.Error(err, "failed to traverse config") - return nil, err + for _, path := range paths { + ctx := ContextKey(path) + + ctxConf := conf[ctx] + if ctxConf == nil { + conn.Log.Info("Config is nil", "context", ctxConf) + return nil, nil + } + + ctxConf, err = traverseConfig(conn.Log, ctxConf, path, ctx) + if err != nil { + conn.Log.Error(err, "failed to traverse config") + return nil, err + } + + confToReturn[path] = ctxConf } return confToReturn, nil diff --git a/asconfig/as_setconfig.go b/asconfig/as_setconfig.go index 4be4774..6045d09 100644 --- a/asconfig/as_setconfig.go +++ b/asconfig/as_setconfig.go @@ -20,8 +20,8 @@ const ( // convertValueToString converts the value of a config to a string. // only string type can be used to populate set-config commands with values. -func convertValueToString(v1 map[Operation]interface{}) (map[Operation][]string, error) { - valueMap := make(map[Operation][]string) +func convertValueToString(v1 map[OpType]interface{}) (map[OpType][]string, error) { + valueMap := make(map[OpType][]string) for k, v := range v1 { values := make([]string, 0) @@ -52,7 +52,7 @@ func convertValueToString(v1 map[Operation]interface{}) (map[Operation][]string, } // createSetConfigServiceCmdList creates set-config commands for service context. -func createSetConfigServiceCmdList(tokens []string, operationValueMap map[Operation][]string) []string { +func createSetConfigServiceCmdList(tokens []string, operationValueMap map[OpType][]string) []string { val := operationValueMap[Update] cmdList := make([]string, 0, len(val)) cmd := cmdSetConfigService @@ -72,7 +72,7 @@ func createSetConfigServiceCmdList(tokens []string, operationValueMap map[Operat } // createSetConfigNetworkCmdList creates set-config commands for network context. -func createSetConfigNetworkCmdList(tokens []string, operationValueMap map[Operation][]string) []string { +func createSetConfigNetworkCmdList(tokens []string, operationValueMap map[OpType][]string) []string { val := operationValueMap[Update] cmdList := make([]string, 0, len(val)) cmd := cmdSetConfigNetwork @@ -92,7 +92,7 @@ func createSetConfigNetworkCmdList(tokens []string, operationValueMap map[Operat } // createSetConfigSecurityCmdList creates set-config commands for security context. -func createSetConfigSecurityCmdList(tokens []string, operationValueMap map[Operation][]string) []string { +func createSetConfigSecurityCmdList(tokens []string, operationValueMap map[OpType][]string) []string { cmdList := make([]string, 0, len(operationValueMap)) cmd := cmdSetConfigSecurity @@ -176,7 +176,7 @@ func createSetConfigSecurityCmdList(tokens []string, operationValueMap map[Opera } // createSetConfigNamespaceCmdList creates set-config commands for namespace context. -func createSetConfigNamespaceCmdList(tokens []string, operationValueMap map[Operation][]string) []string { +func createSetConfigNamespaceCmdList(tokens []string, operationValueMap map[OpType][]string) []string { val := operationValueMap[Update] cmdList := make([]string, 0, len(val)) cmd := cmdSetConfigNamespace @@ -215,7 +215,7 @@ func createSetConfigNamespaceCmdList(tokens []string, operationValueMap map[Oper } // createLogSetCmdList creates log-set commands for logging context. -func createLogSetCmdList(tokens []string, operationValueMap map[Operation][]string, +func createLogSetCmdList(tokens []string, operationValueMap map[OpType][]string, conn deployment.ASConnInterface, aerospikePolicy *aero.ClientPolicy) ([]string, error) { val := operationValueMap[Update] cmdList := make([]string, 0, len(val)) @@ -249,7 +249,7 @@ func createLogSetCmdList(tokens []string, operationValueMap map[Operation][]stri /* // createSetConfigXDRCmdList creates set-config commands for XDR context. -func createSetConfigXDRCmdList(tokens []string, operationValueMap map[Operation][]string) []string { +func createSetConfigXDRCmdList(tokens []string, operationValueMap map[OpType][]string) []string { cmdList := make([]string, 0, len(operationValueMap)) cmd := cmdSetConfigXDR prevToken := "" @@ -460,3 +460,104 @@ func rearrangeConfigMap(log logr.Logger, configMap DynamicConfigMap) []string { return finalList } */ + +func ValidConfigOperations() []OpType { + return []OpType{Add, Update, Remove} +} + +func (o OpType) Validate() error { + switch o { + case Add, Update, Remove: + return nil + } + + return fmt.Errorf("invalid operation type: %s, Valid operations: %v", o, ValidConfigOperations()) +} + +type ConfigOperation struct { + Operation OpType `json:"op"` + Context string `json:"context"` + Config string `json:"config"` + Value string `json:"value,omitempty"` +} + +func (p ConfigOperation) Validate() error { + return p.Operation.Validate() +} + +func CreateConfigSetCmdsUsingPatch( + configMap map[string]interface{}, conn *deployment.ASConn, aerospikePolicy *aero.ClientPolicy, version string, +) ([]string, error) { + conf, err := NewMapAsConfig(conn.Log, configMap) + if err != nil { + return nil, err + } + + flatConf := conf.GetFlatMap() + asConfChange := make(DynamicConfigMap) + + for k, v := range *flatConf { + if strings.HasSuffix(k, sep+KeyName) || strings.HasSuffix(k, sep+keyIndex) { + // skip namespace, dc, etc names + continue + } + + if ok, _ := isListField(k); ok { + // Ignore these fields as these operations are not update operations + //TODO: Should we through an error if these fields are present in the configMap patch? + continue + } + + valueMap := make(map[OpType]interface{}) + valueMap[Update] = v + asConfChange[k] = valueMap + } + + isDynamic, err := IsAllDynamicConfig(conn.Log, asConfChange, version) + if err != nil { + return nil, err + } + + if !isDynamic { + return nil, fmt.Errorf("static field has been changed, cannot change config dynamically") + } + + return CreateSetConfigCmdList(asConfChange, conn, aerospikePolicy) +} + +func CreateConfigSetCmdsUsingOperation( + confOp ConfigOperation, conn *deployment.ASConn, aerospikePolicy *aero.ClientPolicy, version string, +) ([]string, error) { + if err := confOp.Validate(); err != nil { + return nil, err + } + // Context: security.log, Config:report-data-op, Value:test set + // Map: security.log.report-data-op:map[remove:"test set"] + path := confOp.Context + sep + confOp.Config + value := confOp.Value + + if confOp.Config == KeyName { + if confOp.Operation == Update { + return nil, fmt.Errorf("cannot update name field") + } + // Context: namespaces, Config: name, value: ns1 + // Map: namespaces.{testMem}.name:map[remove:testMem] + path = confOp.Context + sep + string(SectionNameStartChar) + value + string(SectionNameEndChar) + sep + KeyName + } + + asConfChange := make(DynamicConfigMap) + valueMap := make(map[OpType]interface{}) + valueMap[confOp.Operation] = value + asConfChange[path] = valueMap + + isDynamic, err := IsAllDynamicConfig(conn.Log, asConfChange, version) + if err != nil { + return nil, err + } + + if !isDynamic { + return nil, fmt.Errorf("static field has been changed, cannot change config dynamically") + } + + return CreateSetConfigCmdList(asConfChange, conn, aerospikePolicy) +} diff --git a/asconfig/confdiff.go b/asconfig/confdiff.go index 1e58d51..c27c60f 100644 --- a/asconfig/confdiff.go +++ b/asconfig/confdiff.go @@ -157,7 +157,7 @@ func handleMissingSection(log logr.Logger, key string, desired, current Conf, d // Whole section which has "name" as key is not present in current // If token is under "{}", then it is a named section if _, okay := current[nameKeyPath]; ReCurlyBraces.MatchString(token) && !okay { - operationValueMap := make(map[Operation]interface{}) + operationValueMap := make(map[OpType]interface{}) if desiredToActual { if _, updated := d[key]; !updated { @@ -193,7 +193,7 @@ func handlePartialMissingSection(desiredKey, ver string, current Conf, d Dynamic continue } - operationValueMap := make(map[Operation]interface{}) + operationValueMap := make(map[OpType]interface{}) // If removed subsection is of type slice, then there is no default values to be set. // eg. current = security.log.report-data-op: []string{test} // desired = security: {} @@ -218,7 +218,7 @@ func handlePartialMissingSection(desiredKey, ver string, current Conf, d Dynamic } func handleSliceFields(key string, desired Conf, d DynamicConfigMap, desiredToActual bool) { - operationValueMap := make(map[Operation]interface{}) + operationValueMap := make(map[OpType]interface{}) if reflect.ValueOf(desired[key]).Kind() == reflect.Slice { if desiredToActual { @@ -234,7 +234,7 @@ func handleSliceFields(key string, desired Conf, d DynamicConfigMap, desiredToAc } func handleValueDiff(key string, desiredValue, currentValue interface{}, d DynamicConfigMap) { - operationValueMap := make(map[Operation]interface{}) + operationValueMap := make(map[OpType]interface{}) if reflect.ValueOf(desiredValue).Kind() == reflect.Slice { currentSet := sets.NewSet[string]() @@ -366,7 +366,7 @@ func ConfDiff( return nil, err } - valueMap := make(map[Operation]interface{}) + valueMap := make(map[OpType]interface{}) valueMap[Update] = getDefaultValue(defaultMap, removedConfigKey) diffs[removedConfigKey] = valueMap } diff --git a/asconfig/constants.go b/asconfig/constants.go index 80462b4..3dd2cb3 100644 --- a/asconfig/constants.go +++ b/asconfig/constants.go @@ -1,6 +1,6 @@ package asconfig -type Operation string +type OpType string // All the aerospike config related keys const ( @@ -33,8 +33,8 @@ const ( equal = "=" colon = ":" - // Enum values for Operation - Add Operation = "add" - Remove Operation = "remove" - Update Operation = "update" + // Enum values for OpType + Add OpType = "add" + Remove OpType = "remove" + Update OpType = "update" ) diff --git a/asconfig/schema.go b/asconfig/schema.go index 8e16489..4e6fe58 100644 --- a/asconfig/schema.go +++ b/asconfig/schema.go @@ -195,7 +195,7 @@ func IsAllDynamicConfig(log logr.Logger, configMap DynamicConfigMap, version str // isDynamicConfig returns true if the given field is dynamically configured. func isDynamicConfig(log logr.Logger, dynamic sets.Set[string], conf string, - valueMap map[Operation]interface{}) bool { + valueMap map[OpType]interface{}) bool { tokens := SplitKey(log, conf, sep) baseKey := tokens[len(tokens)-1] context := tokens[0] diff --git a/asconfig/utils.go b/asconfig/utils.go index c2071b2..bbd1522 100644 --- a/asconfig/utils.go +++ b/asconfig/utils.go @@ -1129,4 +1129,4 @@ var ReCurlyBraces = regexp.MustCompile(`^\{.*\}$`) // DynamicConfigMap is a map of config flatten keys and their operations and values // for eg: "xdr.dcs.{DC3}.node-address-ports": {Remove: []string{"1.1.2.1 3000"}} -type DynamicConfigMap map[string]map[Operation]interface{} +type DynamicConfigMap map[string]map[OpType]interface{} From 32113b10c8b9845d2931aa7484e29868ce924199 Mon Sep 17 00:00:00 2001 From: Tanmay Jain Date: Fri, 31 May 2024 12:53:05 +0530 Subject: [PATCH 2/8] enabling xdr --- asconfig/as_setconfig.go | 57 +++++++++++++++++------------------ asconfig/as_setconfig_test.go | 8 ++--- 2 files changed, 31 insertions(+), 34 deletions(-) diff --git a/asconfig/as_setconfig.go b/asconfig/as_setconfig.go index 6045d09..a97c0ee 100644 --- a/asconfig/as_setconfig.go +++ b/asconfig/as_setconfig.go @@ -1,9 +1,12 @@ package asconfig import ( + "container/list" "fmt" "strings" + "github.com/go-logr/logr" + aero "github.com/aerospike/aerospike-client-go/v7" "github.com/aerospike/aerospike-management-lib/deployment" "github.com/aerospike/aerospike-management-lib/info" @@ -13,9 +16,9 @@ const ( cmdSetConfigNetwork = "set-config:context=network;" // ConfigNetwork cmdSetConfigService = "set-config:context=service;" // ConfigService cmdSetConfigNamespace = "set-config:context=namespace;id=" // ConfigNamespace - // cmdSetConfigXDR = "set-config:context=xdr" // ConfigXDR - cmdSetConfigSecurity = "set-config:context=security;" // ConfigSecurity - cmdSetLogging = "log-set:id=" // ConfigLogging + cmdSetConfigXDR = "set-config:context=xdr" // ConfigXDR + cmdSetConfigSecurity = "set-config:context=security;" // ConfigSecurity + cmdSetLogging = "log-set:id=" // ConfigLogging ) // convertValueToString converts the value of a config to a string. @@ -191,10 +194,14 @@ func createSetConfigNamespaceCmdList(tokens []string, operationValueMap map[OpTy cmd += strings.Trim(token, "{}") } } else { - if prevToken == "index-type" || prevToken == "sindex-type" { + switch prevToken { + case "index-type", "sindex-type": cmd += fmt.Sprintf(";%s.%s", prevToken, token) prevToken = "" - } else { + case "geo2dsphere-within": + cmd += fmt.Sprintf(";%s-%s", prevToken, token) + prevToken = "" + default: prevToken = token } } @@ -247,7 +254,6 @@ func createLogSetCmdList(tokens []string, operationValueMap map[OpType][]string, return cmdList, nil } -/* // createSetConfigXDRCmdList creates set-config commands for XDR context. func createSetConfigXDRCmdList(tokens []string, operationValueMap map[OpType][]string) []string { cmdList := make([]string, 0, len(operationValueMap)) @@ -312,15 +318,15 @@ func createSetConfigXDRCmdList(tokens []string, operationValueMap map[OpType][]s return cmdList } -*/ // CreateSetConfigCmdList creates set-config commands for given config. -func CreateSetConfigCmdList(configMap DynamicConfigMap, conn deployment.ASConnInterface, +func CreateSetConfigCmdList(log logr.Logger, configMap DynamicConfigMap, conn deployment.ASConnInterface, aerospikePolicy *aero.ClientPolicy, ) ([]string, error) { cmdList := make([]string, 0, len(configMap)) - for c := range configMap { + orderedConfList := rearrangeConfigMap(log, configMap) + for _, c := range orderedConfList { tokens := strings.Split(c, sep) context := tokens[0] @@ -339,11 +345,8 @@ func CreateSetConfigCmdList(configMap DynamicConfigMap, conn deployment.ASConnIn case info.ConfigNamespaceContext: cmdList = append(cmdList, createSetConfigNamespaceCmdList(tokens, val)...) - /* - Commenting out XDR context for now because of ordering issues. - case info.ConfigXDRContext: - cmdList = append(cmdList, createSetConfigXDRCmdList(tokens, val)...) - */ + case info.ConfigXDRContext: + cmdList = append(cmdList, createSetConfigXDRCmdList(tokens, val)...) case info.ConfigLoggingContext: cmds, err := createLogSetCmdList(tokens, val, conn, aerospikePolicy) @@ -361,7 +364,6 @@ func CreateSetConfigCmdList(configMap DynamicConfigMap, conn deployment.ASConnIn return cmdList, nil } -/* // Returns a list of config keys in the order in which they should be applied. // The order is as follows: // 1. Removed Namespaces -- If user has to change some of the DC direct fields, they will have to remove the namespace @@ -397,7 +399,7 @@ func rearrangeConfigMap(log logr.Logger, configMap DynamicConfigMap) []string { // If namespace is removed, directly add it to the final list finalList = append(finalList, k) } else { - // If namespace is added, add it after all DCs and their direct fields + // If namespace is added, add it after all DCs and their direct configs if lastDCConfig == nil { if lastDC != nil { rearrangedConfigMap.InsertAfter(k, lastDC) @@ -418,23 +420,19 @@ func rearrangeConfigMap(log logr.Logger, configMap DynamicConfigMap) []string { // Handle DC direct fields if tokens[len(tokens)-3] == info.ConfigDCContext { var nap *list.Element - // Check if the key is related to 'node-address-ports' - isNodeAddressPortsKey := strings.HasSuffix(k, sep+keyNodeAddressPorts) - - if isNodeAddressPortsKey { + // Check if the key is 'node-address-ports' + if strings.HasSuffix(k, sep+keyNodeAddressPorts) { if _, ok := v[Remove]; ok { dc := rearrangedConfigMap.PushFront(k) if lastDC == nil { lastDC = dc } continue - } else { - if lastDCConfig != nil { - // Add 'node-address-ports' after all DC direct fields - // There are certain fields that must be set before 'node-address-ports', for example, 'tls-name'. - lastDCConfig = rearrangedConfigMap.InsertAfter(k, lastDCConfig) - continue - } + } else if lastDCConfig != nil { + // Add 'node-address-ports' after all DC direct fields + // There are certain fields that must be set before 'node-address-ports', for example, 'tls-name'. + lastDCConfig = rearrangedConfigMap.InsertAfter(k, lastDCConfig) + continue } } @@ -459,7 +457,6 @@ func rearrangeConfigMap(log logr.Logger, configMap DynamicConfigMap) []string { return finalList } -*/ func ValidConfigOperations() []OpType { return []OpType{Add, Update, Remove} @@ -522,7 +519,7 @@ func CreateConfigSetCmdsUsingPatch( return nil, fmt.Errorf("static field has been changed, cannot change config dynamically") } - return CreateSetConfigCmdList(asConfChange, conn, aerospikePolicy) + return CreateSetConfigCmdList(logr.Logger{}, asConfChange, conn, aerospikePolicy) } func CreateConfigSetCmdsUsingOperation( @@ -559,5 +556,5 @@ func CreateConfigSetCmdsUsingOperation( return nil, fmt.Errorf("static field has been changed, cannot change config dynamically") } - return CreateSetConfigCmdList(asConfChange, conn, aerospikePolicy) + return CreateSetConfigCmdList(logr.Logger{}, asConfChange, conn, aerospikePolicy) } diff --git a/asconfig/as_setconfig_test.go b/asconfig/as_setconfig_test.go index 9774c6b..98fd57d 100644 --- a/asconfig/as_setconfig_test.go +++ b/asconfig/as_setconfig_test.go @@ -3,6 +3,7 @@ package asconfig import ( "testing" + "github.com/go-logr/logr" "github.com/stretchr/testify/suite" "go.uber.org/mock/gomock" @@ -62,11 +63,12 @@ func (s *AsSetConfigTestSuite) TestCreateSetConfigCmdList() { for _, tc := range testCases { s.Run(tc.name, func() { + logger := logr.Discard() policy := &aero.ClientPolicy{} s.mockASConn.EXPECT().RunInfo(gomock.Any(), gomock.Any()).Return(map[string]string{ "logs": "0:stderr"}, nil).AnyTimes() - result, err := CreateSetConfigCmdList(tc.inputConf, s.mockASConn, policy) + result, err := CreateSetConfigCmdList(logger, tc.inputConf, s.mockASConn, policy) s.Assert().Nil(err) s.Assert().True(gomock.InAnyOrder(result).Matches(tc.expected)) @@ -74,7 +76,6 @@ func (s *AsSetConfigTestSuite) TestCreateSetConfigCmdList() { } } -/* func (s *AsSetConfigTestSuite) TestCreateSetConfigCmdListOrdered() { testCases := []struct { name string @@ -87,7 +88,7 @@ func (s *AsSetConfigTestSuite) TestCreateSetConfigCmdListOrdered() { "xdr.dcs.{DC1}.namespaces.{ns1}.bin-policy": {Update: "no-bins"}, "xdr.dcs.{DC3}.name": {Add: "DC3"}, "xdr.dcs.{DC1}.namespaces.{ns2}.name": {Remove: "ns2"}, - "xdr.dcs.{DC1}.node-address-ports": {Add: []string{"1.1.1.1:3000:tls-name"}, + "xdr.dcs.{DC1}.node-address-ports": {Add: []string{"1.1.1.1:3000:tls-name"}}, "xdr.dcs.{DC1}.namespaces.{ns1}.name": {Add: "ns1"}, "xdr.dcs.{DC1}.tls-name": {Update: "tls-name"}, }, @@ -114,7 +115,6 @@ func (s *AsSetConfigTestSuite) TestCreateSetConfigCmdListOrdered() { }) } } -*/ func TestAsSetConfigTestSuite(t *testing.T) { suite.Run(t, new(AsSetConfigTestSuite)) From 0a60cdefd5e301df612da48bd3de77106bb2addd Mon Sep 17 00:00:00 2001 From: Tanmay Jain Date: Wed, 12 Jun 2024 14:23:28 +0530 Subject: [PATCH 3/8] Updating client-go to 7.4 --- go.mod | 10 +++++----- go.sum | 32 ++++++++++++++++---------------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/go.mod b/go.mod index 334b8f8..d74495b 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/aerospike/aerospike-management-lib go 1.21 require ( - github.com/aerospike/aerospike-client-go/v7 v7.1.0 + github.com/aerospike/aerospike-client-go/v7 v7.4.0 github.com/deckarep/golang-set/v2 v2.3.1 github.com/docker/go-connections v0.4.0 github.com/go-logr/logr v1.4.1 @@ -35,9 +35,9 @@ require ( go.opentelemetry.io/otel/metric v1.25.0 // indirect go.opentelemetry.io/otel/sdk v1.25.0 // indirect go.opentelemetry.io/otel/trace v1.25.0 // indirect - golang.org/x/mod v0.13.0 // indirect + golang.org/x/mod v0.16.0 // indirect golang.org/x/time v0.5.0 // indirect - golang.org/x/tools v0.14.0 // indirect + golang.org/x/tools v0.19.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect @@ -51,9 +51,9 @@ require ( github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/yuin/gopher-lua v1.1.1 // indirect golang.org/x/net v0.24.0 // indirect - golang.org/x/sync v0.6.0 // indirect + golang.org/x/sync v0.7.0 // indirect golang.org/x/sys v0.19.0 // indirect golang.org/x/text v0.14.0 // indirect - google.golang.org/grpc v1.63.0 // indirect + google.golang.org/grpc v1.63.2 // indirect google.golang.org/protobuf v1.33.0 // indirect ) diff --git a/go.sum b/go.sum index 3321d97..b0bba1f 100644 --- a/go.sum +++ b/go.sum @@ -2,8 +2,8 @@ github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOEl github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= -github.com/aerospike/aerospike-client-go/v7 v7.1.0 h1:yvCTKdbpqZxHvv7sWsFHV1j49jZcC8yXRooWsDFqKtA= -github.com/aerospike/aerospike-client-go/v7 v7.1.0/go.mod h1:AkHiKvCbqa1c16gCNGju3c5X/yzwLVvblNczqjxNwNk= +github.com/aerospike/aerospike-client-go/v7 v7.4.0 h1:g8/7v8RHhQhTArhW3C7Au7o+u8j8x5eySZL6MXfpHKU= +github.com/aerospike/aerospike-client-go/v7 v7.4.0/go.mod h1:pPKnWiS8VDJcH4IeB1b8SA2TWnkjcVLHwAAJ+BHfGK8= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= @@ -36,8 +36,8 @@ github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec= -github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7 h1:y3N7Bm7Y9/CtpiVkw/ZWj6lSlDF3F74SfKwfTCer72Q= +github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 h1:Wqo399gCIufwto+VfwCSvsnfGpF/w5E9CNxSwbpD6No= github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0/go.mod h1:qmOFXW2epJhM0qSnUUYpldc7gVz2KMQwJ/QYCDIa7XU= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= @@ -52,10 +52,10 @@ github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= -github.com/onsi/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4= -github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o= -github.com/onsi/gomega v1.29.0 h1:KIA/t2t5UBzoirT4H9tsML45GEbo3ouUnBHsCfD2tVg= -github.com/onsi/gomega v1.29.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= +github.com/onsi/ginkgo/v2 v2.16.0 h1:7q1w9frJDzninhXxjZd+Y/x54XNjG/UlRLIYPZafsPM= +github.com/onsi/ginkgo/v2 v2.16.0/go.mod h1:llBI3WDLL9Z6taip6f33H76YcWtJv+7R3HigUjbIBOs= +github.com/onsi/gomega v1.32.0 h1:JRYU78fJ1LPxlckP6Txi/EYqJvjtMrDC04/MM5XRHPk= +github.com/onsi/gomega v1.32.0/go.mod h1:a4x4gW6Pz2yK1MAmvluYme5lvYTn61afQ2ETw/8n4Lg= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM= @@ -108,8 +108,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= -golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic= +golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -119,8 +119,8 @@ golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= -golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -136,8 +136,8 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= -golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= +golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw= +golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -147,8 +147,8 @@ google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de h1: google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:5iCWqnniDlqZHrd3neWVTOwvh/v6s3232omMecelax8= google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4= google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= -google.golang.org/grpc v1.63.0 h1:WjKe+dnvABXyPJMD7KDNLxtoGk5tgk+YFWN6cBWjZE8= -google.golang.org/grpc v1.63.0/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= +google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= +google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= From 09c04bb8157096f426d0c0fb5e530367d275b66e Mon Sep 17 00:00:00 2001 From: Tanmay Jain Date: Wed, 12 Jun 2024 15:51:32 +0530 Subject: [PATCH 4/8] changing order of revoking and granting priv --- accesscontrol/access_control.go | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/accesscontrol/access_control.go b/accesscontrol/access_control.go index c05fef1..aca612d 100644 --- a/accesscontrol/access_control.go +++ b/accesscontrol/access_control.go @@ -257,49 +257,49 @@ func (roleCreate AerospikeRoleCreateUpdate) UpdateRole( privilegesToRevoke := SliceSubtract(currentPrivileges, desiredPrivileges) privilegesToGrant := SliceSubtract(desiredPrivileges, currentPrivileges) - if len(privilegesToRevoke) > 0 { - aerospikePrivileges, err := privilegeStringToAerospikePrivilege(privilegesToRevoke) + if len(privilegesToGrant) > 0 { + aerospikePrivileges, err := privilegeStringToAerospikePrivilege(privilegesToGrant) if err != nil { return fmt.Errorf( "could not update role %s: %v", roleCreate.Name, err, ) } - if err := client.RevokePrivileges( + if err := client.GrantPrivileges( adminPolicy, roleCreate.Name, aerospikePrivileges, ); err != nil { return fmt.Errorf( - "error revoking privileges for role %s: %v", roleCreate.Name, + "error granting privileges for role %s: %v", roleCreate.Name, err, ) } logger.Info( - "Revoked privileges for role", "role name", roleCreate.Name, - "privileges", privilegesToRevoke, + "Granted privileges to role", "role name", roleCreate.Name, + "privileges", privilegesToGrant, ) } - if len(privilegesToGrant) > 0 { - aerospikePrivileges, err := privilegeStringToAerospikePrivilege(privilegesToGrant) + if len(privilegesToRevoke) > 0 { + aerospikePrivileges, err := privilegeStringToAerospikePrivilege(privilegesToRevoke) if err != nil { return fmt.Errorf( "could not update role %s: %v", roleCreate.Name, err, ) } - if err := client.GrantPrivileges( + if err := client.RevokePrivileges( adminPolicy, roleCreate.Name, aerospikePrivileges, ); err != nil { return fmt.Errorf( - "error granting privileges for role %s: %v", roleCreate.Name, + "error revoking privileges for role %s: %v", roleCreate.Name, err, ) } logger.Info( - "Granted privileges to role", "role name", roleCreate.Name, - "privileges", privilegesToGrant, + "Revoked privileges for role", "role name", roleCreate.Name, + "privileges", privilegesToRevoke, ) } From 10b385feb3f6abf6bb7657d3a10e993d5f2b4cd9 Mon Sep 17 00:00:00 2001 From: Tanmay Jain Date: Mon, 26 Aug 2024 11:58:10 +0530 Subject: [PATCH 5/8] BugFix: Updating read and write quotas in cluster. --- accesscontrol/access_control.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/accesscontrol/access_control.go b/accesscontrol/access_control.go index aca612d..4075a66 100644 --- a/accesscontrol/access_control.go +++ b/accesscontrol/access_control.go @@ -314,6 +314,16 @@ func (roleCreate AerospikeRoleCreateUpdate) UpdateRole( } } + if role.ReadQuota != roleCreate.ReadQuota || role.WriteQuota != roleCreate.WriteQuota { + if err := client.SetQuotas( + adminPolicy, roleCreate.Name, roleCreate.ReadQuota, roleCreate.WriteQuota, + ); err != nil { + return fmt.Errorf( + "error setting quotas for role %s: %v", roleCreate.Name, err, + ) + } + } + logger.Info("Updated role", "role name", roleCreate.Name) return nil From ec5a19ae3dc936fd7352684d2828e7d52ed85a4a Mon Sep 17 00:00:00 2001 From: Tanmay Jain Date: Tue, 22 Oct 2024 23:53:50 +0530 Subject: [PATCH 6/8] lint --- deployment/aeroinfo.go | 10 ++++ deployment/strong_consistency.go | 83 +---------------------------- deployment/utils.go | 91 ++++++++++++++++++++++++++++++++ info/as_parser.go | 14 ----- 4 files changed, 102 insertions(+), 96 deletions(-) diff --git a/deployment/aeroinfo.go b/deployment/aeroinfo.go index e8f0db9..30fb071 100644 --- a/deployment/aeroinfo.go +++ b/deployment/aeroinfo.go @@ -100,3 +100,13 @@ func GetInfoOnHosts(log logr.Logger, policy *aero.ClientPolicy, return c.infoOnHosts(getHostIDsFromHostConns(allHosts), cmd) } + +func GetNamespaceStats(hostConns []*HostConn, policy *aero.ClientPolicy, + namespace string) (map[string]InfoResult, error) { + clHosts, err := getHostsFromHostConns(hostConns, policy) + if err != nil { + return nil, err + } + + return getNamespaceStats(clHosts, namespace) +} diff --git a/deployment/strong_consistency.go b/deployment/strong_consistency.go index 52a7570..241e0b2 100644 --- a/deployment/strong_consistency.go +++ b/deployment/strong_consistency.go @@ -184,7 +184,7 @@ func validateSCClusterNsState(scNamespacesPerHost map[*host][]string, ignorableN continue } - kvMap, err := getNamespaceStats(clHost, ns) + kvMap, err := getNamespaceStatsPerHost(clHost, ns) if err != nil { return err } @@ -256,21 +256,6 @@ func recluster(clHost *host) error { return nil } -func getNamespaceStats(clHost *host, namespace string) (map[string]string, error) { - cmd := fmt.Sprintf("namespace/%s", namespace) - - res, err := clHost.asConnInfo.asInfo.RequestInfo(cmd) - if err != nil { - return nil, err - } - - cmdOutput := res[cmd] - - clHost.log.V(1).Info("Run info command", "cmd", cmd) - - return ParseInfoIntoMap(cmdOutput, ";", "=") -} - func setRoster(clHost *host, namespace, observedNodes string) error { cmd := fmt.Sprintf("roster-set:namespace=%s;nodes=%s", namespace, observedNodes) @@ -305,36 +290,6 @@ func getRoster(clHost *host, namespace string) (map[string]string, error) { return ParseInfoIntoMap(cmdOutput, ":", "=") } -func getNamespaces(clHost *host) ([]string, error) { - cmd := CmdNamespaces - - res, err := clHost.asConnInfo.asInfo.RequestInfo(cmd) - if err != nil { - return nil, err - } - - cmdOutput := res[cmd] - - clHost.log.V(1).Info("Run info command", "cmd", cmd, "output", cmdOutput) - - if cmdOutput != "" { - return strings.Split(cmdOutput, ";"), nil - } - - return nil, nil -} - -// ContainsString check whether list contains given string -func containsString(list []string, ele string) bool { - for _, listEle := range list { - if strings.EqualFold(ele, listEle) { - return true - } - } - - return false -} - func isNodeInRoster(clHost *host, ns string) (bool, error) { nodeID, err := getNodeID(clHost) if err != nil { @@ -360,39 +315,3 @@ func isNodeInRoster(clHost *host, ns string) (bool, error) { return false, nil } - -func getNodeID(clHost *host) (string, error) { - cmd := "node" - - res, err := clHost.asConnInfo.asInfo.RequestInfo(cmd) - if err != nil { - return "", err - } - - return res[cmd], nil -} - -// ParseInfoIntoMap parses info string into a map. -func ParseInfoIntoMap(str, del, sep string) (map[string]string, error) { - m := map[string]string{} - if str == "" { - return m, nil - } - - items := strings.Split(str, del) - - for _, item := range items { - if item == "" { - continue - } - - kv := strings.Split(item, sep) - if len(kv) < 2 { - return nil, fmt.Errorf("error parsing info item %s", item) - } - - m[kv[0]] = strings.Join(kv[1:], sep) - } - - return m, nil -} diff --git a/deployment/utils.go b/deployment/utils.go index 79985ae..37fc2bb 100644 --- a/deployment/utils.go +++ b/deployment/utils.go @@ -97,3 +97,94 @@ func getHostsFromHostConns(hostConns []*HostConn, policy *as.ClientPolicy) ([]*h return hosts, nil } + +func getNamespaceStats(hosts []*host, namespace string) (map[string]InfoResult, error) { + stats := make(map[string]InfoResult, len(hosts)) + + for _, host := range hosts { + ir, err := getNamespaceStatsPerHost(host, namespace) + if err != nil { + return nil, err + } + + stats[host.id] = ir + } + + return stats, nil +} +func getNamespaceStatsPerHost(clHost *host, namespace string) (map[string]string, error) { + cmd := fmt.Sprintf("namespace/%s", namespace) + + res, err := clHost.asConnInfo.asInfo.RequestInfo(cmd) + if err != nil { + return nil, err + } + + cmdOutput := res[cmd] + clHost.log.V(1).Info("Run info command", "cmd", cmd) + + return ParseInfoIntoMap(cmdOutput, ";", "=") +} +func getNodeID(clHost *host) (string, error) { + cmd := "node" + + res, err := clHost.asConnInfo.asInfo.RequestInfo(cmd) + if err != nil { + return "", err + } + + return res[cmd], nil +} + +// ParseInfoIntoMap parses info string into a map. +func ParseInfoIntoMap(str, del, sep string) (map[string]string, error) { + m := map[string]string{} + if str == "" { + return m, nil + } + + items := strings.Split(str, del) + for _, item := range items { + if item == "" { + continue + } + + kv := strings.Split(item, sep) + if len(kv) < 2 { + return nil, fmt.Errorf("error parsing info item %s", item) + } + + m[kv[0]] = strings.Join(kv[1:], sep) + } + + return m, nil +} + +// ContainsString check whether list contains given string +func containsString(list []string, ele string) bool { + for _, listEle := range list { + if strings.EqualFold(ele, listEle) { + return true + } + } + + return false +} + +func getNamespaces(clHost *host) ([]string, error) { + cmd := CmdNamespaces + + res, err := clHost.asConnInfo.asInfo.RequestInfo(cmd) + if err != nil { + return nil, err + } + + cmdOutput := res[cmd] + if cmdOutput != "" { + clHost.log.V(1).Info("Run info command", "cmd", cmd, "output", cmdOutput) + + return strings.Split(cmdOutput, ";"), nil + } + + return nil, nil +} diff --git a/info/as_parser.go b/info/as_parser.go index b561798..4454df4 100644 --- a/info/as_parser.go +++ b/info/as_parser.go @@ -1681,17 +1681,3 @@ func parseIntoDcMap(str, del, sep string) lib.Stats { return m.ToParsedValues() } - -func contains(list []string, str string) bool { - if len(list) == 0 { - return false - } - - for _, s := range list { - if s == str { - return true - } - } - - return false -} From 7db4f4c7a2e89f36c4d0c01cd9ec54e6f37fbdce Mon Sep 17 00:00:00 2001 From: Tanmay Jain Date: Fri, 8 Nov 2024 15:39:41 +0530 Subject: [PATCH 7/8] Removing config set commands wrapper functions. --- asconfig/as_getconfig.go | 47 ++++++---------- asconfig/as_setconfig.go | 117 +++------------------------------------ asconfig/confdiff.go | 10 ++-- asconfig/constants.go | 10 ++-- asconfig/schema.go | 2 +- asconfig/utils.go | 2 +- 6 files changed, 38 insertions(+), 150 deletions(-) diff --git a/asconfig/as_getconfig.go b/asconfig/as_getconfig.go index 76efdd1..ce68818 100644 --- a/asconfig/as_getconfig.go +++ b/asconfig/as_getconfig.go @@ -4,7 +4,6 @@ import ( "fmt" "strings" - sets "github.com/deckarep/golang-set/v2" "github.com/go-logr/logr" aero "github.com/aerospike/aerospike-client-go/v7" @@ -14,54 +13,44 @@ import ( ) // GetASConfig returns the value of the given path from the aerospike config from given host. -func GetASConfig(paths []string, conn *deployment.ASConn, aerospikePolicy *aero.ClientPolicy) ( - confToReturn map[string]interface{}, err error) { +func GetASConfig(path *string, conn *deployment.ASConn, aerospikePolicy *aero.ClientPolicy) ( + confToReturn interface{}, err error) { h := aero.Host{ Name: conn.AerospikeHostName, Port: conn.AerospikePort, TLSName: conn.AerospikeTLSName, } asinfo := info.NewAsInfo(conn.Log, &h, aerospikePolicy) - ctxs := sets.NewSet[string]() - for _, path := range paths { + var ctxs []string + if path != nil { // Get the corresponding sets info also if context is namespace. - ctx := ContextKey(path) - ctxs.Add(ctx) - - if ctx == info.ConfigNamespaceContext { - ctxs.Add(info.ConfigSetContext) + ctxs = []string{ContextKey(*path)} + if ctxs[0] == info.ConfigNamespaceContext { + ctxs = append(ctxs, info.ConfigSetContext) } } - conf, err := asinfo.GetAsConfig(ctxs.ToSlice()...) + conf, err := asinfo.GetAsConfig(ctxs...) if err != nil { conn.Log.Error(err, "failed to get asconfig") return nil, err } - if len(paths) == 0 { + if path == nil { return conf, nil } - confToReturn = make(map[string]interface{}) - - for _, path := range paths { - ctx := ContextKey(path) - - ctxConf := conf[ctx] - if ctxConf == nil { - conn.Log.Info("Config is nil", "context", ctxConf) - return nil, nil - } - - ctxConf, err = traverseConfig(conn.Log, ctxConf, path, ctx) - if err != nil { - conn.Log.Error(err, "failed to traverse config") - return nil, err - } + confToReturn = conf[ctxs[0]] + if confToReturn == nil { + conn.Log.Info("Config is nil", "context", ctxs[0]) + return nil, nil + } - confToReturn[path] = ctxConf + confToReturn, err = traverseConfig(conn.Log, confToReturn, *path, ctxs[0]) + if err != nil { + conn.Log.Error(err, "failed to traverse config") + return nil, err } return confToReturn, nil diff --git a/asconfig/as_setconfig.go b/asconfig/as_setconfig.go index 48f0337..bcec498 100644 --- a/asconfig/as_setconfig.go +++ b/asconfig/as_setconfig.go @@ -22,8 +22,8 @@ const ( // convertValueToString converts the value of a config to a string. // only string type can be used to populate set-config commands with values. -func convertValueToString(v1 map[OpType]interface{}) (map[OpType][]string, error) { - valueMap := make(map[OpType][]string) +func convertValueToString(v1 map[Operation]interface{}) (map[Operation][]string, error) { + valueMap := make(map[Operation][]string) for k, v := range v1 { values := make([]string, 0) @@ -54,7 +54,7 @@ func convertValueToString(v1 map[OpType]interface{}) (map[OpType][]string, error } // createSetConfigServiceCmdList creates set-config commands for service context. -func createSetConfigServiceCmdList(tokens []string, operationValueMap map[OpType][]string) []string { +func createSetConfigServiceCmdList(tokens []string, operationValueMap map[Operation][]string) []string { val := operationValueMap[Update] cmdList := make([]string, 0, len(val)) cmd := cmdSetConfigService @@ -74,7 +74,7 @@ func createSetConfigServiceCmdList(tokens []string, operationValueMap map[OpType } // createSetConfigNetworkCmdList creates set-config commands for network context. -func createSetConfigNetworkCmdList(tokens []string, operationValueMap map[OpType][]string) []string { +func createSetConfigNetworkCmdList(tokens []string, operationValueMap map[Operation][]string) []string { val := operationValueMap[Update] cmdList := make([]string, 0, len(val)) cmd := cmdSetConfigNetwork @@ -94,7 +94,7 @@ func createSetConfigNetworkCmdList(tokens []string, operationValueMap map[OpType } // createSetConfigSecurityCmdList creates set-config commands for security context. -func createSetConfigSecurityCmdList(tokens []string, operationValueMap map[OpType][]string) []string { +func createSetConfigSecurityCmdList(tokens []string, operationValueMap map[Operation][]string) []string { cmdList := make([]string, 0, len(operationValueMap)) cmd := cmdSetConfigSecurity @@ -178,7 +178,7 @@ func createSetConfigSecurityCmdList(tokens []string, operationValueMap map[OpTyp } // createSetConfigNamespaceCmdList creates set-config commands for namespace context. -func createSetConfigNamespaceCmdList(tokens []string, operationValueMap map[OpType][]string) []string { +func createSetConfigNamespaceCmdList(tokens []string, operationValueMap map[Operation][]string) []string { val := operationValueMap[Update] cmdList := make([]string, 0, len(val)) cmd := cmdSetConfigNamespace @@ -221,7 +221,7 @@ func createSetConfigNamespaceCmdList(tokens []string, operationValueMap map[OpTy } // createLogSetCmdList creates log-set commands for logging context. -func createLogSetCmdList(tokens []string, operationValueMap map[OpType][]string, +func createLogSetCmdList(tokens []string, operationValueMap map[Operation][]string, conn deployment.ASConnInterface, aerospikePolicy *aero.ClientPolicy) ([]string, error) { val := operationValueMap[Update] cmdList := make([]string, 0, len(val)) @@ -254,7 +254,7 @@ func createLogSetCmdList(tokens []string, operationValueMap map[OpType][]string, } // createSetConfigXDRCmdList creates set-config commands for XDR context. -func createSetConfigXDRCmdList(tokens []string, operationValueMap map[OpType][]string) []string { +func createSetConfigXDRCmdList(tokens []string, operationValueMap map[Operation][]string) []string { cmdList := make([]string, 0, len(operationValueMap)) cmd := cmdSetConfigXDR prevToken := "" @@ -464,104 +464,3 @@ func rearrangeConfigMap(log logr.Logger, configMap DynamicConfigMap) []string { return finalList } - -func ValidConfigOperations() []OpType { - return []OpType{Add, Update, Remove} -} - -func (o OpType) Validate() error { - switch o { - case Add, Update, Remove: - return nil - } - - return fmt.Errorf("invalid operation type: %s, Valid operations: %v", o, ValidConfigOperations()) -} - -type ConfigOperation struct { - Operation OpType `json:"op"` - Context string `json:"context"` - Config string `json:"config"` - Value string `json:"value,omitempty"` -} - -func (p ConfigOperation) Validate() error { - return p.Operation.Validate() -} - -func CreateConfigSetCmdsUsingPatch( - configMap map[string]interface{}, conn *deployment.ASConn, aerospikePolicy *aero.ClientPolicy, version string, -) ([]string, error) { - conf, err := NewMapAsConfig(conn.Log, configMap) - if err != nil { - return nil, err - } - - flatConf := conf.GetFlatMap() - asConfChange := make(DynamicConfigMap) - - for k, v := range *flatConf { - if strings.HasSuffix(k, sep+KeyName) || strings.HasSuffix(k, sep+keyIndex) { - // skip namespace, dc, etc names - continue - } - - if ok, _ := isListField(k); ok { - // Ignore these fields as these operations are not update operations - //TODO: Should we through an error if these fields are present in the configMap patch? - continue - } - - valueMap := make(map[OpType]interface{}) - valueMap[Update] = v - asConfChange[k] = valueMap - } - - isDynamic, err := IsAllDynamicConfig(conn.Log, asConfChange, version) - if err != nil { - return nil, err - } - - if !isDynamic { - return nil, fmt.Errorf("static field has been changed, cannot change config dynamically") - } - - return CreateSetConfigCmdList(logr.Logger{}, asConfChange, conn, aerospikePolicy) -} - -func CreateConfigSetCmdsUsingOperation( - confOp ConfigOperation, conn *deployment.ASConn, aerospikePolicy *aero.ClientPolicy, version string, -) ([]string, error) { - if err := confOp.Validate(); err != nil { - return nil, err - } - // Context: security.log, Config:report-data-op, Value:test set - // Map: security.log.report-data-op:map[remove:"test set"] - path := confOp.Context + sep + confOp.Config - value := confOp.Value - - if confOp.Config == KeyName { - if confOp.Operation == Update { - return nil, fmt.Errorf("cannot update name field") - } - // Context: namespaces, Config: name, value: ns1 - // Map: namespaces.{testMem}.name:map[remove:testMem] - path = confOp.Context + sep + string(SectionNameStartChar) + value + string(SectionNameEndChar) + sep + KeyName - } - - asConfChange := make(DynamicConfigMap) - valueMap := make(map[OpType]interface{}) - valueMap[confOp.Operation] = value - asConfChange[path] = valueMap - - isDynamic, err := IsAllDynamicConfig(conn.Log, asConfChange, version) - if err != nil { - return nil, err - } - - if !isDynamic { - return nil, fmt.Errorf("static field has been changed, cannot change config dynamically") - } - - return CreateSetConfigCmdList(logr.Logger{}, asConfChange, conn, aerospikePolicy) -} diff --git a/asconfig/confdiff.go b/asconfig/confdiff.go index c27c60f..1e58d51 100644 --- a/asconfig/confdiff.go +++ b/asconfig/confdiff.go @@ -157,7 +157,7 @@ func handleMissingSection(log logr.Logger, key string, desired, current Conf, d // Whole section which has "name" as key is not present in current // If token is under "{}", then it is a named section if _, okay := current[nameKeyPath]; ReCurlyBraces.MatchString(token) && !okay { - operationValueMap := make(map[OpType]interface{}) + operationValueMap := make(map[Operation]interface{}) if desiredToActual { if _, updated := d[key]; !updated { @@ -193,7 +193,7 @@ func handlePartialMissingSection(desiredKey, ver string, current Conf, d Dynamic continue } - operationValueMap := make(map[OpType]interface{}) + operationValueMap := make(map[Operation]interface{}) // If removed subsection is of type slice, then there is no default values to be set. // eg. current = security.log.report-data-op: []string{test} // desired = security: {} @@ -218,7 +218,7 @@ func handlePartialMissingSection(desiredKey, ver string, current Conf, d Dynamic } func handleSliceFields(key string, desired Conf, d DynamicConfigMap, desiredToActual bool) { - operationValueMap := make(map[OpType]interface{}) + operationValueMap := make(map[Operation]interface{}) if reflect.ValueOf(desired[key]).Kind() == reflect.Slice { if desiredToActual { @@ -234,7 +234,7 @@ func handleSliceFields(key string, desired Conf, d DynamicConfigMap, desiredToAc } func handleValueDiff(key string, desiredValue, currentValue interface{}, d DynamicConfigMap) { - operationValueMap := make(map[OpType]interface{}) + operationValueMap := make(map[Operation]interface{}) if reflect.ValueOf(desiredValue).Kind() == reflect.Slice { currentSet := sets.NewSet[string]() @@ -366,7 +366,7 @@ func ConfDiff( return nil, err } - valueMap := make(map[OpType]interface{}) + valueMap := make(map[Operation]interface{}) valueMap[Update] = getDefaultValue(defaultMap, removedConfigKey) diffs[removedConfigKey] = valueMap } diff --git a/asconfig/constants.go b/asconfig/constants.go index 3dd2cb3..80462b4 100644 --- a/asconfig/constants.go +++ b/asconfig/constants.go @@ -1,6 +1,6 @@ package asconfig -type OpType string +type Operation string // All the aerospike config related keys const ( @@ -33,8 +33,8 @@ const ( equal = "=" colon = ":" - // Enum values for OpType - Add OpType = "add" - Remove OpType = "remove" - Update OpType = "update" + // Enum values for Operation + Add Operation = "add" + Remove Operation = "remove" + Update Operation = "update" ) diff --git a/asconfig/schema.go b/asconfig/schema.go index cf72718..99232d8 100644 --- a/asconfig/schema.go +++ b/asconfig/schema.go @@ -195,7 +195,7 @@ func IsAllDynamicConfig(log logr.Logger, configMap DynamicConfigMap, version str // IsDynamicConfig returns true if the given field is dynamically configured. func IsDynamicConfig(log logr.Logger, dynamic sets.Set[string], conf string, - valueMap map[OpType]interface{}) bool { + valueMap map[Operation]interface{}) bool { tokens := SplitKey(log, conf, sep) baseKey := tokens[len(tokens)-1] context := tokens[0] diff --git a/asconfig/utils.go b/asconfig/utils.go index 6715643..c01e065 100644 --- a/asconfig/utils.go +++ b/asconfig/utils.go @@ -1135,4 +1135,4 @@ var ReCurlyBraces = regexp.MustCompile(`^\{.*\}$`) // DynamicConfigMap is a map of config flatten keys and their operations and values // for eg: "xdr.dcs.{DC3}.node-address-ports": {Remove: []string{"1.1.2.1 3000"}} -type DynamicConfigMap map[string]map[OpType]interface{} +type DynamicConfigMap map[string]map[Operation]interface{} From b779599fcda0be9abcdda9389a817113018218d5 Mon Sep 17 00:00:00 2001 From: Tanmay Jain Date: Tue, 12 Nov 2024 12:33:58 +0530 Subject: [PATCH 8/8] addressing review comment --- accesscontrol/access_control.go | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/accesscontrol/access_control.go b/accesscontrol/access_control.go index 4075a66..d74f30d 100644 --- a/accesscontrol/access_control.go +++ b/accesscontrol/access_control.go @@ -13,9 +13,6 @@ import ( as "github.com/aerospike/aerospike-client-go/v7" ) -// logger type alias. -type logger = logr.Logger - const ( // Error marker for user not found errors. @@ -165,7 +162,7 @@ func AerospikePrivilegeToPrivilegeString(aerospikePrivileges []as.Privilege) ( type AerospikeAccessControlReconcileCmd interface { // Execute executes the command. The implementation should be idempotent. Execute( - client *as.Client, adminPolicy *as.AdminPolicy, logger logger, + client *as.Client, adminPolicy *as.AdminPolicy, logger logr.Logger, ) error } @@ -191,7 +188,7 @@ type AerospikeRoleCreateUpdate struct { // Execute creates a new Aerospike role or updates an existing one. func (roleCreate AerospikeRoleCreateUpdate) Execute( - client *as.Client, adminPolicy *as.AdminPolicy, logger logger, + client *as.Client, adminPolicy *as.AdminPolicy, logger logr.Logger, ) error { role, err := client.QueryRole(adminPolicy, roleCreate.Name) isCreate := false @@ -218,7 +215,7 @@ func (roleCreate AerospikeRoleCreateUpdate) Execute( // CreateRole creates a new Aerospike role. func (roleCreate AerospikeRoleCreateUpdate) CreateRole( - client *as.Client, adminPolicy *as.AdminPolicy, logger logger, + client *as.Client, adminPolicy *as.AdminPolicy, logger logr.Logger, ) error { logger.Info("Creating role", "role name", roleCreate.Name) @@ -242,7 +239,7 @@ func (roleCreate AerospikeRoleCreateUpdate) CreateRole( // UpdateRole updates an existing Aerospike role. func (roleCreate AerospikeRoleCreateUpdate) UpdateRole( client *as.Client, adminPolicy *as.AdminPolicy, role *as.Role, - logger logger, + logger logr.Logger, ) error { // Update the role. logger.Info("Updating role", "role name", roleCreate.Name) @@ -343,7 +340,7 @@ type AerospikeUserCreateUpdate struct { // Execute creates a new Aerospike user or updates an existing one. func (userCreate AerospikeUserCreateUpdate) Execute( - client *as.Client, adminPolicy *as.AdminPolicy, logger logger, + client *as.Client, adminPolicy *as.AdminPolicy, logger logr.Logger, ) error { user, err := client.QueryUser(adminPolicy, userCreate.Name) isCreate := false @@ -370,7 +367,7 @@ func (userCreate AerospikeUserCreateUpdate) Execute( // CreateUser creates a new Aerospike user. func (userCreate AerospikeUserCreateUpdate) CreateUser( - client *as.Client, adminPolicy *as.AdminPolicy, logger logger, + client *as.Client, adminPolicy *as.AdminPolicy, logger logr.Logger, ) error { logger.Info("Creating user", "username", userCreate.Name) @@ -394,7 +391,7 @@ func (userCreate AerospikeUserCreateUpdate) CreateUser( // UpdateUser updates an existing Aerospike user. func (userCreate AerospikeUserCreateUpdate) UpdateUser( client *as.Client, adminPolicy *as.AdminPolicy, user *as.UserRoles, - logger logger, + logger logr.Logger, ) error { // Update the user. logger.Info("Updating user", "username", userCreate.Name) @@ -458,7 +455,7 @@ type AerospikeUserDrop struct { // Execute implements dropping the user. func (userDrop AerospikeUserDrop) Execute( - client *as.Client, adminPolicy *as.AdminPolicy, logger logger, + client *as.Client, adminPolicy *as.AdminPolicy, logger logr.Logger, ) error { logger.Info("Dropping user", "username", userDrop.Name) @@ -482,7 +479,7 @@ type AerospikeRoleDrop struct { // Execute implements dropping the role. func (roleDrop AerospikeRoleDrop) Execute( - client *as.Client, adminPolicy *as.AdminPolicy, logger logger, + client *as.Client, adminPolicy *as.AdminPolicy, logger logr.Logger, ) error { logger.Info("Dropping role", "role", roleDrop.Name)