| package v2 |
| |
| import ( |
| "errors" |
| "fmt" |
| "strings" |
| ) |
| |
| type settable struct { |
| name string |
| field string |
| value string |
| } |
| |
| var ( |
| allowedSettableFieldsEnv = []string{"value"} |
| allowedSettableFieldsArgs = []string{"value"} |
| allowedSettableFieldsDevices = []string{"path"} |
| allowedSettableFieldsMounts = []string{"source"} |
| |
| errMultipleFields = errors.New("multiple fields are settable, one must be specified") |
| errInvalidFormat = errors.New("invalid format, must be <name>[.<field>][=<value>]") |
| ) |
| |
| func newSettables(args []string) ([]settable, error) { |
| sets := make([]settable, 0, len(args)) |
| for _, arg := range args { |
| set, err := newSettable(arg) |
| if err != nil { |
| return nil, err |
| } |
| sets = append(sets, set) |
| } |
| return sets, nil |
| } |
| |
| func newSettable(arg string) (settable, error) { |
| var set settable |
| if i := strings.Index(arg, "="); i == 0 { |
| return set, errInvalidFormat |
| } else if i < 0 { |
| set.name = arg |
| } else { |
| set.name = arg[:i] |
| set.value = arg[i+1:] |
| } |
| |
| if i := strings.LastIndex(set.name, "."); i > 0 { |
| set.field = set.name[i+1:] |
| set.name = arg[:i] |
| } |
| |
| return set, nil |
| } |
| |
| // prettyName return name.field if there is a field, otherwise name. |
| func (set *settable) prettyName() string { |
| if set.field != "" { |
| return fmt.Sprintf("%s.%s", set.name, set.field) |
| } |
| return set.name |
| } |
| |
| func (set *settable) isSettable(allowedSettableFields []string, settable []string) (bool, error) { |
| if set.field == "" { |
| if len(settable) == 1 { |
| // if field is not specified and there only one settable, default to it. |
| set.field = settable[0] |
| } else if len(settable) > 1 { |
| return false, errMultipleFields |
| } |
| } |
| |
| isAllowed := false |
| for _, allowedSettableField := range allowedSettableFields { |
| if set.field == allowedSettableField { |
| isAllowed = true |
| break |
| } |
| } |
| |
| if isAllowed { |
| for _, settableField := range settable { |
| if set.field == settableField { |
| return true, nil |
| } |
| } |
| } |
| |
| return false, nil |
| } |
| |
| func updateSettingsEnv(env *[]string, set *settable) { |
| for i, e := range *env { |
| if parts := strings.SplitN(e, "=", 2); parts[0] == set.name { |
| (*env)[i] = fmt.Sprintf("%s=%s", set.name, set.value) |
| return |
| } |
| } |
| |
| *env = append(*env, fmt.Sprintf("%s=%s", set.name, set.value)) |
| } |