cmd/containerd: split package for cli.App
Signed-off-by: Akihiro Suda <suda.akihiro@lab.ntt.co.jp>
This commit is contained in:
parent
af593cf5ab
commit
d7280ce2fb
@ -1,4 +1,4 @@
|
||||
package main
|
||||
package command
|
||||
|
||||
import (
|
||||
"io"
|
@ -1,4 +1,4 @@
|
||||
package main
|
||||
package command
|
||||
|
||||
import (
|
||||
"github.com/containerd/containerd/defaults"
|
@ -1,6 +1,6 @@
|
||||
// +build !linux,!windows,!solaris
|
||||
|
||||
package main
|
||||
package command
|
||||
|
||||
import (
|
||||
"github.com/containerd/containerd/defaults"
|
@ -1,4 +1,4 @@
|
||||
package main
|
||||
package command
|
||||
|
||||
import (
|
||||
"github.com/containerd/containerd/defaults"
|
200
cmd/containerd/command/main.go
Normal file
200
cmd/containerd/command/main.go
Normal file
@ -0,0 +1,200 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
golog "log"
|
||||
"net"
|
||||
"os"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/containerd/containerd/log"
|
||||
"github.com/containerd/containerd/server"
|
||||
"github.com/containerd/containerd/sys"
|
||||
"github.com/containerd/containerd/version"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli"
|
||||
gocontext "golang.org/x/net/context"
|
||||
"google.golang.org/grpc/grpclog"
|
||||
)
|
||||
|
||||
const usage = `
|
||||
__ _ __
|
||||
_________ ____ / /_____ _(_)___ ___ _________/ /
|
||||
/ ___/ __ \/ __ \/ __/ __ ` + "`" + `/ / __ \/ _ \/ ___/ __ /
|
||||
/ /__/ /_/ / / / / /_/ /_/ / / / / / __/ / / /_/ /
|
||||
\___/\____/_/ /_/\__/\__,_/_/_/ /_/\___/_/ \__,_/
|
||||
|
||||
high performance container runtime
|
||||
`
|
||||
|
||||
func init() {
|
||||
// Discard grpc logs so that they don't mess with our stdio
|
||||
grpclog.SetLogger(golog.New(ioutil.Discard, "", golog.LstdFlags))
|
||||
|
||||
cli.VersionPrinter = func(c *cli.Context) {
|
||||
fmt.Println(c.App.Name, version.Package, c.App.Version, version.Revision)
|
||||
}
|
||||
}
|
||||
|
||||
// App returns a *cli.App instance.
|
||||
func App() *cli.App {
|
||||
app := cli.NewApp()
|
||||
app.Name = "containerd"
|
||||
app.Version = version.Version
|
||||
app.Usage = usage
|
||||
app.Flags = []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "config,c",
|
||||
Usage: "path to the configuration file",
|
||||
Value: defaultConfigPath,
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "log-level,l",
|
||||
Usage: "set the logging level [trace, debug, info, warn, error, fatal, panic]",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "address,a",
|
||||
Usage: "address for containerd's GRPC server",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "root",
|
||||
Usage: "containerd root directory",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "state",
|
||||
Usage: "containerd state directory",
|
||||
},
|
||||
}
|
||||
app.Commands = []cli.Command{
|
||||
configCommand,
|
||||
publishCommand,
|
||||
}
|
||||
app.Action = func(context *cli.Context) error {
|
||||
var (
|
||||
start = time.Now()
|
||||
signals = make(chan os.Signal, 2048)
|
||||
serverC = make(chan *server.Server, 1)
|
||||
ctx = gocontext.Background()
|
||||
config = defaultConfig()
|
||||
)
|
||||
|
||||
done := handleSignals(ctx, signals, serverC)
|
||||
// start the signal handler as soon as we can to make sure that
|
||||
// we don't miss any signals during boot
|
||||
signal.Notify(signals, handledSignals...)
|
||||
|
||||
if err := server.LoadConfig(context.GlobalString("config"), config); err != nil && !os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
// apply flags to the config
|
||||
if err := applyFlags(context, config); err != nil {
|
||||
return err
|
||||
}
|
||||
address := config.GRPC.Address
|
||||
if address == "" {
|
||||
return errors.New("grpc address cannot be empty")
|
||||
}
|
||||
log.G(ctx).WithFields(logrus.Fields{
|
||||
"version": version.Version,
|
||||
"revision": version.Revision,
|
||||
}).Info("starting containerd")
|
||||
|
||||
server, err := server.New(ctx, config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
serverC <- server
|
||||
if config.Debug.Address != "" {
|
||||
var l net.Listener
|
||||
if filepath.IsAbs(config.Debug.Address) {
|
||||
if l, err = sys.GetLocalListener(config.Debug.Address, config.Debug.UID, config.Debug.GID); err != nil {
|
||||
return errors.Wrapf(err, "failed to get listener for debug endpoint")
|
||||
}
|
||||
} else {
|
||||
if l, err = net.Listen("tcp", config.Debug.Address); err != nil {
|
||||
return errors.Wrapf(err, "failed to get listener for debug endpoint")
|
||||
}
|
||||
}
|
||||
serve(ctx, l, server.ServeDebug)
|
||||
}
|
||||
if config.Metrics.Address != "" {
|
||||
l, err := net.Listen("tcp", config.Metrics.Address)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to get listener for metrics endpoint")
|
||||
}
|
||||
serve(ctx, l, server.ServeMetrics)
|
||||
}
|
||||
|
||||
l, err := sys.GetLocalListener(address, config.GRPC.UID, config.GRPC.GID)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to get listener for main endpoint")
|
||||
}
|
||||
serve(ctx, l, server.ServeGRPC)
|
||||
|
||||
log.G(ctx).Infof("containerd successfully booted in %fs", time.Since(start).Seconds())
|
||||
<-done
|
||||
return nil
|
||||
}
|
||||
return app
|
||||
}
|
||||
|
||||
func serve(ctx context.Context, l net.Listener, serveFunc func(net.Listener) error) {
|
||||
path := l.Addr().String()
|
||||
log.G(ctx).WithField("address", path).Info("serving...")
|
||||
go func() {
|
||||
defer l.Close()
|
||||
if err := serveFunc(l); err != nil {
|
||||
log.G(ctx).WithError(err).WithField("address", path).Fatal("serve failure")
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func applyFlags(context *cli.Context, config *server.Config) error {
|
||||
// the order for config vs flag values is that flags will always override
|
||||
// the config values if they are set
|
||||
if err := setLevel(context, config); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, v := range []struct {
|
||||
name string
|
||||
d *string
|
||||
}{
|
||||
{
|
||||
name: "root",
|
||||
d: &config.Root,
|
||||
},
|
||||
{
|
||||
name: "state",
|
||||
d: &config.State,
|
||||
},
|
||||
{
|
||||
name: "address",
|
||||
d: &config.GRPC.Address,
|
||||
},
|
||||
} {
|
||||
if s := context.GlobalString(v.name); s != "" {
|
||||
*v.d = s
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func setLevel(context *cli.Context, config *server.Config) error {
|
||||
l := context.GlobalString("log-level")
|
||||
if l == "" {
|
||||
l = config.Debug.Level
|
||||
}
|
||||
if l != "" {
|
||||
lvl, err := log.ParseLevel(l)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
logrus.SetLevel(lvl)
|
||||
}
|
||||
return nil
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
// +build linux darwin freebsd solaris
|
||||
|
||||
package main
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
@ -1,4 +1,4 @@
|
||||
package main
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
@ -1,4 +1,4 @@
|
||||
package main
|
||||
package command
|
||||
|
||||
import (
|
||||
gocontext "context"
|
@ -1,202 +1,16 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
golog "log"
|
||||
"net"
|
||||
"os"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/containerd/containerd/log"
|
||||
"github.com/containerd/containerd/server"
|
||||
"github.com/containerd/containerd/sys"
|
||||
"github.com/containerd/containerd/version"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli"
|
||||
gocontext "golang.org/x/net/context"
|
||||
"google.golang.org/grpc/grpclog"
|
||||
"github.com/containerd/containerd/cmd/containerd/command"
|
||||
)
|
||||
|
||||
const usage = `
|
||||
__ _ __
|
||||
_________ ____ / /_____ _(_)___ ___ _________/ /
|
||||
/ ___/ __ \/ __ \/ __/ __ ` + "`" + `/ / __ \/ _ \/ ___/ __ /
|
||||
/ /__/ /_/ / / / / /_/ /_/ / / / / / __/ / / /_/ /
|
||||
\___/\____/_/ /_/\__/\__,_/_/_/ /_/\___/_/ \__,_/
|
||||
|
||||
high performance container runtime
|
||||
`
|
||||
|
||||
func init() {
|
||||
// Discard grpc logs so that they don't mess with our stdio
|
||||
grpclog.SetLogger(golog.New(ioutil.Discard, "", golog.LstdFlags))
|
||||
|
||||
cli.VersionPrinter = func(c *cli.Context) {
|
||||
fmt.Println(c.App.Name, version.Package, c.App.Version, version.Revision)
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
app := cli.NewApp()
|
||||
app.Name = "containerd"
|
||||
app.Version = version.Version
|
||||
app.Usage = usage
|
||||
app.Flags = []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "config,c",
|
||||
Usage: "path to the configuration file",
|
||||
Value: defaultConfigPath,
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "log-level,l",
|
||||
Usage: "set the logging level [trace, debug, info, warn, error, fatal, panic]",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "address,a",
|
||||
Usage: "address for containerd's GRPC server",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "root",
|
||||
Usage: "containerd root directory",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "state",
|
||||
Usage: "containerd state directory",
|
||||
},
|
||||
}
|
||||
app.Commands = []cli.Command{
|
||||
configCommand,
|
||||
publishCommand,
|
||||
}
|
||||
app.Action = func(context *cli.Context) error {
|
||||
var (
|
||||
start = time.Now()
|
||||
signals = make(chan os.Signal, 2048)
|
||||
serverC = make(chan *server.Server, 1)
|
||||
ctx = gocontext.Background()
|
||||
config = defaultConfig()
|
||||
)
|
||||
|
||||
done := handleSignals(ctx, signals, serverC)
|
||||
// start the signal handler as soon as we can to make sure that
|
||||
// we don't miss any signals during boot
|
||||
signal.Notify(signals, handledSignals...)
|
||||
|
||||
if err := server.LoadConfig(context.GlobalString("config"), config); err != nil && !os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
// apply flags to the config
|
||||
if err := applyFlags(context, config); err != nil {
|
||||
return err
|
||||
}
|
||||
address := config.GRPC.Address
|
||||
if address == "" {
|
||||
return errors.New("grpc address cannot be empty")
|
||||
}
|
||||
log.G(ctx).WithFields(logrus.Fields{
|
||||
"version": version.Version,
|
||||
"revision": version.Revision,
|
||||
}).Info("starting containerd")
|
||||
|
||||
server, err := server.New(ctx, config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
serverC <- server
|
||||
if config.Debug.Address != "" {
|
||||
var l net.Listener
|
||||
if filepath.IsAbs(config.Debug.Address) {
|
||||
if l, err = sys.GetLocalListener(config.Debug.Address, config.Debug.UID, config.Debug.GID); err != nil {
|
||||
return errors.Wrapf(err, "failed to get listener for debug endpoint")
|
||||
}
|
||||
} else {
|
||||
if l, err = net.Listen("tcp", config.Debug.Address); err != nil {
|
||||
return errors.Wrapf(err, "failed to get listener for debug endpoint")
|
||||
}
|
||||
}
|
||||
serve(ctx, l, server.ServeDebug)
|
||||
}
|
||||
if config.Metrics.Address != "" {
|
||||
l, err := net.Listen("tcp", config.Metrics.Address)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to get listener for metrics endpoint")
|
||||
}
|
||||
serve(ctx, l, server.ServeMetrics)
|
||||
}
|
||||
|
||||
l, err := sys.GetLocalListener(address, config.GRPC.UID, config.GRPC.GID)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to get listener for main endpoint")
|
||||
}
|
||||
serve(ctx, l, server.ServeGRPC)
|
||||
|
||||
log.G(ctx).Infof("containerd successfully booted in %fs", time.Since(start).Seconds())
|
||||
<-done
|
||||
return nil
|
||||
}
|
||||
app := command.App()
|
||||
if err := app.Run(os.Args); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "containerd: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func serve(ctx context.Context, l net.Listener, serveFunc func(net.Listener) error) {
|
||||
path := l.Addr().String()
|
||||
log.G(ctx).WithField("address", path).Info("serving...")
|
||||
go func() {
|
||||
defer l.Close()
|
||||
if err := serveFunc(l); err != nil {
|
||||
log.G(ctx).WithError(err).WithField("address", path).Fatal("serve failure")
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func applyFlags(context *cli.Context, config *server.Config) error {
|
||||
// the order for config vs flag values is that flags will always override
|
||||
// the config values if they are set
|
||||
if err := setLevel(context, config); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, v := range []struct {
|
||||
name string
|
||||
d *string
|
||||
}{
|
||||
{
|
||||
name: "root",
|
||||
d: &config.Root,
|
||||
},
|
||||
{
|
||||
name: "state",
|
||||
d: &config.State,
|
||||
},
|
||||
{
|
||||
name: "address",
|
||||
d: &config.GRPC.Address,
|
||||
},
|
||||
} {
|
||||
if s := context.GlobalString(v.name); s != "" {
|
||||
*v.d = s
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func setLevel(context *cli.Context, config *server.Config) error {
|
||||
l := context.GlobalString("log-level")
|
||||
if l == "" {
|
||||
l = config.Debug.Level
|
||||
}
|
||||
if l != "" {
|
||||
lvl, err := log.ParseLevel(l)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
logrus.SetLevel(lvl)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user