Skip to content

Commit 769a064

Browse files
committed
Merge branch 'v1.0.0.rc1' into master
* v1.0.0.rc1: Add Travis CI badge to README generate: fix capability.List() for cap_last_cap not exist generate: remove unnecessary spec initialization generate: fix tmpfs adding based on manpage Check CAP_LAST_CAP while setting privileged
2 parents 3598f61 + c186f4f commit 769a064

File tree

7 files changed

+91
-35
lines changed

7 files changed

+91
-35
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# ocitools
1+
# ocitools [![Build Status](https://travis-ci.org/opencontainers/ocitools.svg?branch=master)](https://travis-ci.org/opencontainers/ocitools)
22

33
ocitools is a collection of tools for working with the [OCI runtime specification][runtime-spec].
44

cmd/ocitools/generate.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ var generateCommand = cli.Command{
7878
}
7979
}
8080

81-
err := setupSpec(specgen, context)
81+
err := setupSpec(&specgen, context)
8282
if err != nil {
8383
return err
8484
}
@@ -96,8 +96,12 @@ var generateCommand = cli.Command{
9696
},
9797
}
9898

99-
func setupSpec(g generate.Generator, context *cli.Context) error {
100-
spec := g.GetSpec()
99+
func setupSpec(g *generate.Generator, context *cli.Context) error {
100+
if context.GlobalBool("host-specific") {
101+
g.HostSpecific = true
102+
}
103+
104+
spec := g.Spec()
101105

102106
if len(spec.Version) == 0 {
103107
g.SetVersion(rspec.Version)
@@ -369,7 +373,7 @@ func checkNs(nsMaps map[string]string, nsName string) bool {
369373
return true
370374
}
371375

372-
func setupLinuxNamespaces(g generate.Generator, needsNewUser bool, nsMaps map[string]string) {
376+
func setupLinuxNamespaces(g *generate.Generator, needsNewUser bool, nsMaps map[string]string) {
373377
for _, nsName := range generate.Namespaces {
374378
if !checkNs(nsMaps, nsName) && !(needsNewUser && nsName == "user") {
375379
continue

cmd/ocitools/main.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ func main() {
1818
Value: "error",
1919
Usage: "Log level (panic, fatal, error, warn, info, or debug)",
2020
},
21+
cli.BoolFlag{
22+
Name: "host-specific",
23+
Usage: "generate host-specific configs or do host-specific validations",
24+
},
2125
}
2226

2327
app.Commands = []cli.Command{

cmd/ocitools/validate.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ type configCheck func(rspec.Spec, string, bool) []string
2424

2525
var bundleValidateFlags = []cli.Flag{
2626
cli.StringFlag{Name: "path", Value: ".", Usage: "path to a bundle"},
27-
cli.BoolFlag{Name: "host-specific", Usage: "Check host specific configs."},
2827
}
2928

3029
var (
@@ -99,7 +98,7 @@ var bundleValidateCommand = cli.Command{
9998
return fmt.Errorf("The root path %q is not a directory.", rootfsPath)
10099
}
101100

102-
hostCheck := context.Bool("host-specific")
101+
hostCheck := context.GlobalBool("host-specific")
103102

104103
checks := []configCheck{
105104
checkMandatoryFields,

generate/generate.go

Lines changed: 61 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ var (
2121

2222
// Generator represents a generator for a container spec.
2323
type Generator struct {
24-
spec *rspec.Spec
24+
spec *rspec.Spec
25+
HostSpecific bool
2526
}
2627

2728
// New creates a spec Generator with the default spec.
@@ -139,12 +140,16 @@ func New() Generator {
139140
Devices: []rspec.Device{},
140141
},
141142
}
142-
return Generator{&spec}
143+
return Generator{
144+
spec: &spec,
145+
}
143146
}
144147

145148
// NewFromSpec creates a spec Generator from a given spec.
146149
func NewFromSpec(spec *rspec.Spec) Generator {
147-
return Generator{spec}
150+
return Generator{
151+
spec: spec,
152+
}
148153
}
149154

150155
// NewFromFile loads the template specifed in a file into a spec Generator.
@@ -166,16 +171,18 @@ func NewFromTemplate(r io.Reader) (Generator, error) {
166171
if err := json.NewDecoder(r).Decode(&spec); err != nil {
167172
return Generator{}, err
168173
}
169-
return Generator{&spec}, nil
174+
return Generator{
175+
spec: &spec,
176+
}, nil
170177
}
171178

172179
// SetSpec sets the spec in the Generator g.
173180
func (g *Generator) SetSpec(spec *rspec.Spec) {
174181
g.spec = spec
175182
}
176183

177-
// GetSpec gets the spec in the Generator g.
178-
func (g *Generator) GetSpec() *rspec.Spec {
184+
// Spec gets the spec in the Generator g.
185+
func (g *Generator) Spec() *rspec.Spec {
179186
return g.spec
180187
}
181188

@@ -230,7 +237,9 @@ func (g *Generator) SetHostname(s string) {
230237

231238
// ClearAnnotations clears g.spec.Annotations.
232239
func (g *Generator) ClearAnnotations() {
233-
g.initSpec()
240+
if g.spec == nil {
241+
return
242+
}
234243
g.spec.Annotations = make(map[string]string)
235244
}
236245

@@ -310,7 +319,9 @@ func (g *Generator) SetProcessArgs(args []string) {
310319

311320
// ClearProcessEnv clears g.spec.Process.Env.
312321
func (g *Generator) ClearProcessEnv() {
313-
g.initSpec()
322+
if g.spec == nil {
323+
return
324+
}
314325
g.spec.Process.Env = []string{}
315326
}
316327

@@ -322,7 +333,9 @@ func (g *Generator) AddProcessEnv(env string) {
322333

323334
// ClearProcessAdditionalGids clear g.spec.Process.AdditionalGids.
324335
func (g *Generator) ClearProcessAdditionalGids() {
325-
g.initSpec()
336+
if g.spec == nil {
337+
return
338+
}
326339
g.spec.Process.User.AdditionalGids = []uint32{}
327340
}
328341

@@ -886,11 +899,26 @@ func (g *Generator) AddPostStartHook(s string) error {
886899

887900
// AddTmpfsMount adds a tmpfs mount into g.spec.Mounts.
888901
func (g *Generator) AddTmpfsMount(dest string) error {
889-
mnt := rspec.Mount{
890-
Destination: dest,
891-
Type: "tmpfs",
892-
Source: "tmpfs",
893-
Options: []string{"nosuid", "nodev", "mode=755"},
902+
mnt := rspec.Mount{}
903+
904+
parts := strings.Split(dest, ":")
905+
if len(parts) == 2 {
906+
options := strings.Split(parts[1], ",")
907+
mnt = rspec.Mount{
908+
Destination: parts[0],
909+
Type: "tmpfs",
910+
Source: "tmpfs",
911+
Options: options,
912+
}
913+
} else if len(parts) == 1 {
914+
mnt = rspec.Mount{
915+
Destination: parts[0],
916+
Type: "tmpfs",
917+
Source: "tmpfs",
918+
Options: []string{"rw", "noexec", "nosuid", "nodev", "size=65536k"},
919+
}
920+
} else {
921+
return fmt.Errorf("invalid value for --tmpfs")
894922
}
895923

896924
g.initSpec()
@@ -953,6 +981,9 @@ func (g *Generator) SetupPrivileged(privileged bool) {
953981
// Add all capabilities in privileged mode.
954982
var finalCapList []string
955983
for _, cap := range capability.List() {
984+
if g.HostSpecific && cap > lastCap() {
985+
continue
986+
}
956987
finalCapList = append(finalCapList, fmt.Sprintf("CAP_%s", strings.ToUpper(cap.String())))
957988
}
958989
g.initSpecLinux()
@@ -963,12 +994,25 @@ func (g *Generator) SetupPrivileged(privileged bool) {
963994
}
964995
}
965996

966-
func checkCap(c string) error {
997+
func lastCap() capability.Cap {
998+
last := capability.CAP_LAST_CAP
999+
// hack for RHEL6 which has no /proc/sys/kernel/cap_last_cap
1000+
if last == capability.Cap(63) {
1001+
last = capability.CAP_BLOCK_SUSPEND
1002+
}
1003+
1004+
return last
1005+
}
1006+
1007+
func checkCap(c string, hostSpecific bool) error {
9671008
isValid := false
9681009
cp := strings.ToUpper(c)
9691010

9701011
for _, cap := range capability.List() {
9711012
if cp == strings.ToUpper(cap.String()) {
1013+
if hostSpecific && cap > lastCap() {
1014+
return fmt.Errorf("CAP_%s is not supported on the current host", cp)
1015+
}
9721016
isValid = true
9731017
break
9741018
}
@@ -990,7 +1034,7 @@ func (g *Generator) ClearProcessCapabilities() {
9901034

9911035
// AddProcessCapability adds a process capability into g.spec.Process.Capabilities.
9921036
func (g *Generator) AddProcessCapability(c string) error {
993-
if err := checkCap(c); err != nil {
1037+
if err := checkCap(c, g.HostSpecific); err != nil {
9941038
return err
9951039
}
9961040

@@ -1009,7 +1053,7 @@ func (g *Generator) AddProcessCapability(c string) error {
10091053

10101054
// DropProcessCapability drops a process capability from g.spec.Process.Capabilities.
10111055
func (g *Generator) DropProcessCapability(c string) error {
1012-
if err := checkCap(c); err != nil {
1056+
if err := checkCap(c, g.HostSpecific); err != nil {
10131057
return err
10141058
}
10151059

man/ocitools-validate.1.md

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,6 @@ Validate an OCI bundle
1818
**--path=PATH
1919
Path to bundle
2020

21-
**--host-specific**
22-
Check host specific configs.
23-
By default, validation only tests for compatibility with a hypothetical host.
24-
With this flag, validation will also run more specific tests to see whether
25-
the current host is capable of launching a container from the configuration.
26-
For example, validating a compliant Windows configuration on a Linux machine
27-
will pass without this flag ("there may be a Windows host capable of
28-
launching this container"), but will fail with it ("this host is not capable
29-
of launching this container").
30-
3121
# SEE ALSO
3222
**ocitools**(1)
3323

man/ocitools.1.md

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,26 @@ ocitools is a collection of tools for working with the [OCI runtime specificatio
1515

1616
# OPTIONS
1717
**--help**
18-
Print usage statement
18+
Print usage statement.
1919

2020
**-v**, **--version**
2121
Print version information.
2222

23+
**--log-level**
24+
Log level (panic, fatal, error, warn, info, or debug) (default: "error").
25+
26+
**--host-specific**
27+
Generate host-specific configs or do host-specific validations.
28+
29+
By default, generator generates configs without checking whether they are
30+
supported on the current host. With this flag, generator will first check
31+
whether each config is supported on the current host, and only add it into
32+
the config file if it passes the checking.
33+
34+
By default, validation only tests for compatibility with a hypothetical host.
35+
With this flag, validation will also run more specific tests to see whether
36+
the current host is capable of launching a container from the configuration.
37+
2338
# COMMANDS
2439
**validate**
2540
Validating OCI bundle

0 commit comments

Comments
 (0)