github.com/panekj/cli@v0.0.0-20230304125325-467dd2f3797e/opts/config.go (about) 1 package opts 2 3 import ( 4 "encoding/csv" 5 "fmt" 6 "os" 7 "strconv" 8 "strings" 9 10 swarmtypes "github.com/docker/docker/api/types/swarm" 11 ) 12 13 // ConfigOpt is a Value type for parsing configs 14 type ConfigOpt struct { 15 values []*swarmtypes.ConfigReference 16 } 17 18 // Set a new config value 19 func (o *ConfigOpt) Set(value string) error { 20 csvReader := csv.NewReader(strings.NewReader(value)) 21 fields, err := csvReader.Read() 22 if err != nil { 23 return err 24 } 25 26 options := &swarmtypes.ConfigReference{ 27 File: &swarmtypes.ConfigReferenceFileTarget{ 28 UID: "0", 29 GID: "0", 30 Mode: 0o444, 31 }, 32 } 33 34 // support a simple syntax of --config foo 35 if len(fields) == 1 && !strings.Contains(fields[0], "=") { 36 options.File.Name = fields[0] 37 options.ConfigName = fields[0] 38 o.values = append(o.values, options) 39 return nil 40 } 41 42 for _, field := range fields { 43 key, val, ok := strings.Cut(field, "=") 44 if !ok || key == "" { 45 return fmt.Errorf("invalid field '%s' must be a key=value pair", field) 46 } 47 48 // TODO(thaJeztah): these options should not be case-insensitive. 49 switch strings.ToLower(key) { 50 case "source", "src": 51 options.ConfigName = val 52 case "target": 53 options.File.Name = val 54 case "uid": 55 options.File.UID = val 56 case "gid": 57 options.File.GID = val 58 case "mode": 59 m, err := strconv.ParseUint(val, 0, 32) 60 if err != nil { 61 return fmt.Errorf("invalid mode specified: %v", err) 62 } 63 64 options.File.Mode = os.FileMode(m) 65 default: 66 return fmt.Errorf("invalid field in config request: %s", key) 67 } 68 } 69 70 if options.ConfigName == "" { 71 return fmt.Errorf("source is required") 72 } 73 if options.File.Name == "" { 74 options.File.Name = options.ConfigName 75 } 76 77 o.values = append(o.values, options) 78 return nil 79 } 80 81 // Type returns the type of this option 82 func (o *ConfigOpt) Type() string { 83 return "config" 84 } 85 86 // String returns a string repr of this option 87 func (o *ConfigOpt) String() string { 88 configs := []string{} 89 for _, config := range o.values { 90 repr := fmt.Sprintf("%s -> %s", config.ConfigName, config.File.Name) 91 configs = append(configs, repr) 92 } 93 return strings.Join(configs, ", ") 94 } 95 96 // Value returns the config requests 97 func (o *ConfigOpt) Value() []*swarmtypes.ConfigReference { 98 return o.values 99 }