Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

store snapshot of config files on create #824

Merged
merged 2 commits into from
Nov 4, 2021
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions commands/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ func driversForNodeGroup(ctx context.Context, dockerCli command.Cli, ng *store.N
}
}

d, err := driver.GetDriver(ctx, "buildx_buildkit_"+n.Name, f, dockerapi, dockerCli.ConfigFile(), kcc, n.Flags, n.ConfigFile, n.DriverOpts, n.Platforms, contextPathHash)
d, err := driver.GetDriver(ctx, "buildx_buildkit_"+n.Name, f, dockerapi, dockerCli.ConfigFile(), kcc, n.Flags, n.Files, n.DriverOpts, n.Platforms, contextPathHash)
if err != nil {
di.Err = err
return nil
Expand Down Expand Up @@ -360,7 +360,7 @@ func getDefaultDrivers(ctx context.Context, dockerCli command.Cli, defaultOnly b
}
}

d, err := driver.GetDriver(ctx, "buildx_buildkit_default", nil, dockerCli.Client(), dockerCli.ConfigFile(), nil, nil, "", nil, nil, contextPathHash)
d, err := driver.GetDriver(ctx, "buildx_buildkit_default", nil, dockerCli.Client(), dockerCli.ConfigFile(), nil, nil, nil, nil, nil, contextPathHash)
if err != nil {
return nil, err
}
Expand Down
48 changes: 37 additions & 11 deletions driver/docker-container/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (
"io/ioutil"
"net"
"os"
"path"
"path/filepath"
"time"

"github.com/docker/buildx/driver"
Expand Down Expand Up @@ -134,15 +136,8 @@ func (d *Driver) create(ctx context.Context, l progress.SubLogger) error {
if err != nil {
return err
}
if f := d.InitConfig.ConfigFile; f != "" {
configFiles, err := confutil.LoadConfigFiles(f)
if err != nil {
return err
}
defer os.RemoveAll(configFiles)
if err := d.copyToContainer(ctx, configFiles, "/"); err != nil {
return err
}
if err := d.copyToContainer(ctx, d.InitConfig.Files); err != nil {
return err
}
if err := d.start(ctx, l); err != nil {
return err
Expand Down Expand Up @@ -202,15 +197,22 @@ func (d *Driver) copyLogs(ctx context.Context, l progress.SubLogger) error {
return rc.Close()
}

func (d *Driver) copyToContainer(ctx context.Context, srcPath string, dstDir string) error {
func (d *Driver) copyToContainer(ctx context.Context, files map[string][]byte) error {
srcPath, err := writeConfigFiles(files)
if err != nil {
return err
}
if srcPath != "" {
defer os.RemoveAll(srcPath)
}
srcArchive, err := dockerarchive.TarWithOptions(srcPath, &dockerarchive.TarOptions{
ChownOpts: &idtools.Identity{UID: 0, GID: 0},
})
if err != nil {
return err
}
defer srcArchive.Close()
return d.DockerAPI.CopyToContainer(ctx, d.Name, dstDir, srcArchive, dockertypes.CopyToContainerOptions{})
return d.DockerAPI.CopyToContainer(ctx, d.Name, "/", srcArchive, dockertypes.CopyToContainerOptions{})
}

func (d *Driver) exec(ctx context.Context, cmd []string) (string, net.Conn, error) {
Expand Down Expand Up @@ -383,3 +385,27 @@ func (l *logWriter) Write(dt []byte) (int, error) {
l.logger.Log(l.stream, dt)
return len(dt), nil
}

func writeConfigFiles(m map[string][]byte) (_ string, err error) {
// Temp dir that will be copied to the container
tmpDir, err := os.MkdirTemp("", "buildkitd-config")
if err != nil {
return "", err
}
defer func() {
if err != nil {
os.RemoveAll(tmpDir)
}
}()
for f, dt := range m {
f = path.Join(confutil.DefaultBuildKitConfigDir, f)
p := filepath.Join(tmpDir, f)
if err := os.MkdirAll(filepath.Dir(p), 0700); err != nil {
return "", err
}
if err := os.WriteFile(p, dt, 0600); err != nil {
return "", err
}
}
return tmpDir, nil
}
2 changes: 1 addition & 1 deletion driver/docker/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func (f *factory) New(ctx context.Context, cfg driver.InitConfig) (driver.Driver
if cfg.DockerAPI == nil {
return nil, errors.Errorf("docker driver requires docker API access")
}
if cfg.ConfigFile != "" {
if len(cfg.Files) > 0 {
return nil, errors.Errorf("setting config file is not supported for docker driver, use dockerd configuration file")
}

Expand Down
18 changes: 9 additions & 9 deletions driver/kubernetes/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ type Driver struct {
factory driver.Factory
minReplicas int
deployment *appsv1.Deployment
configMap *corev1.ConfigMap
configMaps []*corev1.ConfigMap
clientset *kubernetes.Clientset
deploymentClient clientappsv1.DeploymentInterface
podClient clientcorev1.PodInterface
Expand All @@ -65,16 +65,16 @@ func (d *Driver) Bootstrap(ctx context.Context, l progress.Logger) error {
return errors.Wrapf(err, "error for bootstrap %q", d.deployment.Name)
}

if d.configMap != nil {
for _, cfg := range d.configMaps {
// create ConfigMap first if exists
_, err = d.configMapClient.Create(ctx, d.configMap, metav1.CreateOptions{})
_, err = d.configMapClient.Create(ctx, cfg, metav1.CreateOptions{})
if err != nil {
if !apierrors.IsAlreadyExists(err) {
return errors.Wrapf(err, "error while calling configMapClient.Create for %q", d.configMap.Name)
return errors.Wrapf(err, "error while calling configMapClient.Create for %q", cfg.Name)
}
_, err = d.configMapClient.Update(ctx, d.configMap, metav1.UpdateOptions{})
_, err = d.configMapClient.Update(ctx, cfg, metav1.UpdateOptions{})
if err != nil {
return errors.Wrapf(err, "error while calling configMapClient.Update for %q", d.configMap.Name)
return errors.Wrapf(err, "error while calling configMapClient.Update for %q", cfg.Name)
}
}
}
Expand Down Expand Up @@ -171,10 +171,10 @@ func (d *Driver) Rm(ctx context.Context, force bool, rmVolume bool) error {
return errors.Wrapf(err, "error while calling deploymentClient.Delete for %q", d.deployment.Name)
}
}
if d.configMap != nil {
if err := d.configMapClient.Delete(ctx, d.configMap.Name, metav1.DeleteOptions{}); err != nil {
for _, cfg := range d.configMaps {
if err := d.configMapClient.Delete(ctx, cfg.Name, metav1.DeleteOptions{}); err != nil {
if !apierrors.IsNotFound(err) {
return errors.Wrapf(err, "error while calling configMapClient.Delete for %q", d.configMap.Name)
return errors.Wrapf(err, "error while calling configMapClient.Delete for %q", cfg.Name)
}
}
}
Expand Down
12 changes: 2 additions & 10 deletions driver/kubernetes/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package kubernetes

import (
"context"
"os"
"strconv"
"strings"

Expand Down Expand Up @@ -74,18 +73,11 @@ func (f *factory) New(ctx context.Context, cfg driver.InitConfig) (driver.Driver
BuildkitFlags: cfg.BuildkitFlags,
Rootless: false,
Platforms: cfg.Platforms,
ConfigFiles: cfg.Files,
}

deploymentOpt.Qemu.Image = bkimage.QemuImage

if cfg.ConfigFile != "" {
buildkitConfig, err := os.ReadFile(cfg.ConfigFile)
if err != nil {
return nil, err
}
deploymentOpt.BuildkitConfig = buildkitConfig
}

loadbalance := LoadbalanceSticky

for k, v := range cfg.DriverOpts {
Expand Down Expand Up @@ -147,7 +139,7 @@ func (f *factory) New(ctx context.Context, cfg driver.InitConfig) (driver.Driver
}
}

d.deployment, d.configMap, err = manifest.NewDeployment(deploymentOpt)
d.deployment, d.configMaps, err = manifest.NewDeployment(deploymentOpt)
if err != nil {
return nil, err
}
Expand Down
59 changes: 45 additions & 14 deletions driver/kubernetes/manifest/manifest.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package manifest

import (
"fmt"
"path"
"strings"

"github.com/docker/buildx/util/platformutil"
Expand All @@ -25,9 +27,8 @@ type DeploymentOpt struct {
}

BuildkitFlags []string
// BuildkitConfig
// when not empty, will create configmap with buildkit.toml and mounted
BuildkitConfig []byte
// files mounted at /etc/buildkitd
ConfigFiles map[string][]byte

Rootless bool
NodeSelector map[string]string
Expand All @@ -43,7 +44,7 @@ const (
AnnotationPlatform = "buildx.docker.com/platform"
)

func NewDeployment(opt *DeploymentOpt) (d *appsv1.Deployment, c *corev1.ConfigMap, err error) {
func NewDeployment(opt *DeploymentOpt) (d *appsv1.Deployment, c []*corev1.ConfigMap, err error) {
labels := map[string]string{
"app": opt.Name,
}
Expand Down Expand Up @@ -103,38 +104,36 @@ func NewDeployment(opt *DeploymentOpt) (d *appsv1.Deployment, c *corev1.ConfigMa
},
},
}

if len(opt.BuildkitConfig) > 0 {
c = &corev1.ConfigMap{
for _, cfg := range splitConfigFiles(opt.ConfigFiles) {
cc := &corev1.ConfigMap{
TypeMeta: metav1.TypeMeta{
APIVersion: corev1.SchemeGroupVersion.String(),
Kind: "ConfigMap",
},
ObjectMeta: metav1.ObjectMeta{
Namespace: opt.Namespace,
Name: opt.Name + "-config",
Name: opt.Name + "-" + cfg.name,
Annotations: annotations,
},
Data: map[string]string{
"buildkitd.toml": string(opt.BuildkitConfig),
},
Data: cfg.files,
}

d.Spec.Template.Spec.Containers[0].VolumeMounts = []corev1.VolumeMount{{
Name: "config",
MountPath: "/etc/buildkit",
Name: cfg.name,
MountPath: path.Join("/etc/buildkit", cfg.path),
}}

d.Spec.Template.Spec.Volumes = []corev1.Volume{{
Name: "config",
VolumeSource: corev1.VolumeSource{
ConfigMap: &corev1.ConfigMapVolumeSource{
LocalObjectReference: corev1.LocalObjectReference{
Name: c.Name,
Name: cc.Name,
},
},
},
}}
c = append(c, cc)
}

if opt.Qemu.Install {
Expand Down Expand Up @@ -208,3 +207,35 @@ func toRootless(d *appsv1.Deployment) error {
d.Spec.Template.ObjectMeta.Annotations["container.seccomp.security.alpha.kubernetes.io/"+containerName] = "unconfined"
return nil
}

type config struct {
name string
path string
files map[string]string
}

func splitConfigFiles(m map[string][]byte) []config {
var c []config
idx := map[string]int{}
nameIdx := 0
for k, v := range m {
dir := path.Dir(k)
i, ok := idx[dir]
if !ok {
idx[dir] = len(c)
i = len(c)
name := "config"
if dir != "." {
nameIdx++
name = fmt.Sprintf("%s-%d", name, nameIdx)
}
c = append(c, config{
path: dir,
name: name,
files: map[string]string{},
})
}
c[i].files[path.Base(k)] = string(v)
}
return c
}
6 changes: 3 additions & 3 deletions driver/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ type InitConfig struct {
DockerAPI dockerclient.APIClient
KubeClientConfig KubeClientConfig
BuildkitFlags []string
ConfigFile string
Files map[string][]byte
DriverOpts map[string]string
Auth Auth
Platforms []specs.Platform
Expand Down Expand Up @@ -103,17 +103,17 @@ func GetFactory(name string, instanceRequired bool) Factory {
return nil
}

func GetDriver(ctx context.Context, name string, f Factory, api dockerclient.APIClient, auth Auth, kcc KubeClientConfig, flags []string, config string, do map[string]string, platforms []specs.Platform, contextPathHash string) (Driver, error) {
func GetDriver(ctx context.Context, name string, f Factory, api dockerclient.APIClient, auth Auth, kcc KubeClientConfig, flags []string, files map[string][]byte, do map[string]string, platforms []specs.Platform, contextPathHash string) (Driver, error) {
ic := InitConfig{
DockerAPI: api,
KubeClientConfig: kcc,
Name: name,
BuildkitFlags: flags,
ConfigFile: config,
DriverOpts: do,
Auth: auth,
Platforms: platforms,
ContextPathHash: contextPathHash,
Files: files,
}
if f == nil {
var err error
Expand Down
14 changes: 12 additions & 2 deletions store/nodegroup.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"

"github.com/containerd/containerd/platforms"
"github.com/docker/buildx/util/confutil"
"github.com/docker/buildx/util/platformutil"
specs "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
Expand All @@ -21,8 +22,9 @@ type Node struct {
Endpoint string
Platforms []specs.Platform
Flags []string
ConfigFile string
DriverOpts map[string]string

Files map[string][]byte
}

func (ng *NodeGroup) Leave(name string) error {
Expand Down Expand Up @@ -88,10 +90,18 @@ func (ng *NodeGroup) Update(name, endpoint string, platforms []string, endpoints
Name: name,
Endpoint: endpoint,
Platforms: pp,
ConfigFile: configFile,
Flags: flags,
DriverOpts: do,
}

if configFile != "" {
files, err := confutil.LoadConfigFiles(configFile)
if err != nil {
return err
}
n.Files = files
}

ng.Nodes = append(ng.Nodes, n)

if err := ng.validateDuplicates(endpoint, len(ng.Nodes)-1); err != nil {
Expand Down