From 4107f9a8756314a4b77d4cadc461421da2df6708 Mon Sep 17 00:00:00 2001 From: Lucas Perreau Date: Tue, 21 Sep 2021 08:47:27 +0200 Subject: [PATCH 1/3] fix(buildkitd): Start the daemon if it is not active Add a method that will retrieve the version, the running state and the network host existence of the buildkitd container. If the version is outdated or there is no host network, we delete the container and install a proper one. If the container is correctly configured but is not active, we start it, which saves some time. Signed-off-by: Lucas Perreau --- util/buildkitd/buildkit_information.go | 62 ++++++++++++ util/buildkitd/buildkitd.go | 127 ++++++++++++++++--------- 2 files changed, 142 insertions(+), 47 deletions(-) create mode 100644 util/buildkitd/buildkit_information.go diff --git a/util/buildkitd/buildkit_information.go b/util/buildkitd/buildkit_information.go new file mode 100644 index 00000000..55a9d2d9 --- /dev/null +++ b/util/buildkitd/buildkit_information.go @@ -0,0 +1,62 @@ +package buildkitd + +import ( + "context" + "fmt" + "os/exec" + "strconv" + "strings" + + "github.com/docker/distribution/reference" +) + +func getBuildkitInformation(ctx context.Context) (*BuilkitInformation, error) { + formatString := "{{.Config.Image}};{{.State.Running}};{{ if index .NetworkSettings.Networks \"host\" }}{{ \"true\" }}{{else}}{{\"false\"}}{{end}}" + cmd := exec.CommandContext(ctx, + "docker", + "inspect", + "--format", + formatString, + containerName, + ) + output, err := cmd.CombinedOutput() + if err != nil { + return nil, err + } + + s := strings.Split(string(output), ";") + + // Retrieve the tag + ref, err := reference.ParseNormalizedNamed(strings.TrimSpace(s[0])) + if err != nil { + return nil, err + } + tag, ok := ref.(reference.Tagged) + if !ok { + return nil, fmt.Errorf("failed to parse image: %s", output) + } + + // Retrieve the state + isActive, err := strconv.ParseBool(strings.TrimSpace(s[1])) + if err != nil { + return nil, err + } + + // Retrieve the check on if the host network is configured + haveHostNetwork, err := strconv.ParseBool(strings.TrimSpace(s[2])) + if err != nil { + return nil, err + } + + return &BuilkitInformation{ + Version: tag.Tag(), + IsActive: isActive, + HaveHostNetwork: haveHostNetwork, + }, nil +} + +type BuilkitInformation struct { + Version string + IsActive bool + HaveHostNetwork bool +} diff --git a/util/buildkitd/buildkitd.go b/util/buildkitd/buildkitd.go index 64563774..54bf245b 100644 --- a/util/buildkitd/buildkitd.go +++ b/util/buildkitd/buildkitd.go @@ -9,7 +9,6 @@ import ( "strings" "time" - "github.com/docker/distribution/reference" bk "github.com/moby/buildkit/client" _ "github.com/moby/buildkit/client/connhelper/dockercontainer" // import the container connection driver "github.com/rs/zerolog/log" @@ -41,48 +40,73 @@ func init() { } func Start(ctx context.Context) (string, error) { - lg := log.Ctx(ctx) - if vendoredVersion == "" { return "", fmt.Errorf("vendored version is empty") } - // Attempt to detect the current buildkit version - currentVersion, err := getBuildkitVersion(ctx) - if err != nil { - // If that failed, it might either be because buildkitd is not running - // or because the docker CLI is out of service. - if err := checkDocker(ctx); err != nil { - return "", err - } - - currentVersion = "" - lg.Debug().Msg("no buildkit daemon detected") - } else { - lg.Debug().Str("version", currentVersion).Msg("detected buildkit version") + if err := checkBuildkit(ctx); err != nil { + return "", err } - if currentVersion != vendoredVersion { - if currentVersion != "" { + return fmt.Sprintf("docker-container://%s", containerName), nil +} + +// ensure the buildkit is active and properly set up (e.g. connected to host and last version with moby/buildkit) +func checkBuildkit(ctx context.Context) error { + lg := log.Ctx(ctx) + + config, err := getBuildkitInformation(ctx) + if err != nil { + // If that failed, it might be because the docker CLI is out of service. + if err := checkDocker(ctx); err != nil { + return err + } + + lg.Debug().Msg("no buildkit daemon detected") + + if err := removeBuildkit(ctx); err != nil { + return err + } + + if err := installBuildkit(ctx); err != nil { + return err + } + + } else { + lg. + Debug(). + Str("version", config.Version). + Bool("isActive", config.IsActive). + Bool("haveHostNetwork", config.HaveHostNetwork). + Msg("detected buildkit config") + + if config.Version != vendoredVersion || !config.HaveHostNetwork { lg. Info(). Str("version", vendoredVersion). + Bool("have host network", config.HaveHostNetwork). Msg("upgrading buildkit") + if err := removeBuildkit(ctx); err != nil { - return "", err + return err } - } else { + if err := installBuildkit(ctx); err != nil { + return err + } + } + if !config.IsActive { lg. Info(). Str("version", vendoredVersion). Msg("starting buildkit") - } - if err := startBuildkit(ctx); err != nil { - return "", err + + if err := startBuildkit(ctx); err != nil { + return err + } } } - return fmt.Sprintf("docker-container://%s", containerName), nil + return nil } // ensure the docker CLI is available and properly set up (e.g. permissions to @@ -103,6 +127,7 @@ func checkDocker(ctx context.Context) error { return nil } +// Start the buildkit daemon func startBuildkit(ctx context.Context) error { lg := log. Ctx(ctx). @@ -110,6 +135,35 @@ func startBuildkit(ctx context.Context) error { Str("version", vendoredVersion). Logger() + lg.Debug().Msg("starting buildkit image") + + cmd := exec.CommandContext(ctx, + "docker", + "start", + containerName, + ) + output, err := cmd.CombinedOutput() + if err != nil { + lg. + Error(). + Err(err). + Bytes("output", output). + Msg("failed to start buildkit container") + return err + } + + return waitBuildkit(ctx) +} + +// Pull and run the buildkit daemon with a proper configuration +// If the buildkit daemon is already configured, use startBuildkit +func installBuildkit(ctx context.Context) error { + lg := log. + Ctx(ctx). + With(). + Str("version", vendoredVersion). + Logger() + lg.Debug().Msg("pulling buildkit image") // #nosec cmd := exec.CommandContext(ctx, @@ -167,6 +221,8 @@ func waitBuildkit(ctx context.Context) error { if err != nil { return err } + + // FIXME Does output "failed to wait: signal: broken pipe" defer c.Close() // Try to connect every 100ms up to 100 times (10 seconds total) @@ -207,26 +263,3 @@ func removeBuildkit(ctx context.Context) error { return nil } - -func getBuildkitVersion(ctx context.Context) (string, error) { - cmd := exec.CommandContext(ctx, - "docker", - "inspect", - "--format", - "{{.Config.Image}}", - containerName, - ) - output, err := cmd.CombinedOutput() - if err != nil { - return "", err - } - ref, err := reference.ParseNormalizedNamed(strings.TrimSpace(string(output))) - if err != nil { - return "", err - } - tag, ok := ref.(reference.Tagged) - if !ok { - return "", fmt.Errorf("failed to parse image: %s", output) - } - return tag.Tag(), nil -} From 8f1034b79f894b4b1112a4bc1903f37f22f7f5ed Mon Sep 17 00:00:00 2001 From: Lucas Perreau Date: Tue, 21 Sep 2021 08:56:57 +0200 Subject: [PATCH 2/3] style: remove spaces for consistency Signed-off-by: Lucas Perreau --- util/buildkitd/buildkit_information.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/buildkitd/buildkit_information.go b/util/buildkitd/buildkit_information.go index 55a9d2d9..1f26740e 100644 --- a/util/buildkitd/buildkit_information.go +++ b/util/buildkitd/buildkit_information.go @@ -11,7 +11,7 @@ import ( ) func getBuildkitInformation(ctx context.Context) (*BuilkitInformation, error) { - formatString := "{{.Config.Image}};{{.State.Running}};{{ if index .NetworkSettings.Networks \"host\" }}{{ \"true\" }}{{else}}{{\"false\"}}{{end}}" + formatString := "{{.Config.Image}};{{.State.Running}};{{if index .NetworkSettings.Networks \"host\"}}{{\"true\"}}{{else}}{{\"false\"}}{{end}}" cmd := exec.CommandContext(ctx, "docker", "inspect", From 72dbfe200cfa232d22135173afeb560029cdf406 Mon Sep 17 00:00:00 2001 From: Lucas Perreau Date: Tue, 21 Sep 2021 09:38:04 +0200 Subject: [PATCH 3/3] fix trailing newline Signed-off-by: Lucas Perreau --- go.mod | 3 ++- go.sum | 12 ++++++++++++ util/buildkitd/buildkitd.go | 1 - 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index d7470431..ff64d415 100644 --- a/go.mod +++ b/go.mod @@ -32,10 +32,11 @@ require ( go.opentelemetry.io/otel/exporters/jaeger v1.0.0-RC1 go.opentelemetry.io/otel/sdk v1.0.0-RC1 go.opentelemetry.io/otel/trace v1.0.0-RC1 - golang.org/x/net v0.0.0-20210331212208-0fccb6fa2b5c // indirect + golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect golang.org/x/sync v0.0.0-20210220032951-036812b2e83c golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e + golang.org/x/tools v0.1.6 // indirect google.golang.org/grpc v1.40.0 gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b ) diff --git a/go.sum b/go.sum index 2a258df3..46f9143d 100644 --- a/go.sum +++ b/go.sum @@ -1342,6 +1342,7 @@ github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs= github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA= github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg= @@ -1472,6 +1473,8 @@ golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPI golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5 h1:2M3HP5CCK1Si9FQhwnzYhXdG6DXeebvUHFpre8QvbyI= golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mobile v0.0.0-20201217150744-e6ae53a27f4f/go.mod h1:skQtrUTUwhdJvXM/2KKJzY8pDgNr9I/FOMqDVRPBUS4= @@ -1485,6 +1488,7 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.1-0.20200828183125-ce943fd02449/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1543,6 +1547,8 @@ golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLd golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k= golang.org/x/net v0.0.0-20210331212208-0fccb6fa2b5c h1:KHUzaHIpjWVlVVNh65G3hhuj3KB1HnjY6Cq5cTvRQT8= golang.org/x/net v0.0.0-20210331212208-0fccb6fa2b5c/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d h1:20cMwl2fHAzkJMEA+8J4JgqBQcQGzbisXo31MIeenXI= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/oauth2 v0.0.0-20180724155351-3d292e4d0cdc/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1669,8 +1675,10 @@ golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210502180810-71e4cd670f79/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210903071746-97244b99971b h1:3Dq0eVHn0uaQJmPO+/aYPI/fRMqdrVDbu7MQcku54gg= golang.org/x/sys v0.0.0-20210903071746-97244b99971b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= @@ -1687,6 +1695,8 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1776,6 +1786,8 @@ golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.6 h1:SIasE1FVIQOWz2GEAHFOmoW7xchJcqlucjSULTL0Ag4= +golang.org/x/tools v0.1.6/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/util/buildkitd/buildkitd.go b/util/buildkitd/buildkitd.go index 54bf245b..22ba299f 100644 --- a/util/buildkitd/buildkitd.go +++ b/util/buildkitd/buildkitd.go @@ -71,7 +71,6 @@ func checkBuildkit(ctx context.Context) error { if err := installBuildkit(ctx); err != nil { return err } - } else { lg. Debug().