Skip to content

Commit

Permalink
Pushing config set commands wrapper functions for future reference.
Browse files Browse the repository at this point in the history
  • Loading branch information
tanmayja committed Nov 8, 2024
1 parent c22db49 commit 2ff2477
Show file tree
Hide file tree
Showing 6 changed files with 152 additions and 39 deletions.
47 changes: 29 additions & 18 deletions asconfig/as_getconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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]()

for _, path := range paths {
ctx := ContextKey(path)
ctxs.Add(ctx)

var ctxs []string
if path != nil {
// Get the corresponding sets info also if context is namespace.
ctxs = []string{ContextKey(*path)}
if ctxs[0] == info.ConfigNamespaceContext {
ctxs = append(ctxs, info.ConfigSetContext)
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
Expand Down
120 changes: 111 additions & 9 deletions asconfig/as_setconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ import (
"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"
"github.com/go-logr/logr"
)

const (
Expand All @@ -22,8 +23,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)
Expand Down Expand Up @@ -54,7 +55,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
Expand All @@ -74,7 +75,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
Expand All @@ -94,7 +95,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

Expand Down Expand Up @@ -178,7 +179,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
Expand Down Expand Up @@ -221,7 +222,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))
Expand Down Expand Up @@ -254,7 +255,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 := ""
Expand Down Expand Up @@ -464,3 +465,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(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)
}
10 changes: 5 additions & 5 deletions asconfig/confdiff.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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: {}
Expand All @@ -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 {
Expand All @@ -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]()
Expand Down Expand Up @@ -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
}
Expand Down
10 changes: 5 additions & 5 deletions asconfig/constants.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package asconfig

type Operation string
type OpType string

// All the aerospike config related keys
const (
Expand Down Expand Up @@ -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"
)
2 changes: 1 addition & 1 deletion asconfig/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
2 changes: 1 addition & 1 deletion asconfig/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -1136,4 +1136,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{}

0 comments on commit 2ff2477

Please sign in to comment.