github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/admin/commands/common/set_config.go (about) 1 package common 2 3 import ( 4 "context" 5 "fmt" 6 7 "github.com/onflow/flow-go/admin" 8 "github.com/onflow/flow-go/admin/commands" 9 "github.com/onflow/flow-go/module/updatable_configs" 10 ) 11 12 var _ commands.AdminCommand = (*SetConfigCommand)(nil) 13 14 // SetConfigCommand is an admin command which enables setting any config field which 15 // has registered as dynamically updatable with the config Manager. 16 type SetConfigCommand struct { 17 configs *updatable_configs.Manager 18 } 19 20 func NewSetConfigCommand(configs *updatable_configs.Manager) *SetConfigCommand { 21 return &SetConfigCommand{ 22 configs: configs, 23 } 24 } 25 26 // validatedSetConfigData represents a set-config admin request which has passed basic validation. 27 // It contains the config field to update, and the config value. 28 type validatedSetConfigData struct { 29 field updatable_configs.Field 30 value any 31 } 32 33 func (s *SetConfigCommand) Handler(_ context.Context, req *admin.CommandRequest) (interface{}, error) { 34 validatedReq := req.ValidatorData.(validatedSetConfigData) 35 36 oldValue := validatedReq.field.Get() 37 38 err := validatedReq.field.Set(validatedReq.value) 39 if err != nil { 40 if updatable_configs.IsValidationError(err) { 41 return nil, fmt.Errorf("config update failed due to invalid input: %w", err) 42 } 43 return nil, fmt.Errorf("unexpected error setting config field %s: %w", validatedReq.field.Name, err) 44 } 45 46 res := map[string]any{ 47 "oldValue": oldValue, 48 "newValue": validatedReq.value, 49 } 50 51 return res, nil 52 } 53 54 // Validator validates the request. 55 // Returns admin.InvalidAdminReqError for invalid/malformed requests. 56 func (s *SetConfigCommand) Validator(req *admin.CommandRequest) error { 57 mval, ok := req.Data.(map[string]any) 58 if !ok { 59 return admin.NewInvalidAdminReqFormatError("expected map[string]any") 60 } 61 62 if len(mval) != 1 { 63 return admin.NewInvalidAdminReqErrorf("data field must have 1 entry, got %d", len(mval)) 64 } 65 66 var ( 67 configName string 68 configValue any 69 ) 70 // select the single name/value pair from the map 71 for k, v := range mval { 72 configName = k 73 configValue = v 74 break 75 } 76 77 field, ok := s.configs.GetField(configName) 78 if !ok { 79 return admin.NewInvalidAdminReqErrorf("unknown config field: %s", configName) 80 } 81 82 // we have found a corresponding updatable config field, set it in the ValidatorData 83 // field - we will attempt to apply the change in Handler 84 req.ValidatorData = validatedSetConfigData{ 85 field: field, 86 value: configValue, 87 } 88 return nil 89 }