-
Notifications
You must be signed in to change notification settings - Fork 2.1k
/
utils.go
130 lines (114 loc) · 2.94 KB
/
utils.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
package main
import (
"errors"
"fmt"
"os"
"path/filepath"
"strconv"
"strings"
"github.com/opencontainers/runtime-spec/specs-go"
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
)
const (
exactArgs = iota
minArgs
maxArgs
)
func checkArgs(context *cli.Context, expected, checkType int) error {
var err error
cmdName := context.Command.Name
switch checkType {
case exactArgs:
if context.NArg() != expected {
err = fmt.Errorf("%s: %q requires exactly %d argument(s)", os.Args[0], cmdName, expected)
}
case minArgs:
if context.NArg() < expected {
err = fmt.Errorf("%s: %q requires a minimum of %d argument(s)", os.Args[0], cmdName, expected)
}
case maxArgs:
if context.NArg() > expected {
err = fmt.Errorf("%s: %q requires a maximum of %d argument(s)", os.Args[0], cmdName, expected)
}
}
if err != nil {
fmt.Printf("Incorrect Usage.\n\n")
_ = cli.ShowCommandHelp(context, cmdName)
return err
}
return nil
}
func logrusToStderr() bool {
l, ok := logrus.StandardLogger().Out.(*os.File)
return ok && l.Fd() == os.Stderr.Fd()
}
// fatal prints the error's details if it is a libcontainer specific error type
// then exits the program with an exit status of 1.
func fatal(err error) {
fatalWithCode(err, 1)
}
func fatalWithCode(err error, ret int) {
// Make sure the error is written to the logger.
logrus.Error(err)
if !logrusToStderr() {
fmt.Fprintln(os.Stderr, err)
}
os.Exit(ret)
}
// setupSpec performs initial setup based on the cli.Context for the container
func setupSpec(context *cli.Context) (*specs.Spec, error) {
bundle := context.String("bundle")
if bundle != "" {
if err := os.Chdir(bundle); err != nil {
return nil, err
}
}
spec, err := loadSpec(specConfig)
if err != nil {
return nil, err
}
return spec, nil
}
func revisePidFile(context *cli.Context) error {
pidFile := context.String("pid-file")
if pidFile == "" {
return nil
}
// convert pid-file to an absolute path so we can write to the right
// file after chdir to bundle
pidFile, err := filepath.Abs(pidFile)
if err != nil {
return err
}
return context.Set("pid-file", pidFile)
}
// reviseRootDir ensures that the --root option argument,
// if specified, is converted to an absolute and cleaned path,
// and that this path is sane.
func reviseRootDir(context *cli.Context) error {
if !context.IsSet("root") {
return nil
}
root, err := filepath.Abs(context.GlobalString("root"))
if err != nil {
return err
}
if root == "/" {
// This can happen if --root argument is
// - "" (i.e. empty);
// - "." (and the CWD is /);
// - "../../.." (enough to get to /);
// - "/" (the actual /).
return errors.New("Option --root argument should not be set to /")
}
return context.GlobalSet("root", root)
}
// parseBoolOrAuto returns (nil, nil) if s is empty or "auto"
func parseBoolOrAuto(s string) (*bool, error) {
if s == "" || strings.ToLower(s) == "auto" {
return nil, nil
}
b, err := strconv.ParseBool(s)
return &b, err
}