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/buildkit_information.go b/util/buildkitd/buildkit_information.go new file mode 100644 index 00000000..1f26740e --- /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..22ba299f 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,72 @@ 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 +126,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 +134,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 +220,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 +262,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 -}