File: namespaces.go

package info (click to toggle)
podman 5.7.0%2Bds2-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 23,824 kB
  • sloc: sh: 4,700; python: 2,798; perl: 1,885; ansic: 1,484; makefile: 977; ruby: 42; csh: 8
file content (234 lines) | stat: -rw-r--r-- 6,407 bytes parent folder | download
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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
package namespaces

import (
	"fmt"
	"strconv"
	"strings"
)

const (
	bridgeType    = "bridge"
	containerType = "container"
	defaultType   = "default"
	hostType      = "host"
	noneType      = "none"
	nsType        = "ns"
	podType       = "pod"
	privateType   = "private"
	shareableType = "shareable"
	slirpType     = "slirp4netns"
	pastaType     = "pasta"
)

// KeepIDUserNsOptions defines how to create a user namespace using keep-id.
type KeepIDUserNsOptions struct {
	// UID is the target uid in the user namespace.
	UID *uint32
	// GID is the target uid in the user namespace.
	GID *uint32
	// MaxSize is the maximum size of the user namespace.
	MaxSize *uint32
}

// UsernsMode represents userns mode in the container.
type UsernsMode string

// IsHost indicates whether the container uses the host's userns.
func (n UsernsMode) IsHost() bool {
	return n == hostType
}

// IsKeepID indicates whether container uses a mapping where the (uid, gid) on the host is kept inside of the namespace.
func (n UsernsMode) IsKeepID() bool {
	parts := strings.Split(string(n), ":")
	return parts[0] == "keep-id"
}

// IsNoMap indicates whether container uses a mapping where the (uid, gid) on the host is not present in the namespace.
func (n UsernsMode) IsNoMap() bool {
	return n == "nomap"
}

// IsAuto indicates whether container uses the "auto" userns mode.
func (n UsernsMode) IsAuto() bool {
	parts := strings.Split(string(n), ":")
	return parts[0] == "auto"
}

// IsDefaultValue indicates whether the user namespace has the default value.
func (n UsernsMode) IsDefaultValue() bool {
	return n == "" || n == defaultType
}

// GetKeepIDOptions returns a KeepIDUserNsOptions with the settings to keepIDmatically set up
// a user namespace.
func (n UsernsMode) GetKeepIDOptions() (*KeepIDUserNsOptions, error) {
	nsmode, nsopts, hasOpts := strings.Cut(string(n), ":")
	if nsmode != "keep-id" {
		return nil, fmt.Errorf("wrong user namespace mode")
	}
	options := KeepIDUserNsOptions{}
	if !hasOpts {
		return &options, nil
	}
	for o := range strings.SplitSeq(nsopts, ",") {
		opt, val, hasVal := strings.Cut(o, "=")
		if !hasVal {
			return nil, fmt.Errorf("invalid option specified: %q", o)
		}
		switch opt {
		case "uid":
			s, err := strconv.ParseUint(val, 10, 32)
			if err != nil {
				return nil, err
			}
			v := uint32(s)
			options.UID = &v
		case "gid":
			s, err := strconv.ParseUint(val, 10, 32)
			if err != nil {
				return nil, err
			}
			v := uint32(s)
			options.GID = &v
		case "size":
			s, err := strconv.ParseUint(val, 10, 32)
			if err != nil {
				return nil, err
			}
			v := uint32(s)
			options.MaxSize = &v
		default:
			return nil, fmt.Errorf("unknown option specified: %q", opt)
		}
	}
	return &options, nil
}

// IsPrivate indicates whether the container uses the a private userns.
func (n UsernsMode) IsPrivate() bool {
	return !n.IsHost() && !n.IsContainer()
}

// Valid indicates whether the userns is valid.
func (n UsernsMode) Valid() bool {
	parts := strings.Split(string(n), ":")
	switch mode := parts[0]; mode {
	case "", privateType, hostType, "keep-id", nsType, "auto", "nomap":
	case containerType:
		if len(parts) != 2 || parts[1] == "" {
			return false
		}
	default:
		return false
	}
	return true
}

// IsNS indicates a userns namespace passed in by path (ns:<path>)
func (n UsernsMode) IsNS() bool {
	return strings.HasPrefix(string(n), "ns:")
}

// NS gets the path associated with a ns:<path> userns ns
func (n UsernsMode) NS() string {
	_, path, _ := strings.Cut(string(n), ":")
	return path
}

// IsContainer indicates whether container uses a container userns.
func (n UsernsMode) IsContainer() bool {
	typ, _, hasName := strings.Cut(string(n), ":")
	return hasName && typ == containerType
}

// Container is the id of the container which network this container is connected to.
func (n UsernsMode) Container() string {
	typ, name, hasName := strings.Cut(string(n), ":")
	if hasName && typ == containerType {
		return name
	}
	return ""
}

// NetworkMode represents the container network stack.
type NetworkMode string

// IsNone indicates whether container isn't using a network stack.
func (n NetworkMode) IsNone() bool {
	return n == noneType
}

// IsHost indicates whether the container uses the host's network stack.
func (n NetworkMode) IsHost() bool {
	return n == hostType
}

// IsDefault indicates whether container uses the default network stack.
func (n NetworkMode) IsDefault() bool {
	return n == defaultType
}

// IsPrivate indicates whether container uses its private network stack.
func (n NetworkMode) IsPrivate() bool {
	return !n.IsHost() && !n.IsContainer()
}

// IsContainer indicates whether container uses a container network stack.
func (n NetworkMode) IsContainer() bool {
	typ, _, hasName := strings.Cut(string(n), ":")
	return hasName && typ == containerType
}

// Container is the id of the container which network this container is connected to.
func (n NetworkMode) Container() string {
	typ, name, hasName := strings.Cut(string(n), ":")
	if hasName && typ == containerType {
		return name
	}
	return ""
}

// UserDefined indicates user-created network
func (n NetworkMode) UserDefined() string {
	if n.IsUserDefined() {
		return string(n)
	}
	return ""
}

// IsBridge indicates whether container uses the bridge network stack
func (n NetworkMode) IsBridge() bool {
	return n == bridgeType
}

// IsSlirp4netns indicates if we are running a rootless network stack
func (n NetworkMode) IsSlirp4netns() bool {
	return n == slirpType || strings.HasPrefix(string(n), slirpType+":")
}

// IsPasta indicates if we are running a rootless network stack using pasta
func (n NetworkMode) IsPasta() bool {
	return n == pastaType || strings.HasPrefix(string(n), pastaType+":")
}

// IsNS indicates a network namespace passed in by path (ns:<path>)
func (n NetworkMode) IsNS() bool {
	return strings.HasPrefix(string(n), nsType)
}

// NS gets the path associated with a ns:<path> network ns
func (n NetworkMode) NS() string {
	_, path, _ := strings.Cut(string(n), ":")
	return path
}

// IsPod returns whether the network refers to pod networking
func (n NetworkMode) IsPod() bool {
	return n == podType
}

// IsUserDefined indicates user-created network
func (n NetworkMode) IsUserDefined() bool {
	return !n.IsDefault() && !n.IsBridge() && !n.IsHost() && !n.IsNone() && !n.IsContainer() && !n.IsSlirp4netns() && !n.IsPasta() && !n.IsNS()
}