This repository has been archived by the owner on Feb 24, 2020. It is now read-only.
/
apps.go
198 lines (173 loc) · 6.59 KB
/
apps.go
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
// Copyright 2015 The rkt Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//+build linux
package apps
import (
"errors"
"fmt"
"strings"
"github.com/appc/spec/schema"
"github.com/appc/spec/schema/types"
)
var (
ErrInvalidSeccompMode = errors.New("invalid seccomp mode command-line override")
ErrInvalidSeccompOverride = errors.New("invalid seccomp command-line override")
)
// AppIO describes the type of an application stream at runtime (stdin/stdout/stderr).
type AppIO string
func (a AppIO) String() string {
return string(a)
}
const (
AppIOInteractive AppIO = "interactive" // interactive I/O (parent terminal)
AppIOLog AppIO = "log" // log-only I/O
AppIONull AppIO = "null" // null I/O
AppIOStream AppIO = "stream" // attachable I/O
AppIOTTY AppIO = "tty" // I/O over TTY
)
type App struct {
Name string // the name of the app. If not set, the image's name will be used.
Image string // the image reference as supplied by the user on the cli
Args []string // any arguments the user supplied for this app
Asc string // signature file override for image verification (if fetching occurs)
Exec string // exec override for image
WorkingDir string // working directory override for image
ReadOnlyRootFS bool // read-only rootfs override.
Mounts []schema.Mount // mounts for this app (superseding any mounts in rktApps.mounts of same MountPoint)
MemoryLimit *types.ResourceMemory // memory isolator override
CPULimit *types.ResourceCPU // cpu isolator override
CPUShares *types.LinuxCPUShares // cpu-shares isolator override
User, Group string // user, group overrides
SupplementaryGIDs []int // supplementary gids override
CapsRetain *types.LinuxCapabilitiesRetainSet // os/linux/capabilities-retain-set overrides
CapsRemove *types.LinuxCapabilitiesRevokeSet // os/linux/capabilities-remove-set overrides
SeccompFilter string // seccomp CLI overrides
OOMScoreAdj *types.LinuxOOMScoreAdj // oom-score-adj isolator override
Annotations map[string]string // the annotations of the app
UserAnnotations map[string]string // the user annotations of the app.
UserLabels map[string]string // the user labels of the app.
Environments map[string]string // the environments of the app.
Stdin AppIO // mode for stdin
Stdout AppIO // mode for stdout
Stderr AppIO // mode for stderr
// TODO(jonboulle): These images are partially-populated hashes, this should be clarified.
ImageID types.Hash // resolved image identifier
}
type Apps struct {
apps []App
Mounts []schema.Mount // global mounts applied to all apps
Volumes []types.Volume // volumes available to all apps
}
// SeccompFilter returns type, filter set and optional errno
// for a seccomp filter override specified via CLI
func (a *App) SeccompOverride() (mode string, errno string, set []string, e error) {
if a.SeccompFilter == "" {
return
}
for _, i := range strings.Split(a.SeccompFilter, ",") {
kv := strings.Split(i, "=")
if len(kv) == 2 {
switch kv[0] {
case "mode":
if kv[1] != "remove" && kv[1] != "retain" {
e = ErrInvalidSeccompMode
}
mode = kv[1]
case "errno":
errno = kv[1]
default:
e = ErrInvalidSeccompOverride
}
} else {
set = append(set, i)
}
}
return
}
// Reset creates a new slice for al.apps, needed by tests
func (al *Apps) Reset() {
al.apps = make([]App, 0)
}
// Count returns the number of apps in al
func (al *Apps) Count() int {
return len(al.apps)
}
// Create creates a new app in al and returns a pointer to it
func (al *Apps) Create(img string) {
al.apps = append(al.apps, App{Image: img})
}
// Last returns a pointer to the top app in al
func (al *Apps) Last() *App {
if len(al.apps) == 0 {
return nil
}
return &al.apps[len(al.apps)-1]
}
// Validate validates al for things like referential integrity of mounts<->volumes.
func (al *Apps) Validate() error {
vs := map[types.ACName]struct{}{}
for _, v := range al.Volumes {
vs[v.Name] = struct{}{}
}
f := func(mnts []schema.Mount) error {
for _, m := range mnts {
if m.AppVolume != nil { // allow app-specific volumes
continue
}
if _, ok := vs[m.Volume]; !ok {
return fmt.Errorf("dangling mount point %q: volume %q not found", m.Path, m.Volume)
}
}
return nil
}
if err := f(al.Mounts); err != nil {
return err
}
err := al.Walk(func(app *App) error {
return f(app.Mounts)
})
/* TODO(vc): in debug/verbose mode say something about unused volumes? */
return err
}
// Walk iterates on al.apps calling f for each app
// walking stops if f returns an error, the error is simply returned
func (al *Apps) Walk(f func(*App) error) error {
for i := range al.apps {
// XXX(vc): note we supply f() with a pointer to the app instance in al.apps to enable modification by f()
if err := f(&al.apps[i]); err != nil {
return err
}
}
return nil
}
// these convenience functions just return typed lists containing just the named member
// TODO(vc): these probably go away when we just pass Apps to stage0
// GetImages returns a list of the images in al, one per app.
// The order reflects the app order in al.
func (al *Apps) GetImages() []string {
var il []string
for _, a := range al.apps {
il = append(il, a.Image)
}
return il
}
// GetArgs returns a list of lists of arguments in al, one list of args per app.
// The order reflects the app order in al.
func (al *Apps) GetArgs() [][]string {
var aal [][]string
for _, a := range al.apps {
aal = append(aal, a.Args)
}
return aal
}