github.1git.de/docker/cli@v26.1.3+incompatible/cli/command/swarm/ipnet_slice.go (about) 1 package swarm 2 3 import ( 4 "bytes" 5 "encoding/csv" 6 "fmt" 7 "io" 8 "net" 9 "strings" 10 ) 11 12 // -- ipNetSlice Value 13 type ipNetSliceValue struct { 14 value *[]net.IPNet 15 changed bool 16 } 17 18 func newIPNetSliceValue(val []net.IPNet, p *[]net.IPNet) *ipNetSliceValue { 19 ipnsv := new(ipNetSliceValue) 20 ipnsv.value = p 21 *ipnsv.value = val 22 return ipnsv 23 } 24 25 // Set converts, and assigns, the comma-separated IPNet argument string representation as the []net.IPNet value of this flag. 26 // If Set is called on a flag that already has a []net.IPNet assigned, the newly converted values will be appended. 27 func (s *ipNetSliceValue) Set(val string) error { 28 // remove all quote characters 29 rmQuote := strings.NewReplacer(`"`, "", `'`, "", "`", "") 30 31 // read flag arguments with CSV parser 32 ipNetStrSlice, err := readAsCSV(rmQuote.Replace(val)) 33 if err != nil && err != io.EOF { 34 return err 35 } 36 37 // parse ip values into slice 38 out := make([]net.IPNet, 0, len(ipNetStrSlice)) 39 for _, ipNetStr := range ipNetStrSlice { 40 _, n, err := net.ParseCIDR(strings.TrimSpace(ipNetStr)) 41 if err != nil { 42 return fmt.Errorf("invalid string being converted to CIDR: %s", ipNetStr) 43 } 44 out = append(out, *n) 45 } 46 47 if !s.changed { 48 *s.value = out 49 } else { 50 *s.value = append(*s.value, out...) 51 } 52 53 s.changed = true 54 55 return nil 56 } 57 58 // Type returns a string that uniquely represents this flag's type. 59 func (s *ipNetSliceValue) Type() string { 60 return "ipNetSlice" 61 } 62 63 // String defines a "native" format for this net.IPNet slice flag value. 64 func (s *ipNetSliceValue) String() string { 65 ipNetStrSlice := make([]string, len(*s.value)) 66 for i, n := range *s.value { 67 ipNetStrSlice[i] = n.String() 68 } 69 70 out, _ := writeAsCSV(ipNetStrSlice) 71 return "[" + out + "]" 72 } 73 74 func readAsCSV(val string) ([]string, error) { 75 if val == "" { 76 return []string{}, nil 77 } 78 stringReader := strings.NewReader(val) 79 csvReader := csv.NewReader(stringReader) 80 return csvReader.Read() 81 } 82 83 func writeAsCSV(vals []string) (string, error) { 84 b := &bytes.Buffer{} 85 w := csv.NewWriter(b) 86 err := w.Write(vals) 87 if err != nil { 88 return "", err 89 } 90 w.Flush() 91 return strings.TrimSuffix(b.String(), "\n"), nil 92 }