buildkitd: add config file support
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>docker-18.09
parent
9d1b0e6b31
commit
c524709f4a
|
@ -0,0 +1,78 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/BurntSushi/toml"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// Config provides containerd configuration data for the server
|
||||
type Config struct {
|
||||
Debug bool `toml:"debug"`
|
||||
|
||||
// Root is the path to a directory where buildkit will store persistent data
|
||||
Root string `toml:"root"`
|
||||
|
||||
// GRPC configuration settings
|
||||
GRPC GRPCConfig `toml:"grpc"`
|
||||
|
||||
Workers struct {
|
||||
OCI OCIConfig `toml:"oci"`
|
||||
Containerd ContainerdConfig `toml:"containerd"`
|
||||
} `toml:"worker"`
|
||||
}
|
||||
|
||||
type GRPCConfig struct {
|
||||
Address []string `toml:"address"`
|
||||
DebugAddress string `toml:"debugAddress"`
|
||||
UID int `toml:"uid"`
|
||||
GID int `toml:"gid"`
|
||||
|
||||
TLS TLSConfig `toml:"tls"`
|
||||
// MaxRecvMsgSize int `toml:"max_recv_message_size"`
|
||||
// MaxSendMsgSize int `toml:"max_send_message_size"`
|
||||
}
|
||||
|
||||
type TLSConfig struct {
|
||||
Cert string `toml:"cert"`
|
||||
Key string `toml:"key"`
|
||||
CA string `toml:"ca"`
|
||||
}
|
||||
|
||||
type OCIConfig struct {
|
||||
Enabled *bool `toml:"enabled"`
|
||||
Labels map[string]string `toml:"labels"`
|
||||
Platforms []string `toml:"platforms"`
|
||||
Snapshotter string `toml:"snapshotter"`
|
||||
Rootless bool `toml:"rootless"`
|
||||
}
|
||||
|
||||
type ContainerdConfig struct {
|
||||
Address string `toml:"address"`
|
||||
Enabled *bool `toml:"enabled"`
|
||||
Labels map[string]string `toml:"labels"`
|
||||
Platforms []string `toml:"platforms"`
|
||||
}
|
||||
|
||||
func Load(r io.Reader) (Config, *toml.MetaData, error) {
|
||||
var c Config
|
||||
md, err := toml.DecodeReader(r, &c)
|
||||
if err != nil {
|
||||
return c, nil, errors.Wrap(err, "failed to parse config")
|
||||
}
|
||||
return c, &md, nil
|
||||
}
|
||||
|
||||
func LoadFile(fp string) (Config, *toml.MetaData, error) {
|
||||
f, err := os.Open(fp)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return Config{}, nil, nil
|
||||
}
|
||||
return Config{}, nil, errors.Wrapf(err, "failed to load config from %s", fp)
|
||||
}
|
||||
defer f.Close()
|
||||
return Load(f)
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestConfig(t *testing.T) {
|
||||
|
||||
const testConfig = `
|
||||
root = "/foo/bar"
|
||||
debug=true
|
||||
|
||||
[grpc]
|
||||
address=["buildkit.sock"]
|
||||
debugAddress="debug.sock"
|
||||
gid=1234
|
||||
[grpc.tls]
|
||||
cert="mycert.pem"
|
||||
|
||||
[worker.oci]
|
||||
enabled=true
|
||||
snapshotter="overlay"
|
||||
rootless=true
|
||||
[worker.oci.labels]
|
||||
foo="bar"
|
||||
"aa.bb.cc"="baz"
|
||||
|
||||
[worker.containerd]
|
||||
platforms=["linux/amd64"]
|
||||
address="containerd.sock"
|
||||
`
|
||||
|
||||
cfg, md, err := Load(bytes.NewBuffer([]byte(testConfig)))
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, "/foo/bar", cfg.Root)
|
||||
require.Equal(t, true, cfg.Debug)
|
||||
|
||||
require.Equal(t, "buildkit.sock", cfg.GRPC.Address[0])
|
||||
require.Equal(t, "debug.sock", cfg.GRPC.DebugAddress)
|
||||
require.Equal(t, 1234, cfg.GRPC.GID)
|
||||
require.Equal(t, "mycert.pem", cfg.GRPC.TLS.Cert)
|
||||
|
||||
require.True(t, md.IsDefined("grpc", "gid"))
|
||||
require.False(t, md.IsDefined("grpc", "uid"))
|
||||
|
||||
require.NotNil(t, cfg.Workers.OCI.Enabled)
|
||||
require.Equal(t, true, *cfg.Workers.OCI.Enabled)
|
||||
require.Equal(t, "overlay", cfg.Workers.OCI.Snapshotter)
|
||||
require.Equal(t, true, cfg.Workers.OCI.Rootless)
|
||||
|
||||
require.Equal(t, "bar", cfg.Workers.OCI.Labels["foo"])
|
||||
require.Equal(t, "baz", cfg.Workers.OCI.Labels["aa.bb.cc"])
|
||||
|
||||
require.Nil(t, cfg.Workers.Containerd.Enabled)
|
||||
require.Equal(t, 1, len(cfg.Workers.Containerd.Platforms))
|
||||
require.Equal(t, "containerd.sock", cfg.Workers.Containerd.Address)
|
||||
}
|
|
@ -14,12 +14,14 @@ import (
|
|||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/BurntSushi/toml"
|
||||
"github.com/containerd/containerd/pkg/seed"
|
||||
"github.com/containerd/containerd/platforms"
|
||||
"github.com/containerd/containerd/sys"
|
||||
"github.com/docker/go-connections/sockets"
|
||||
"github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc"
|
||||
registryremotecache "github.com/moby/buildkit/cache/remotecache/registry"
|
||||
"github.com/moby/buildkit/cmd/buildkitd/config"
|
||||
"github.com/moby/buildkit/control"
|
||||
"github.com/moby/buildkit/frontend"
|
||||
dockerfile "github.com/moby/buildkit/frontend/dockerfile/builder"
|
||||
|
@ -50,7 +52,7 @@ func init() {
|
|||
|
||||
type workerInitializerOpt struct {
|
||||
sessionManager *session.Manager
|
||||
root string
|
||||
config *config.Config
|
||||
}
|
||||
|
||||
type workerInitializer struct {
|
||||
|
@ -80,29 +82,35 @@ func main() {
|
|||
app := cli.NewApp()
|
||||
app.Name = "buildkitd"
|
||||
app.Usage = "build daemon"
|
||||
defaultRoot := appdefaults.Root
|
||||
defaultAddress := appdefaults.Address
|
||||
|
||||
defaultConf, md := defaultConf()
|
||||
|
||||
rootlessUsage := "set all the default options to be compatible with rootless containers"
|
||||
if system.RunningInUserNS() {
|
||||
app.Flags = append(app.Flags, cli.BoolTFlag{
|
||||
Name: "rootless",
|
||||
Usage: rootlessUsage + " (default: true)",
|
||||
})
|
||||
// if buildkitd is being executed as the mapped-root (not only EUID==0 but also $USER==root)
|
||||
// in a user namespace, we need to enable the rootless mode but
|
||||
// we don't want to honor $HOME for setting up default paths.
|
||||
if u := os.Getenv("USER"); u != "" && u != "root" {
|
||||
defaultRoot = appdefaults.UserRoot()
|
||||
defaultAddress = appdefaults.UserAddress()
|
||||
appdefaults.EnsureUserAddressDir()
|
||||
}
|
||||
} else {
|
||||
app.Flags = append(app.Flags, cli.BoolFlag{
|
||||
Name: "rootless",
|
||||
Usage: rootlessUsage,
|
||||
})
|
||||
}
|
||||
|
||||
groupValue := func(gid int) string {
|
||||
if md == nil || !md.IsDefined("grpc", "gid") {
|
||||
return ""
|
||||
}
|
||||
return strconv.Itoa(gid)
|
||||
}
|
||||
|
||||
app.Flags = append(app.Flags,
|
||||
cli.StringFlag{
|
||||
Name: "config",
|
||||
Usage: "path to config file",
|
||||
Value: defaultConfigPath(),
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "debug",
|
||||
Usage: "enable debug output in logs",
|
||||
|
@ -110,34 +118,37 @@ func main() {
|
|||
cli.StringFlag{
|
||||
Name: "root",
|
||||
Usage: "path to state directory",
|
||||
Value: defaultRoot,
|
||||
Value: defaultConf.Root,
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "addr",
|
||||
Usage: "listening address (socket or tcp)",
|
||||
Value: &cli.StringSlice{defaultAddress},
|
||||
Value: &cli.StringSlice{defaultConf.GRPC.Address[0]},
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "group",
|
||||
Usage: "group (name or gid) which will own all Unix socket listening addresses",
|
||||
Value: "",
|
||||
Value: groupValue(defaultConf.GRPC.GID),
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "debugaddr",
|
||||
Usage: "debugging address (eg. 0.0.0.0:6060)",
|
||||
Value: "",
|
||||
Value: defaultConf.GRPC.DebugAddress,
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "tlscert",
|
||||
Usage: "certificate file to use",
|
||||
Value: defaultConf.GRPC.TLS.Cert,
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "tlskey",
|
||||
Usage: "key file to use",
|
||||
Value: defaultConf.GRPC.TLS.Key,
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "tlscacert",
|
||||
Usage: "ca certificate to verify clients",
|
||||
Value: defaultConf.GRPC.TLS.CA,
|
||||
},
|
||||
)
|
||||
app.Flags = append(app.Flags, appFlags...)
|
||||
|
@ -149,13 +160,27 @@ func main() {
|
|||
ctx, cancel := context.WithCancel(appcontext.Context())
|
||||
defer cancel()
|
||||
|
||||
if debugAddr := c.GlobalString("debugaddr"); debugAddr != "" {
|
||||
if err := setupDebugHandlers(debugAddr); err != nil {
|
||||
cfg, md, err := config.LoadFile(c.GlobalString("config"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
setDefaultConfig(&cfg)
|
||||
if err := applyMainFlags(c, &cfg, md); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if cfg.Debug {
|
||||
logrus.SetLevel(logrus.DebugLevel)
|
||||
}
|
||||
|
||||
if cfg.GRPC.DebugAddress != "" {
|
||||
if err := setupDebugHandlers(cfg.GRPC.DebugAddress); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
opts := []grpc.ServerOption{unaryInterceptor(ctx), grpc.StreamInterceptor(otgrpc.OpenTracingStreamServerInterceptor(tracer))}
|
||||
creds, err := serverCredentials(c)
|
||||
creds, err := serverCredentials(cfg.GRPC.TLS)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -165,16 +190,17 @@ func main() {
|
|||
server := grpc.NewServer(opts...)
|
||||
|
||||
// relative path does not work with nightlyone/lockfile
|
||||
root, err := filepath.Abs(c.GlobalString("root"))
|
||||
root, err := filepath.Abs(cfg.Root)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cfg.Root = root
|
||||
|
||||
if err := os.MkdirAll(root, 0700); err != nil {
|
||||
return errors.Wrapf(err, "failed to create %s", root)
|
||||
}
|
||||
|
||||
controller, err := newController(c, root)
|
||||
controller, err := newController(c, &cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -182,11 +208,7 @@ func main() {
|
|||
controller.Register(server)
|
||||
|
||||
errCh := make(chan error, 1)
|
||||
addrs := c.GlobalStringSlice("addr")
|
||||
if len(addrs) > 1 {
|
||||
addrs = addrs[1:] // https://github.com/urfave/cli/issues/160
|
||||
}
|
||||
if err := serveGRPC(c, server, addrs, errCh); err != nil {
|
||||
if err := serveGRPC(cfg.GRPC, server, errCh); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -203,12 +225,6 @@ func main() {
|
|||
|
||||
return err
|
||||
}
|
||||
app.Before = func(context *cli.Context) error {
|
||||
if context.GlobalBool("debug") {
|
||||
logrus.SetLevel(logrus.DebugLevel)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
app.After = func(context *cli.Context) error {
|
||||
if closeTracer != nil {
|
||||
|
@ -225,14 +241,15 @@ func main() {
|
|||
}
|
||||
}
|
||||
|
||||
func serveGRPC(c *cli.Context, server *grpc.Server, addrs []string, errCh chan error) error {
|
||||
func serveGRPC(cfg config.GRPCConfig, server *grpc.Server, errCh chan error) error {
|
||||
addrs := cfg.Address
|
||||
if len(addrs) == 0 {
|
||||
return errors.New("--addr cannot be empty")
|
||||
}
|
||||
eg, _ := errgroup.WithContext(context.Background())
|
||||
listeners := make([]net.Listener, 0, len(addrs))
|
||||
for _, addr := range addrs {
|
||||
l, err := getListener(c, addr)
|
||||
l, err := getListener(cfg, addr)
|
||||
if err != nil {
|
||||
for _, l := range listeners {
|
||||
l.Close()
|
||||
|
@ -256,6 +273,102 @@ func serveGRPC(c *cli.Context, server *grpc.Server, addrs []string, errCh chan e
|
|||
return nil
|
||||
}
|
||||
|
||||
func defaultConfigPath() string {
|
||||
if system.RunningInUserNS() {
|
||||
return filepath.Join(appdefaults.UserConfigDir(), "buildkitd.toml")
|
||||
}
|
||||
return filepath.Join(appdefaults.ConfigDir, "buildkitd.toml")
|
||||
}
|
||||
|
||||
func defaultConf() (config.Config, *toml.MetaData) {
|
||||
cfg, md, err := config.LoadFile(defaultConfigPath())
|
||||
if err != nil {
|
||||
return cfg, nil
|
||||
}
|
||||
setDefaultConfig(&cfg)
|
||||
|
||||
return cfg, md
|
||||
}
|
||||
|
||||
func setDefaultConfig(cfg *config.Config) {
|
||||
orig := *cfg
|
||||
|
||||
if cfg.Root == "" {
|
||||
cfg.Root = appdefaults.Root
|
||||
}
|
||||
|
||||
if len(cfg.GRPC.Address) == 0 {
|
||||
cfg.GRPC.Address = []string{appdefaults.Address}
|
||||
}
|
||||
|
||||
if system.RunningInUserNS() {
|
||||
// if buildkitd is being executed as the mapped-root (not only EUID==0 but also $USER==root)
|
||||
// in a user namespace, we need to enable the rootless mode but
|
||||
// we don't want to honor $HOME for setting up default paths.
|
||||
if u := os.Getenv("USER"); u != "" && u != "root" {
|
||||
if orig.Root == "" {
|
||||
cfg.Root = appdefaults.UserRoot()
|
||||
}
|
||||
if len(orig.GRPC.Address) == 0 {
|
||||
cfg.GRPC.Address = []string{appdefaults.UserAddress()}
|
||||
}
|
||||
appdefaults.EnsureUserAddressDir()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func applyMainFlags(c *cli.Context, cfg *config.Config, md *toml.MetaData) error {
|
||||
if c.IsSet("debug") {
|
||||
cfg.Debug = c.Bool("debug")
|
||||
}
|
||||
if c.IsSet("root") {
|
||||
cfg.Root = c.String("root")
|
||||
}
|
||||
|
||||
if c.IsSet("addr") || len(cfg.GRPC.Address) == 0 {
|
||||
addrs := c.StringSlice("addr")
|
||||
if len(addrs) > 1 {
|
||||
addrs = addrs[1:] // https://github.com/urfave/cli/issues/160
|
||||
}
|
||||
|
||||
cfg.GRPC.Address = make([]string, 0, len(addrs))
|
||||
for _, v := range addrs {
|
||||
cfg.GRPC.Address = append(cfg.GRPC.Address, v)
|
||||
}
|
||||
}
|
||||
|
||||
if c.IsSet("debugaddr") {
|
||||
cfg.GRPC.DebugAddress = c.String("debugaddr")
|
||||
}
|
||||
|
||||
if md == nil || !md.IsDefined("grpc", "uid") {
|
||||
cfg.GRPC.UID = os.Getuid()
|
||||
}
|
||||
|
||||
if md == nil || !md.IsDefined("grpc", "gid") {
|
||||
cfg.GRPC.GID = os.Getgid()
|
||||
}
|
||||
|
||||
if group := c.String("group"); group != "" {
|
||||
gid, err := groupToGid(group)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cfg.GRPC.GID = gid
|
||||
}
|
||||
|
||||
if tlscert := c.String("tlscert"); tlscert != "" {
|
||||
cfg.GRPC.TLS.Cert = tlscert
|
||||
}
|
||||
if tlskey := c.String("tlskey"); tlskey != "" {
|
||||
cfg.GRPC.TLS.Key = tlskey
|
||||
}
|
||||
if tlsca := c.String("tlsca"); tlsca != "" {
|
||||
cfg.GRPC.TLS.CA = tlsca
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert a string containing either a group name or a stringified gid into a numeric id)
|
||||
func groupToGid(group string) (int, error) {
|
||||
if group == "" {
|
||||
|
@ -289,7 +402,7 @@ func groupToGid(group string) (int, error) {
|
|||
return id, nil
|
||||
}
|
||||
|
||||
func getListener(c *cli.Context, addr string) (net.Listener, error) {
|
||||
func getListener(cfg config.GRPCConfig, addr string) (net.Listener, error) {
|
||||
addrSlice := strings.SplitN(addr, "://", 2)
|
||||
if len(addrSlice) < 2 {
|
||||
return nil, errors.Errorf("address %s does not contain proto, you meant unix://%s ?",
|
||||
|
@ -299,12 +412,7 @@ func getListener(c *cli.Context, addr string) (net.Listener, error) {
|
|||
listenAddr := addrSlice[1]
|
||||
switch proto {
|
||||
case "unix", "npipe":
|
||||
uid := os.Getuid()
|
||||
gid, err := groupToGid(c.GlobalString("group"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return sys.GetLocalListener(listenAddr, uid, gid)
|
||||
return sys.GetLocalListener(listenAddr, cfg.UID, cfg.GID)
|
||||
case "tcp":
|
||||
return sockets.NewTCPSocket(listenAddr, nil)
|
||||
default:
|
||||
|
@ -335,10 +443,10 @@ func unaryInterceptor(globalCtx context.Context) grpc.ServerOption {
|
|||
})
|
||||
}
|
||||
|
||||
func serverCredentials(c *cli.Context) (grpc.ServerOption, error) {
|
||||
certFile := c.GlobalString("tlscert")
|
||||
keyFile := c.GlobalString("tlskey")
|
||||
caFile := c.GlobalString("tlscacert")
|
||||
func serverCredentials(cfg config.TLSConfig) (grpc.ServerOption, error) {
|
||||
certFile := cfg.Cert
|
||||
keyFile := cfg.Key
|
||||
caFile := cfg.CA
|
||||
if certFile == "" && keyFile == "" {
|
||||
return nil, nil
|
||||
}
|
||||
|
@ -373,14 +481,14 @@ func serverCredentials(c *cli.Context) (grpc.ServerOption, error) {
|
|||
return creds, nil
|
||||
}
|
||||
|
||||
func newController(c *cli.Context, root string) (*control.Controller, error) {
|
||||
func newController(c *cli.Context, cfg *config.Config) (*control.Controller, error) {
|
||||
sessionManager, err := session.NewManager()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
wc, err := newWorkerController(c, workerInitializerOpt{
|
||||
sessionManager: sessionManager,
|
||||
root: root,
|
||||
config: cfg,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -389,7 +497,7 @@ func newController(c *cli.Context, root string) (*control.Controller, error) {
|
|||
frontends["dockerfile.v0"] = forwarder.NewGatewayForwarder(wc, dockerfile.Build)
|
||||
frontends["gateway.v0"] = gateway.NewGatewayFrontend(wc)
|
||||
|
||||
cacheStorage, err := boltdbcachestorage.NewStore(filepath.Join(root, "cache.db"))
|
||||
cacheStorage, err := boltdbcachestorage.NewStore(filepath.Join(cfg.Root, "cache.db"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -4,10 +4,12 @@ package main
|
|||
|
||||
import (
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
ctd "github.com/containerd/containerd"
|
||||
"github.com/moby/buildkit/cmd/buildkitd/config"
|
||||
"github.com/moby/buildkit/worker"
|
||||
"github.com/moby/buildkit/worker/base"
|
||||
"github.com/moby/buildkit/worker/containerd"
|
||||
|
@ -16,7 +18,22 @@ import (
|
|||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
const defaultContainerdAddress = "/run/containerd/containerd.sock"
|
||||
|
||||
func init() {
|
||||
defaultConf, _ := defaultConf()
|
||||
|
||||
enabledValue := func(b *bool) string {
|
||||
if b == nil {
|
||||
return "auto"
|
||||
}
|
||||
return strconv.FormatBool(*b)
|
||||
}
|
||||
|
||||
if defaultConf.Workers.Containerd.Address == "" {
|
||||
defaultConf.Workers.Containerd.Address = defaultContainerdAddress
|
||||
}
|
||||
|
||||
registerWorkerInitializer(
|
||||
workerInitializer{
|
||||
fn: containerdWorkerInitializer,
|
||||
|
@ -26,12 +43,12 @@ func init() {
|
|||
cli.StringFlag{
|
||||
Name: "containerd-worker",
|
||||
Usage: "enable containerd workers (true/false/auto)",
|
||||
Value: "auto",
|
||||
Value: enabledValue(defaultConf.Workers.Containerd.Enabled),
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "containerd-worker-addr",
|
||||
Usage: "containerd socket",
|
||||
Value: "/run/containerd/containerd.sock",
|
||||
Value: defaultConf.Workers.Containerd.Address,
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "containerd-worker-labels",
|
||||
|
@ -48,32 +65,64 @@ func init() {
|
|||
// TODO(AkihiroSuda): allow using multiple snapshotters. should be useful for some applications that does not work with the default overlay snapshotter. e.g. mysql (docker/for-linux#72)",
|
||||
}
|
||||
|
||||
func containerdWorkerInitializer(c *cli.Context, common workerInitializerOpt) ([]worker.Worker, error) {
|
||||
socket := c.GlobalString("containerd-worker-addr")
|
||||
boolOrAuto, err := parseBoolOrAuto(c.GlobalString("containerd-worker"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
func applyContainerdFlags(c *cli.Context, cfg *config.Config) error {
|
||||
if cfg.Workers.Containerd.Address == "" {
|
||||
cfg.Workers.Containerd.Address = defaultContainerdAddress
|
||||
}
|
||||
if (boolOrAuto == nil && !validContainerdSocket(socket)) || (boolOrAuto != nil && !*boolOrAuto) {
|
||||
return nil, nil
|
||||
}
|
||||
labels, err := attrMap(c.GlobalStringSlice("containerd-worker-labels"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
if c.GlobalIsSet("containerd-worker") {
|
||||
boolOrAuto, err := parseBoolOrAuto(c.GlobalString("containerd-worker"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cfg.Workers.Containerd.Enabled = boolOrAuto
|
||||
}
|
||||
|
||||
// GlobalBool works for BoolT as well
|
||||
rootless := c.GlobalBool("rootless")
|
||||
if rootless {
|
||||
logrus.Warn("rootless mode is not supported for containerd workers. disabling containerd worker.")
|
||||
b := false
|
||||
cfg.Workers.Containerd.Enabled = &b
|
||||
return nil
|
||||
}
|
||||
|
||||
labels, err := attrMap(c.GlobalStringSlice("containerd-worker-labels"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for k, v := range labels {
|
||||
cfg.Workers.Containerd.Labels[k] = v
|
||||
}
|
||||
if c.GlobalIsSet("containerd-worker-addr") {
|
||||
cfg.Workers.Containerd.Address = c.GlobalString("containerd-worker-addr")
|
||||
}
|
||||
|
||||
if platforms := c.GlobalStringSlice("containerd-worker-platform"); len(platforms) != 0 {
|
||||
cfg.Workers.Containerd.Platforms = platforms
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func containerdWorkerInitializer(c *cli.Context, common workerInitializerOpt) ([]worker.Worker, error) {
|
||||
if err := applyContainerdFlags(c, common.config); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cfg := common.config.Workers.Containerd
|
||||
|
||||
if (cfg.Enabled == nil && !validContainerdSocket(cfg.Address)) || (cfg.Enabled != nil && !*cfg.Enabled) {
|
||||
return nil, nil
|
||||
}
|
||||
opt, err := containerd.NewWorkerOpt(common.root, socket, ctd.DefaultSnapshotter, labels, ctd.WithTimeout(60*time.Second))
|
||||
|
||||
opt, err := containerd.NewWorkerOpt(common.config.Root, cfg.Address, ctd.DefaultSnapshotter, cfg.Labels, ctd.WithTimeout(60*time.Second))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
opt.SessionManager = common.sessionManager
|
||||
|
||||
if platformsStr := c.GlobalStringSlice("containerd-worker-platform"); len(platformsStr) != 0 {
|
||||
if platformsStr := cfg.Platforms; len(platformsStr) != 0 {
|
||||
platforms, err := parsePlatforms(platformsStr)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "invalid platforms")
|
||||
|
|
|
@ -4,10 +4,12 @@ package main
|
|||
|
||||
import (
|
||||
"os/exec"
|
||||
"strconv"
|
||||
|
||||
ctdsnapshot "github.com/containerd/containerd/snapshots"
|
||||
"github.com/containerd/containerd/snapshots/native"
|
||||
"github.com/containerd/containerd/snapshots/overlay"
|
||||
"github.com/moby/buildkit/cmd/buildkitd/config"
|
||||
"github.com/moby/buildkit/worker"
|
||||
"github.com/moby/buildkit/worker/base"
|
||||
"github.com/moby/buildkit/worker/runc"
|
||||
|
@ -18,11 +20,24 @@ import (
|
|||
)
|
||||
|
||||
func init() {
|
||||
defaultConf, _ := defaultConf()
|
||||
|
||||
enabledValue := func(b *bool) string {
|
||||
if b == nil {
|
||||
return "auto"
|
||||
}
|
||||
return strconv.FormatBool(*b)
|
||||
}
|
||||
|
||||
if defaultConf.Workers.OCI.Snapshotter == "" {
|
||||
defaultConf.Workers.OCI.Snapshotter = "auto"
|
||||
}
|
||||
|
||||
flags := []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "oci-worker",
|
||||
Usage: "enable oci workers (true/false/auto)",
|
||||
Value: "auto",
|
||||
Value: enabledValue(defaultConf.Workers.OCI.Enabled),
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "oci-worker-labels",
|
||||
|
@ -31,7 +46,7 @@ func init() {
|
|||
cli.StringFlag{
|
||||
Name: "oci-worker-snapshotter",
|
||||
Usage: "name of snapshotter (overlayfs or native)",
|
||||
Value: "auto",
|
||||
Value: defaultConf.Workers.OCI.Snapshotter,
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "oci-worker-platform",
|
||||
|
@ -61,34 +76,70 @@ func init() {
|
|||
// TODO: allow multiple oci runtimes
|
||||
}
|
||||
|
||||
func ociWorkerInitializer(c *cli.Context, common workerInitializerOpt) ([]worker.Worker, error) {
|
||||
boolOrAuto, err := parseBoolOrAuto(c.GlobalString("oci-worker"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
func applyOCIFlags(c *cli.Context, cfg *config.Config) error {
|
||||
if cfg.Workers.OCI.Snapshotter == "" {
|
||||
cfg.Workers.OCI.Snapshotter = "auto"
|
||||
}
|
||||
if (boolOrAuto == nil && !validOCIBinary()) || (boolOrAuto != nil && !*boolOrAuto) {
|
||||
return nil, nil
|
||||
|
||||
if c.GlobalIsSet("oci-worker") {
|
||||
boolOrAuto, err := parseBoolOrAuto(c.GlobalString("oci-worker"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cfg.Workers.OCI.Enabled = boolOrAuto
|
||||
}
|
||||
|
||||
labels, err := attrMap(c.GlobalStringSlice("oci-worker-labels"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for k, v := range labels {
|
||||
cfg.Workers.OCI.Labels[k] = v
|
||||
}
|
||||
if c.GlobalIsSet("oci-worker-snapshotter") {
|
||||
cfg.Workers.OCI.Snapshotter = c.GlobalString("oci-worker-snapshotter")
|
||||
}
|
||||
|
||||
if c.GlobalIsSet("rootless") || c.GlobalBool("rootless") {
|
||||
cfg.Workers.OCI.Rootless = c.GlobalBool("rootless")
|
||||
}
|
||||
if c.GlobalIsSet("oci-worker-rootless") {
|
||||
cfg.Workers.OCI.Rootless = c.GlobalBool("oci-worker-rootless")
|
||||
}
|
||||
|
||||
if platforms := c.GlobalStringSlice("oci-worker-platform"); len(platforms) != 0 {
|
||||
cfg.Workers.OCI.Platforms = platforms
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func ociWorkerInitializer(c *cli.Context, common workerInitializerOpt) ([]worker.Worker, error) {
|
||||
if err := applyOCIFlags(c, common.config); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
snFactory, err := snapshotterFactory(common.root, c.GlobalString("oci-worker-snapshotter"))
|
||||
|
||||
cfg := common.config.Workers.OCI
|
||||
|
||||
if (cfg.Enabled == nil && !validOCIBinary()) || (cfg.Enabled != nil && !*cfg.Enabled) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
snFactory, err := snapshotterFactory(common.config.Root, cfg.Snapshotter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// GlobalBool works for BoolT as well
|
||||
rootless := c.GlobalBool("oci-worker-rootless") || c.GlobalBool("rootless")
|
||||
if rootless {
|
||||
|
||||
if cfg.Rootless {
|
||||
logrus.Debugf("running in rootless mode")
|
||||
}
|
||||
opt, err := runc.NewWorkerOpt(common.root, snFactory, rootless, labels)
|
||||
opt, err := runc.NewWorkerOpt(common.config.Root, snFactory, cfg.Rootless, cfg.Labels)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
opt.SessionManager = common.sessionManager
|
||||
platformsStr := c.GlobalStringSlice("oci-worker-platform")
|
||||
if len(platformsStr) != 0 {
|
||||
|
||||
if platformsStr := cfg.Platforms; len(platformsStr) != 0 {
|
||||
platforms, err := parsePlatforms(platformsStr)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "invalid platforms")
|
||||
|
|
|
@ -9,8 +9,9 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
Address = "unix:///run/buildkit/buildkitd.sock"
|
||||
Root = "/var/lib/buildkit"
|
||||
Address = "unix:///run/buildkit/buildkitd.sock"
|
||||
Root = "/var/lib/buildkit"
|
||||
ConfigDir = "/etc/buildkit"
|
||||
)
|
||||
|
||||
// UserAddress typically returns /run/user/$UID/buildkit/buildkitd.sock
|
||||
|
@ -53,3 +54,16 @@ func UserRoot() string {
|
|||
}
|
||||
return Root
|
||||
}
|
||||
|
||||
// UserConfigDir returns dir for storing config. /home/$USER/.config/buildkit/
|
||||
func UserConfigDir() string {
|
||||
xdgConfigHome := os.Getenv("XDG_CONFIG_HOME")
|
||||
if xdgConfigHome != "" {
|
||||
return filepath.Join(xdgConfigHome, "buildkit")
|
||||
}
|
||||
home := os.Getenv("HOME")
|
||||
if home != "" {
|
||||
return filepath.Join(home, ".config", "buildkit")
|
||||
}
|
||||
return ConfigDir
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
package appdefaults
|
||||
|
||||
const (
|
||||
Address = "npipe:////./pipe/buildkitd"
|
||||
Root = ".buildstate"
|
||||
Address = "npipe:////./pipe/buildkitd"
|
||||
Root = ".buildstate"
|
||||
ConfigDir = ""
|
||||
)
|
||||
|
||||
func UserAddress() string {
|
||||
|
@ -16,3 +17,7 @@ func EnsureUserAddressDir() error {
|
|||
func UserRoot() string {
|
||||
return Root
|
||||
}
|
||||
|
||||
func UserConfigDir() string {
|
||||
return ConfigDir
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue