Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions cli/info.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,13 @@ func prettyPrintInfo(cli *Cli, info *types.SystemInfo) error {
fmt.Fprintln(os.Stdout, "Logging Driver:", info.LoggingDriver)
fmt.Fprintln(os.Stdout, "Volume Drivers:", info.VolumeDrivers)
fmt.Fprintln(os.Stdout, "Cgroup Driver:", info.CgroupDriver)
fmt.Fprintln(os.Stdout, "Default Runtime:", info.DefaultRuntime)
if len(info.Runtimes) > 0 {
fmt.Fprintln(os.Stdout, "Runtimes:")
fmt.Fprintf(os.Stdout, "Runtimes:")
for name := range info.Runtimes {
fmt.Fprintf(os.Stdout, "%s", name)
fmt.Fprintf(os.Stdout, " %s", name)
}
fmt.Fprint(os.Stdout, "\n")
fmt.Fprintln(os.Stdout, "Default Runtime:", info.DefaultRuntime)
}
fmt.Fprintln(os.Stdout, "runc:", info.RuncCommit)
fmt.Fprintln(os.Stdout, "containerd:", info.ContainerdCommit)
Expand Down
59 changes: 59 additions & 0 deletions config/opt/runtime.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package opt

import (
"fmt"
"strings"

"github.com/alibaba/pouch/apis/types"
)

// Runtime defines runtimes information
type Runtime struct {
values *map[string]types.Runtime
}

// NewRuntime initials a Runtime struct
func NewRuntime(rts *map[string]types.Runtime) *Runtime {
if rts == nil {
rts = &map[string]types.Runtime{}
}

if *rts == nil {
*rts = map[string]types.Runtime{}
}

rt := &Runtime{values: rts}
return rt
}

// Set implement Runtime as pflag.Value interface
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should add unit test for this function.

func (r *Runtime) Set(val string) error {
splits := strings.Split(val, "=")
if len(splits) != 2 || splits[0] == "" || splits[1] == "" {
return fmt.Errorf("invalid runtime %s, correct format must be runtime=path", val)
}

name := splits[0]
path := splits[1]
if _, exist := (*r.values)[name]; exist {
return fmt.Errorf("runtime %s already registers to daemon", name)
}

(*r.values)[name] = types.Runtime{Path: path}
return nil
}

// String implement Runtime as pflag.Value interface
func (r *Runtime) String() string {
var str []string
for k := range *r.values {
str = append(str, fmt.Sprintf("%s", k))
}

return fmt.Sprintf("%v", str)
}

// Type implement Runtime as pflag.Value interface
func (r *Runtime) Type() string {
return "value"
}
25 changes: 25 additions & 0 deletions config/opt/runtime_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package opt

import (
"testing"

"github.com/alibaba/pouch/apis/types"
"github.com/stretchr/testify/assert"
)

func TestNewRuntime(t *testing.T) {
assert := assert.New(t)

for _, r := range []*map[string]types.Runtime{
nil,
{},
{
"a": {},
"b": {Path: "foo"},
},
} {
runtime := NewRuntime(r)
// just test no panic here
assert.NoError(runtime.Set("foo=bar"))
}
}
47 changes: 42 additions & 5 deletions daemon/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,11 @@ type Config struct {

// oom_score_adj for the daemon
OOMScoreAdjust int `json:"oom-score-adjust,omitempty"`

// runtimes config
// TODO(Ace-Tang): runtime args is not support, since containerd is not support,
// add a resolution later if it needed.
Runtimes map[string]types.Runtime `json:"add-runtime,omitempty"`
}

// Validate validates the user input config.
Expand All @@ -128,6 +133,16 @@ func (cfg *Config) Validate() error {

// TODO: add config validation

// validates runtimes config
if len(cfg.Runtimes) == 0 {
cfg.Runtimes = make(map[string]types.Runtime)
}
if _, exist := cfg.Runtimes[cfg.DefaultRuntime]; exist {
return fmt.Errorf("default runtime %s cannot be re-register", cfg.DefaultRuntime)
}
// add default runtime
cfg.Runtimes[cfg.DefaultRuntime] = types.Runtime{Path: cfg.DefaultRuntime}

return nil
}

Expand All @@ -141,17 +156,16 @@ func (cfg *Config) MergeConfigurations(flagSet *pflag.FlagSet) error {
return fmt.Errorf("failed to read contents from config file %s: %s", cfg.ConfigFile, err)
}

var origin map[string]interface{}
if err = json.NewDecoder(bytes.NewReader(contents)).Decode(&origin); err != nil {
var fileFlags map[string]interface{}
if err = json.NewDecoder(bytes.NewReader(contents)).Decode(&fileFlags); err != nil {
return fmt.Errorf("failed to decode json: %s", err)
}

if len(origin) == 0 {
if len(fileFlags) == 0 {
return nil
}

fileFlags := make(map[string]interface{}, 0)
iterateConfig(origin, fileFlags)
transferTLSConfig(fileFlags)

// check if invalid or unknown flag exist in config file
if err = getUnknownFlags(flagSet, fileFlags); err != nil {
Expand Down Expand Up @@ -211,6 +225,29 @@ func (cfg *Config) delValue(flagSet *pflag.FlagSet, fileFlags map[string]interfa
return cfg
}

// transferTLSConfig fetch key value from tls config
// {
// "tlscert": "...",
// "tlscacert": "..."
// }
// add this transfer logic since no flag named TLS, but tlscert, tlscert...
// we should fetch them to do unknown flags and conflict flags check
func transferTLSConfig(config map[string]interface{}) {
v, exist := config["TLS"]
if !exist {
return
}

var tlscofig map[string]interface{}
iterateConfig(map[string]interface{}{
"TLS": v,
}, tlscofig)

for k, v := range tlscofig {
config[k] = v
}
}

// iterateConfig resolves key-value from config file iteratly.
func iterateConfig(origin map[string]interface{}, config map[string]interface{}) {
for k, v := range origin {
Expand Down
4 changes: 4 additions & 0 deletions daemon/mgr/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,10 @@ func (mgr *ContainerManager) Create(ctx context.Context, name string, config *ty
config.HostConfig.Runtime = mgr.Config.DefaultRuntime
}

if _, exist := mgr.Config.Runtimes[config.HostConfig.Runtime]; !exist {
return nil, fmt.Errorf("unknown runtime %s", config.HostConfig.Runtime)
}

config.Image = primaryRef.String()
// create a snapshot with image.
if err := mgr.Client.CreateSnapshot(ctx, id, config.Image); err != nil {
Expand Down
2 changes: 1 addition & 1 deletion daemon/mgr/system.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ func (mgr *SystemManager) Info() (types.SystemInfo, error) {
PouchRootDir: mgr.config.HomeDir,
RegistryConfig: &mgr.config.RegistryService,
// RuncCommit: ,
// Runtimes: ,
Runtimes: mgr.config.Runtimes,
// SecurityOptions: ,
ServerVersion: version.Version,
ListenAddresses: mgr.config.Listen,
Expand Down
4 changes: 2 additions & 2 deletions hack/make.sh
Original file line number Diff line number Diff line change
Expand Up @@ -260,10 +260,10 @@ function target
# start pouch daemon
echo "start pouch daemon"
if stat /usr/bin/lxcfs ; then
$POUCHD --debug --enable-lxcfs=true \
$POUCHD --debug --enable-lxcfs=true --add-runtime runv=runv \
--lxcfs=/usr/bin/lxcfs > "$TMP/log" 2>&1 &
else
$POUCHD --debug > "$TMP/log" 2>&1 &
$POUCHD --debug --add-runtime runv=runv > "$TMP/log" 2>&1 &
fi

# wait until pouch daemon is ready
Expand Down
26 changes: 8 additions & 18 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"syscall"
"time"

"github.com/alibaba/pouch/config/opt"
"github.com/alibaba/pouch/daemon"
"github.com/alibaba/pouch/daemon/config"
"github.com/alibaba/pouch/lxcfs"
Expand Down Expand Up @@ -42,17 +43,11 @@ func main() {
Args: cobra.NoArgs,
SilenceUsage: true,
RunE: func(cmd *cobra.Command, args []string) error {
return runDaemon()
return runDaemon(cmd)
},
}

setupFlags(cmdServe)
parseFlags(cmdServe, os.Args[1:])
if err := loadDaemonFile(cfg, cmdServe.Flags()); err != nil {
logrus.Errorf("failed to load daemon file: %s", err)
os.Exit(1)
}

if err := cmdServe.Execute(); err != nil {
logrus.Error(err)
os.Exit(1)
Expand Down Expand Up @@ -116,21 +111,16 @@ func setupFlags(cmd *cobra.Command) {
flagSet.BoolVar(&cfg.EnableProfiler, "enable-profiler", false, "Set if pouchd setup profiler")
flagSet.StringVar(&cfg.Pidfile, "pidfile", "/var/run/pouch.pid", "Save daemon pid")
flagSet.IntVar(&cfg.OOMScoreAdjust, "oom-score-adj", -500, "Set the oom_score_adj for the daemon")
}
flagSet.Var(opt.NewRuntime(&cfg.Runtimes), "add-runtime", "register a OCI runtime to daemon")

// parse flags
func parseFlags(cmd *cobra.Command, flags []string) {
err := cmd.Flags().Parse(flags)
if err == nil || err == pflag.ErrHelp {
return
}

cmd.SetOutput(os.Stderr)
cmd.Usage()
}

// runDaemon prepares configs, setups essential details and runs pouchd daemon.
func runDaemon() error {
func runDaemon(cmd *cobra.Command) error {
if err := loadDaemonFile(cfg, cmd.Flags()); err != nil {
return fmt.Errorf("failed to load daemon file: %s", err)
}

//user specifies --version or -v, print version and return.
if printVersion {
fmt.Printf("pouchd version: %s, build: %s, build at: %s\n", version.Version, version.GitCommit, version.BuildTime)
Expand Down
15 changes: 15 additions & 0 deletions test/z_cli_daemon_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -451,3 +451,18 @@ func (suite *PouchDaemonSuite) TestDaemonStartOverOneTimes(c *check.C) {
c.Assert(err, check.NotNil)

}

// TestDaemonWithMultiRuntimes tests start daemon with multiple runtimes
func (suite *PouchDaemonSuite) TestDaemonWithMultiRuntimes(c *check.C) {
dcfg1, err := StartDefaultDaemonDebug(
"--add-runtime", "foo=bar")
c.Assert(err, check.IsNil)
dcfg1.KillDaemon()

// should fail if runtime name equal
dcfg2, err := StartDefaultDaemonDebug(
"--add-runtime", "runa=runa",
"--add-runtime", "runa=runa")
c.Assert(err, check.NotNil)
dcfg2.KillDaemon()
}