podman

Форк
0
/
container_validate.go 
185 строк · 7.6 Кб
1
//go:build !remote
2

3
package libpod
4

5
import (
6
	"fmt"
7

8
	"github.com/containers/image/v5/docker"
9
	"github.com/containers/image/v5/pkg/shortnames"
10
	"github.com/containers/image/v5/transports/alltransports"
11
	"github.com/containers/podman/v5/libpod/define"
12
	spec "github.com/opencontainers/runtime-spec/specs-go"
13
)
14

15
// Validate that the configuration of a container is valid.
16
func (c *Container) validate() error {
17
	imageIDSet := c.config.RootfsImageID != ""
18
	imageNameSet := c.config.RootfsImageName != ""
19
	rootfsSet := c.config.Rootfs != ""
20

21
	// If one of RootfsImageIDor RootfsImageName are set, both must be set.
22
	if (imageIDSet || imageNameSet) && !(imageIDSet && imageNameSet) {
23
		return fmt.Errorf("both RootfsImageName and RootfsImageID must be set if either is set: %w", define.ErrInvalidArg)
24
	}
25

26
	// Cannot set RootfsImageID and Rootfs at the same time
27
	if imageIDSet && rootfsSet {
28
		return fmt.Errorf("cannot set both an image ID and rootfs for a container: %w", define.ErrInvalidArg)
29
	}
30

31
	// Must set at least one of RootfsImageID or Rootfs
32
	if !(imageIDSet || rootfsSet) {
33
		return fmt.Errorf("must set root filesystem source to either image or rootfs: %w", define.ErrInvalidArg)
34
	}
35

36
	// A container cannot be marked as an infra and service container at
37
	// the same time.
38
	if c.IsInfra() && c.IsService() {
39
		return fmt.Errorf("cannot be infra and service container at the same time: %w", define.ErrInvalidArg)
40
	}
41

42
	// Cannot make a network namespace if we are joining another container's
43
	// network namespace
44
	if c.config.CreateNetNS && c.config.NetNsCtr != "" {
45
		return fmt.Errorf("cannot both create a network namespace and join another container's network namespace: %w", define.ErrInvalidArg)
46
	}
47

48
	if c.config.CgroupsMode == cgroupSplit && c.config.CgroupParent != "" {
49
		return fmt.Errorf("cannot specify --cgroup-mode=split with a cgroup-parent: %w", define.ErrInvalidArg)
50
	}
51

52
	// Not creating cgroups has a number of requirements, mostly related to
53
	// the PID namespace.
54
	if c.config.NoCgroups || c.config.CgroupsMode == "disabled" {
55
		if c.config.PIDNsCtr != "" {
56
			return fmt.Errorf("cannot join another container's PID namespace if not creating cgroups: %w", define.ErrInvalidArg)
57
		}
58

59
		if c.config.CgroupParent != "" {
60
			return fmt.Errorf("cannot set cgroup parent if not creating cgroups: %w", define.ErrInvalidArg)
61
		}
62

63
		// Ensure we have a PID namespace
64
		if c.config.Spec.Linux == nil {
65
			return fmt.Errorf("must provide Linux namespace configuration in OCI spec when using NoCgroups: %w", define.ErrInvalidArg)
66
		}
67
		foundPid := false
68
		for _, ns := range c.config.Spec.Linux.Namespaces {
69
			if ns.Type == spec.PIDNamespace {
70
				foundPid = true
71
				if ns.Path != "" {
72
					return fmt.Errorf("containers not creating Cgroups must create a private PID namespace - cannot use another: %w", define.ErrInvalidArg)
73
				}
74
				break
75
			}
76
		}
77
		if !foundPid {
78
			return fmt.Errorf("containers not creating Cgroups must create a private PID namespace: %w", define.ErrInvalidArg)
79
		}
80
	}
81

82
	// Can only set static IP or MAC is creating a network namespace.
83
	if !c.config.CreateNetNS && (c.config.StaticIP != nil || c.config.StaticMAC != nil) {
84
		return fmt.Errorf("cannot set static IP or MAC address if not creating a network namespace: %w", define.ErrInvalidArg)
85
	}
86

87
	// Cannot set static IP or MAC if joining >1 network.
88
	if len(c.config.Networks) > 1 && (c.config.StaticIP != nil || c.config.StaticMAC != nil) {
89
		return fmt.Errorf("cannot set static IP or MAC address if joining more than one network: %w", define.ErrInvalidArg)
90
	}
91

92
	// Using image resolv.conf conflicts with various DNS settings.
93
	if c.config.UseImageResolvConf &&
94
		(len(c.config.DNSSearch) > 0 || len(c.config.DNSServer) > 0 ||
95
			len(c.config.DNSOption) > 0) {
96
		return fmt.Errorf("cannot configure DNS options if using image's resolv.conf: %w", define.ErrInvalidArg)
97
	}
98

99
	if c.config.UseImageHosts && len(c.config.HostAdd) > 0 {
100
		return fmt.Errorf("cannot add to /etc/hosts if using image's /etc/hosts: %w", define.ErrInvalidArg)
101
	}
102

103
	// Check named volume, overlay volume and image volume destination conflist
104
	destinations := make(map[string]bool)
105
	for _, vol := range c.config.NamedVolumes {
106
		// Don't check if they already exist.
107
		// If they don't we will automatically create them.
108
		if _, ok := destinations[vol.Dest]; ok {
109
			return fmt.Errorf("two volumes found with destination %s: %w", vol.Dest, define.ErrInvalidArg)
110
		}
111
		destinations[vol.Dest] = true
112
	}
113
	for _, vol := range c.config.OverlayVolumes {
114
		// Don't check if they already exist.
115
		// If they don't we will automatically create them.
116
		if _, ok := destinations[vol.Dest]; ok {
117
			return fmt.Errorf("two volumes found with destination %s: %w", vol.Dest, define.ErrInvalidArg)
118
		}
119
		destinations[vol.Dest] = true
120
	}
121
	for _, vol := range c.config.ImageVolumes {
122
		// Don't check if they already exist.
123
		// If they don't we will automatically create them.
124
		if _, ok := destinations[vol.Dest]; ok {
125
			return fmt.Errorf("two volumes found with destination %s: %w", vol.Dest, define.ErrInvalidArg)
126
		}
127
		destinations[vol.Dest] = true
128
	}
129

130
	// If User in the OCI spec is set, require that c.config.User is set for
131
	// security reasons (a lot of our code relies on c.config.User).
132
	if c.config.User == "" && (c.config.Spec.Process.User.UID != 0 || c.config.Spec.Process.User.GID != 0) {
133
		return fmt.Errorf("please set User explicitly via WithUser() instead of in OCI spec directly: %w", define.ErrInvalidArg)
134
	}
135

136
	// Init-ctrs must be used inside a Pod.  Check if an init container type is
137
	// passed and if no pod is passed
138
	if len(c.config.InitContainerType) > 0 && len(c.config.Pod) < 1 {
139
		return fmt.Errorf("init containers must be created in a pod: %w", define.ErrInvalidArg)
140
	}
141

142
	if c.config.SdNotifyMode == define.SdNotifyModeIgnore && len(c.config.SdNotifySocket) > 0 {
143
		return fmt.Errorf("cannot set sd-notify socket %q with sd-notify mode %q", c.config.SdNotifySocket, c.config.SdNotifyMode)
144
	}
145

146
	if c.config.HealthCheckOnFailureAction != define.HealthCheckOnFailureActionNone && c.config.HealthCheckConfig == nil {
147
		return fmt.Errorf("cannot set on-failure action to %s without a health check", c.config.HealthCheckOnFailureAction.String())
148
	}
149

150
	if value, exists := c.config.Labels[define.AutoUpdateLabel]; exists {
151
		// TODO: we cannot reference pkg/autoupdate here due to
152
		// circular dependencies.  It's worth considering moving the
153
		// auto-update logic into the libpod package.
154
		if value == "registry" || value == "image" {
155
			if err := validateAutoUpdateImageReference(c.config.RawImageName); err != nil {
156
				return err
157
			}
158
		}
159
	}
160

161
	// Cannot set startup HC without a healthcheck
162
	if c.config.HealthCheckConfig == nil && c.config.StartupHealthCheckConfig != nil {
163
		return fmt.Errorf("cannot set a startup healthcheck when there is no regular healthcheck: %w", define.ErrInvalidArg)
164
	}
165

166
	return nil
167
}
168

169
// validateAutoUpdateImageReference checks if the specified imageName is a
170
// fully-qualified image reference to the docker transport. Such a reference
171
// includes a domain, name and tag (e.g., quay.io/podman/stable:latest).  The
172
// reference may also be prefixed with "docker://" explicitly indicating that
173
// it's a reference to the docker transport.
174
func validateAutoUpdateImageReference(imageName string) error {
175
	// Make sure the input image is a docker.
176
	imageRef, err := alltransports.ParseImageName(imageName)
177
	if err == nil && imageRef.Transport().Name() != docker.Transport.Name() {
178
		return fmt.Errorf("auto updates require the docker image transport but image is of transport %q", imageRef.Transport().Name())
179
	} else if err != nil {
180
		if shortnames.IsShortName(imageName) {
181
			return fmt.Errorf("short name: auto updates require fully-qualified image reference: %q", imageName)
182
		}
183
	}
184
	return nil
185
}
186

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.