From d1458a65879f3707e4708c4a19f1c2570d3620f1 Mon Sep 17 00:00:00 2001 From: Tonis Tiigi Date: Tue, 25 Feb 2020 15:23:34 -0800 Subject: [PATCH] update supported platforms without restart Signed-off-by: Tonis Tiigi --- cmd/buildkitd/main.go | 6 +-- control/control.go | 2 +- solver/llbsolver/solver.go | 2 +- solver/llbsolver/vertex.go | 7 ++- util/binfmt_misc/detect.go | 89 +++++++++++++++++++++++++------------- worker/base/worker.go | 16 ++++++- worker/worker.go | 3 +- worker/workercontroller.go | 2 +- 8 files changed, 89 insertions(+), 38 deletions(-) diff --git a/cmd/buildkitd/main.go b/cmd/buildkitd/main.go index 7c53484c..f9185ef3 100644 --- a/cmd/buildkitd/main.go +++ b/cmd/buildkitd/main.go @@ -373,10 +373,10 @@ func setDefaultConfig(cfg *config.Config) { } if cfg.Workers.OCI.Platforms == nil { - cfg.Workers.OCI.Platforms = binfmt_misc.SupportedPlatforms() + cfg.Workers.OCI.Platforms = binfmt_misc.SupportedPlatforms(false) } if cfg.Workers.Containerd.Platforms == nil { - cfg.Workers.Containerd.Platforms = binfmt_misc.SupportedPlatforms() + cfg.Workers.Containerd.Platforms = binfmt_misc.SupportedPlatforms(false) } cfg.Workers.OCI.NetworkConfig = setDefaultNetworkConfig(cfg.Workers.OCI.NetworkConfig) @@ -639,7 +639,7 @@ func newWorkerController(c *cli.Context, wiOpt workerInitializerOpt) (*worker.Co return nil, err } for _, w := range ws { - p := formatPlatforms(w.Platforms()) + p := formatPlatforms(w.Platforms(false)) logrus.Infof("found worker %q, labels=%v, platforms=%v", w.ID(), w.Labels(), p) binfmt_misc.WarnIfUnsupported(p) if err = wc.Add(w); err != nil { diff --git a/control/control.go b/control/control.go index 83833539..ff46d237 100644 --- a/control/control.go +++ b/control/control.go @@ -373,7 +373,7 @@ func (c *Controller) ListWorkers(ctx context.Context, r *controlapi.ListWorkersR resp.Record = append(resp.Record, &apitypes.WorkerRecord{ ID: w.ID(), Labels: w.Labels(), - Platforms: pb.PlatformsFromSpec(w.Platforms()), + Platforms: pb.PlatformsFromSpec(w.Platforms(true)), GCPolicy: toPBGCPolicy(w.GCPolicy()), }) } diff --git a/solver/llbsolver/solver.go b/solver/llbsolver/solver.go index 94e950a3..640a9738 100644 --- a/solver/llbsolver/solver.go +++ b/solver/llbsolver/solver.go @@ -66,7 +66,7 @@ func New(wc *worker.Controller, f map[string]frontend.Frontend, cache solver.Cac if err != nil { return nil, err } - s.platforms = w.Platforms() + s.platforms = w.Platforms(false) s.solver = solver.NewSolver(solver.SolverOpt{ ResolveOpFunc: s.resolver(), diff --git a/solver/llbsolver/vertex.go b/solver/llbsolver/vertex.go index 7de9fd0f..2dbded12 100644 --- a/solver/llbsolver/vertex.go +++ b/solver/llbsolver/vertex.go @@ -8,6 +8,7 @@ import ( "github.com/moby/buildkit/solver" "github.com/moby/buildkit/solver/pb" "github.com/moby/buildkit/source" + "github.com/moby/buildkit/util/binfmt_misc" "github.com/moby/buildkit/util/entitlements" digest "github.com/opencontainers/go-digest" specs "github.com/opencontainers/image-spec/specs-go/v1" @@ -104,7 +105,11 @@ func RuntimePlatforms(p []specs.Platform) LoadOpt { } } if !found { - return errors.Errorf("runtime execution on platform %s not supported", platforms.Format(specs.Platform{OS: op.Platform.OS, Architecture: op.Platform.Architecture, Variant: op.Platform.Variant})) + if !binfmt_misc.Check(normalizedPlatform) { + return errors.Errorf("runtime execution on platform %s not supported", platforms.Format(specs.Platform{OS: op.Platform.OS, Architecture: op.Platform.Architecture, Variant: op.Platform.Variant})) + } else { + pp = append(pp, normalizedPlatform) + } } } return nil diff --git a/util/binfmt_misc/detect.go b/util/binfmt_misc/detect.go index 1a250a5d..73eb405c 100644 --- a/util/binfmt_misc/detect.go +++ b/util/binfmt_misc/detect.go @@ -5,43 +5,74 @@ import ( "sync" "github.com/containerd/containerd/platforms" + specs "github.com/opencontainers/image-spec/specs-go/v1" "github.com/sirupsen/logrus" ) -var once sync.Once +var mu sync.Mutex var arr []string -func SupportedPlatforms() []string { - once.Do(func() { - def := defaultPlatform() - arr = append(arr, def) - if p := "linux/amd64"; def != p && amd64Supported() == nil { - arr = append(arr, p) - } - if p := "linux/arm64"; def != p && arm64Supported() == nil { - arr = append(arr, p) - } - if p := "linux/riscv64"; def != p && riscv64Supported() == nil { - arr = append(arr, p) - } - if p := "linux/ppc64le"; def != p && ppc64leSupported() == nil { - arr = append(arr, p) - } - if p := "linux/s390x"; def != p && s390xSupported() == nil { - arr = append(arr, p) - } - if p := "linux/386"; def != p && i386Supported() == nil { - arr = append(arr, p) - } - if !strings.HasPrefix(def, "linux/arm/") && armSupported() == nil { - arr = append(arr, "linux/arm/v7", "linux/arm/v6") - } else if def == "linux/arm/v7" { - arr = append(arr, "linux/arm/v6") - } - }) +func SupportedPlatforms(noCache bool) []string { + mu.Lock() + defer mu.Unlock() + if !noCache && arr != nil { + return arr + } + def := defaultPlatform() + arr = append([]string{}, def) + if p := "linux/amd64"; def != p && amd64Supported() == nil { + arr = append(arr, p) + } + if p := "linux/arm64"; def != p && arm64Supported() == nil { + arr = append(arr, p) + } + if p := "linux/riscv64"; def != p && riscv64Supported() == nil { + arr = append(arr, p) + } + if p := "linux/ppc64le"; def != p && ppc64leSupported() == nil { + arr = append(arr, p) + } + if p := "linux/s390x"; def != p && s390xSupported() == nil { + arr = append(arr, p) + } + if p := "linux/386"; def != p && i386Supported() == nil { + arr = append(arr, p) + } + if !strings.HasPrefix(def, "linux/arm/") && armSupported() == nil { + arr = append(arr, "linux/arm/v7", "linux/arm/v6") + } else if def == "linux/arm/v7" { + arr = append(arr, "linux/arm/v6") + } return arr } +func Check(pp specs.Platform) bool { + p := platforms.Format(pp) + if p == "linux/amd64" && amd64Supported() == nil { + return true + } + if p == "linux/arm64" && arm64Supported() == nil { + return true + } + if p == "linux/riscv64" && riscv64Supported() == nil { + return true + } + if p == "linux/ppc64le" && ppc64leSupported() == nil { + return true + } + if p == "linux/s390x" && s390xSupported() == nil { + return true + } + if p == "linux/386" && i386Supported() == nil { + return true + } + if !strings.HasPrefix(p, "linux/arm/") && armSupported() == nil { + return true + } + + return false +} + //WarnIfUnsupported validates the platforms and show warning message if there is, //the end user could fix the issue based on those warning, and thus no need to drop //the platform from the candidates. diff --git a/worker/base/worker.go b/worker/base/worker.go index f0803d60..b4c05b48 100644 --- a/worker/base/worker.go +++ b/worker/base/worker.go @@ -15,6 +15,7 @@ import ( "github.com/containerd/containerd/gc" "github.com/containerd/containerd/images" "github.com/containerd/containerd/leases" + "github.com/containerd/containerd/platforms" "github.com/containerd/containerd/remotes/docker" "github.com/docker/docker/pkg/idtools" "github.com/moby/buildkit/cache" @@ -41,6 +42,7 @@ import ( "github.com/moby/buildkit/source/git" "github.com/moby/buildkit/source/http" "github.com/moby/buildkit/source/local" + "github.com/moby/buildkit/util/binfmt_misc" "github.com/moby/buildkit/util/contentutil" "github.com/moby/buildkit/util/leaseutil" "github.com/moby/buildkit/util/progress" @@ -200,7 +202,19 @@ func (w *Worker) Labels() map[string]string { return w.WorkerOpt.Labels } -func (w *Worker) Platforms() []specs.Platform { +func (w *Worker) Platforms(noCache bool) []specs.Platform { + if noCache { + pm := make(map[string]struct{}, len(w.WorkerOpt.Platforms)) + for _, p := range w.WorkerOpt.Platforms { + pm[platforms.Format(p)] = struct{}{} + } + for _, p := range binfmt_misc.SupportedPlatforms(noCache) { + if _, ok := pm[p]; !ok { + pp, _ := platforms.Parse(p) + w.WorkerOpt.Platforms = append(w.WorkerOpt.Platforms, pp) + } + } + } return w.WorkerOpt.Platforms } diff --git a/worker/worker.go b/worker/worker.go index 50196530..6505e307 100644 --- a/worker/worker.go +++ b/worker/worker.go @@ -21,7 +21,8 @@ type Worker interface { // ID needs to be unique in the cluster ID() string Labels() map[string]string - Platforms() []specs.Platform + Platforms(noCache bool) []specs.Platform + GCPolicy() []client.PruneInfo LoadRef(id string, hidden bool) (cache.ImmutableRef, error) // ResolveOp resolves Vertex.Sys() to Op implementation. diff --git a/worker/workercontroller.go b/worker/workercontroller.go index b07db8f5..5389f58d 100644 --- a/worker/workercontroller.go +++ b/worker/workercontroller.go @@ -70,7 +70,7 @@ func (c *Controller) WorkerInfos() []client.WorkerInfo { out = append(out, client.WorkerInfo{ ID: w.ID(), Labels: w.Labels(), - Platforms: w.Platforms(), + Platforms: w.Platforms(true), }) } return out