File: tmpfs.go

package info (click to toggle)
docker.io 20.10.24%2Bdfsg1-1%2Bdeb12u1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 60,824 kB
  • sloc: sh: 5,621; makefile: 593; ansic: 179; python: 162; asm: 7
file content (116 lines) | stat: -rw-r--r-- 2,861 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
package flagparser

import (
	"os"
	"path"
	"strconv"
	"strings"

	"github.com/docker/swarmkit/api"
	"github.com/pkg/errors"
	"github.com/spf13/pflag"
)

// parseTmpfs supports a simple tmpfs decl, similar to docker run.
//
// This should go away.
func parseTmpfs(flags *pflag.FlagSet, spec *api.ServiceSpec) error {
	if flags.Changed("tmpfs") {
		tmpfss, err := flags.GetStringSlice("tmpfs")
		if err != nil {
			return err
		}

		container := spec.Task.GetContainer()
		// TODO(stevvooe): Nasty inline parsing code, replace with mount syntax.
		for _, tmpfs := range tmpfss {
			parts := strings.SplitN(tmpfs, ":", 2)

			if len(parts) < 1 {
				return errors.Errorf("invalid mount spec: %v", tmpfs)
			}

			if len(parts[0]) == 0 || !path.IsAbs(parts[0]) {
				return errors.Errorf("invalid mount spec: %v", tmpfs)
			}

			m := api.Mount{
				Type:   api.MountTypeTmpfs,
				Target: parts[0],
			}

			if len(parts) == 2 {
				if strings.Contains(parts[1], ":") {
					// repeated colon is illegal
					return errors.Errorf("invalid mount spec: %v", tmpfs)
				}

				// BUG(stevvooe): Cobra stringslice actually doesn't correctly
				// handle comma separated values, so multiple flags aren't
				// really supported. We'll have to replace StringSlice with a
				// type that doesn't use the csv parser. This is good enough
				// for now.

				flags := strings.Split(parts[1], ",")
				var opts api.Mount_TmpfsOptions
				for _, flag := range flags {
					switch {
					case strings.HasPrefix(flag, "size="):
						meat := strings.TrimPrefix(flag, "size=")

						// try to parse this into bytes
						i, err := strconv.ParseInt(meat, 10, 64)
						if err != nil {
							// remove suffix and try again
							suffix := meat[len(meat)-1]
							meat = meat[:len(meat)-1]
							var multiplier int64
							switch suffix {
							case 'g':
								multiplier = 1 << 30
							case 'm':
								multiplier = 1 << 20
							case 'k':
								multiplier = 1 << 10
							default:
								return errors.Errorf("invalid size format: %v", flag)
							}

							// reparse the meat
							var err error
							i, err = strconv.ParseInt(meat, 10, 64)
							if err != nil {
								return err
							}

							i *= multiplier
						}
						opts.SizeBytes = i
					case strings.HasPrefix(flag, "mode="):
						meat := strings.TrimPrefix(flag, "mode=")
						i, err := strconv.ParseInt(meat, 8, 32)
						if err != nil {
							return err
						}
						opts.Mode = os.FileMode(i)
					case flag == "ro":
						m.ReadOnly = true
					case flag == "rw":
						m.ReadOnly = false
					case flag == "exec":
						opts.Options = "exec"
					case flag == "noexec":
						opts.Options = "noexec"
					default:
						return errors.New("unsupported flag")
					}
				}
				m.TmpfsOptions = &opts
			}

			container.Mounts = append(container.Mounts, m)
		}
	}

	return nil
}