github.com/kaisenlinux/docker.io@v0.0.0-20230510090727-ea55db55fac7/swarmkit/cmd/swarmctl/service/flagparser/tmpfs.go (about) 1 package flagparser 2 3 import ( 4 "os" 5 "path" 6 "strconv" 7 "strings" 8 9 "github.com/docker/swarmkit/api" 10 "github.com/pkg/errors" 11 "github.com/spf13/pflag" 12 ) 13 14 // parseTmpfs supports a simple tmpfs decl, similar to docker run. 15 // 16 // This should go away. 17 func parseTmpfs(flags *pflag.FlagSet, spec *api.ServiceSpec) error { 18 if flags.Changed("tmpfs") { 19 tmpfss, err := flags.GetStringSlice("tmpfs") 20 if err != nil { 21 return err 22 } 23 24 container := spec.Task.GetContainer() 25 // TODO(stevvooe): Nasty inline parsing code, replace with mount syntax. 26 for _, tmpfs := range tmpfss { 27 parts := strings.SplitN(tmpfs, ":", 2) 28 29 if len(parts) < 1 { 30 return errors.Errorf("invalid mount spec: %v", tmpfs) 31 } 32 33 if len(parts[0]) == 0 || !path.IsAbs(parts[0]) { 34 return errors.Errorf("invalid mount spec: %v", tmpfs) 35 } 36 37 m := api.Mount{ 38 Type: api.MountTypeTmpfs, 39 Target: parts[0], 40 } 41 42 if len(parts) == 2 { 43 if strings.Contains(parts[1], ":") { 44 // repeated colon is illegal 45 return errors.Errorf("invalid mount spec: %v", tmpfs) 46 } 47 48 // BUG(stevvooe): Cobra stringslice actually doesn't correctly 49 // handle comma separated values, so multiple flags aren't 50 // really supported. We'll have to replace StringSlice with a 51 // type that doesn't use the csv parser. This is good enough 52 // for now. 53 54 flags := strings.Split(parts[1], ",") 55 var opts api.Mount_TmpfsOptions 56 for _, flag := range flags { 57 switch { 58 case strings.HasPrefix(flag, "size="): 59 meat := strings.TrimPrefix(flag, "size=") 60 61 // try to parse this into bytes 62 i, err := strconv.ParseInt(meat, 10, 64) 63 if err != nil { 64 // remove suffix and try again 65 suffix := meat[len(meat)-1] 66 meat = meat[:len(meat)-1] 67 var multiplier int64 68 switch suffix { 69 case 'g': 70 multiplier = 1 << 30 71 case 'm': 72 multiplier = 1 << 20 73 case 'k': 74 multiplier = 1 << 10 75 default: 76 return errors.Errorf("invalid size format: %v", flag) 77 } 78 79 // reparse the meat 80 var err error 81 i, err = strconv.ParseInt(meat, 10, 64) 82 if err != nil { 83 return err 84 } 85 86 i *= multiplier 87 } 88 opts.SizeBytes = i 89 case strings.HasPrefix(flag, "mode="): 90 meat := strings.TrimPrefix(flag, "mode=") 91 i, err := strconv.ParseInt(meat, 8, 32) 92 if err != nil { 93 return err 94 } 95 opts.Mode = os.FileMode(i) 96 case flag == "ro": 97 m.ReadOnly = true 98 case flag == "rw": 99 m.ReadOnly = false 100 case flag == "exec": 101 opts.Options = "exec" 102 case flag == "noexec": 103 opts.Options = "noexec" 104 default: 105 return errors.New("unsupported flag") 106 } 107 } 108 m.TmpfsOptions = &opts 109 } 110 111 container.Mounts = append(container.Mounts, m) 112 } 113 } 114 115 return nil 116 }