talos

Форк
0
165 строк · 4.6 Кб
1
// This Source Code Form is subject to the terms of the Mozilla Public
2
// License, v. 2.0. If a copy of the MPL was not distributed with this
3
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
4

5
// Package services contains definitions for non-system services.
6
package services
7

8
import (
9
	"errors"
10
	"fmt"
11
	"path/filepath"
12
	"regexp"
13

14
	"github.com/hashicorp/go-multierror"
15
	"github.com/opencontainers/runtime-spec/specs-go"
16

17
	"github.com/siderolabs/talos/pkg/machinery/nethelpers"
18
)
19

20
// Spec is represents non-system service definition.
21
type Spec struct {
22
	// Name of the service to run, will be prefixed with `ext-` when registered as Talos service.
23
	//
24
	// Valid: [-_a-z0-9]+
25
	Name string `yaml:"name"`
26
	// Container to run.
27
	//
28
	// Container rootfs should be extracted to the /usr/local/lib/containers/<name>.
29
	Container Container `yaml:"container"`
30
	// Service dependencies.
31
	Depends []Dependency `yaml:"depends"`
32
	// Restart configuration.
33
	Restart RestartKind `yaml:"restart"`
34
}
35

36
// Container specifies service container to run.
37
type Container struct {
38
	// Entrypoint for the service, relative to the container rootfs.
39
	Entrypoint string `yaml:"entrypoint"`
40
	// Environment variables for the service.
41
	Environment []string `yaml:"environment"`
42
	// EnvironmentFile to load environment vars before running the service.
43
	EnvironmentFile string `yaml:"environmentFile"`
44
	// Args to pass to the entrypoint.
45
	Args []string `yaml:"args"`
46
	// Volume mounts.
47
	Mounts []specs.Mount `yaml:"mounts"`
48
	// Security options.
49
	Security Security `yaml:"security"`
50
}
51

52
// Security options for containers.
53
type Security struct {
54
	// WriteableSysfs makes the '/sys' path writeable in the container namespace if set to true.
55
	WriteableSysfs bool `yaml:"writeableSysfs"`
56
	// MaskedPaths is a list of paths in the container namespace that should not be readable.
57
	MaskedPaths []string `yaml:"maskedPaths"`
58
	// ReadonlyPaths is a list of paths in the container namespace that should be read-only.
59
	ReadonlyPaths []string `yaml:"readonlyPaths"`
60
	// WriteableRootfs
61
	WriteableRootfs bool `yaml:"writeableRootfs"`
62
	// RootfsPropagation is the propagation mode for the rootfs mount.
63
	RootfsPropagation string `yaml:"rootfsPropagation,omitempty"`
64
}
65

66
// Dependency describes a service Dependency.
67
//
68
// Only a single dependency out of the list might be specified.
69
type Dependency struct {
70
	// Depends on a service being running and healthy (if health checks are available).
71
	Service string `yaml:"service,omitempty"`
72
	// Depends on file/directory existence.
73
	Path string `yaml:"path,omitempty"`
74
	// Network readiness checks.
75
	//
76
	// Valid options are nethelpers.Status string values.
77
	Network []nethelpers.Status `yaml:"network,omitempty"`
78
	// Time sync check.
79
	Time bool `yaml:"time,omitempty"`
80
	// Depends on configuration files to be present.
81
	Configuration bool `yaml:"configuration,omitempty"`
82
}
83

84
var nameRe = regexp.MustCompile(`^[-_a-z0-9]{1,}$`)
85

86
// Validate the service spec.
87
func (spec *Spec) Validate() error {
88
	var multiErr *multierror.Error
89

90
	if !nameRe.MatchString(spec.Name) {
91
		multiErr = multierror.Append(multiErr, fmt.Errorf("name %q is invalid", spec.Name))
92
	}
93

94
	if !spec.Restart.IsARestartKind() {
95
		multiErr = multierror.Append(multiErr, fmt.Errorf("restart kind is invalid: %s", spec.Restart))
96
	}
97

98
	multiErr = multierror.Append(multiErr, spec.Container.Validate())
99

100
	for _, dep := range spec.Depends {
101
		multiErr = multierror.Append(multiErr, dep.Validate())
102
	}
103

104
	return multiErr.ErrorOrNil()
105
}
106

107
// Validate the container spec.
108
func (ctr *Container) Validate() error {
109
	var multiErr *multierror.Error
110

111
	if ctr.Entrypoint == "" {
112
		multiErr = multierror.Append(multiErr, errors.New("container endpoint can't be empty"))
113
	}
114

115
	return multiErr.ErrorOrNil()
116
}
117

118
// Validate the dependency spec.
119
//
120
//nolint:gocyclo
121
func (dep *Dependency) Validate() error {
122
	var multiErr *multierror.Error
123

124
	nonZeroDeps := 0
125

126
	if dep.Service != "" {
127
		nonZeroDeps++
128
	}
129

130
	if dep.Path != "" {
131
		nonZeroDeps++
132

133
		if !filepath.IsAbs(dep.Path) {
134
			multiErr = multierror.Append(multiErr, fmt.Errorf("path is not absolute: %q", dep.Path))
135
		}
136
	}
137

138
	if len(dep.Network) > 0 {
139
		nonZeroDeps++
140

141
		for _, st := range dep.Network {
142
			if !st.IsAStatus() {
143
				multiErr = multierror.Append(multiErr, fmt.Errorf("invalid network dependency: %s", st))
144
			}
145
		}
146
	}
147

148
	if dep.Time {
149
		nonZeroDeps++
150
	}
151

152
	if dep.Configuration {
153
		nonZeroDeps++
154
	}
155

156
	if nonZeroDeps == 0 {
157
		multiErr = multierror.Append(multiErr, errors.New("no dependency specified"))
158
	}
159

160
	if nonZeroDeps > 1 {
161
		multiErr = multierror.Append(multiErr, errors.New("more than a single dependency is set"))
162
	}
163

164
	return multiErr.ErrorOrNil()
165
}
166

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

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

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

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