mirror of
https://github.com/docker/compose.git
synced 2025-07-23 13:45:00 +02:00
Merge pull request #9729 from glours/add-platforms-build
Add platforms build
This commit is contained in:
commit
0ac0e29294
35
cmd/compose/tracing.go
Normal file
35
cmd/compose/tracing.go
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2020 Docker Compose CLI authors
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package compose
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/moby/buildkit/util/tracing/detect"
|
||||||
|
"go.opentelemetry.io/otel"
|
||||||
|
|
||||||
|
_ "github.com/moby/buildkit/util/tracing/detect/delegated" //nolint:blank-imports
|
||||||
|
_ "github.com/moby/buildkit/util/tracing/env" //nolint:blank-imports
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
detect.ServiceName = "compose"
|
||||||
|
// do not log tracing errors to stdio
|
||||||
|
otel.SetErrorHandler(skipErrors{})
|
||||||
|
}
|
||||||
|
|
||||||
|
type skipErrors struct{}
|
||||||
|
|
||||||
|
func (skipErrors) Handle(err error) {}
|
12
go.mod
12
go.mod
@ -101,7 +101,7 @@ require (
|
|||||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.29.0 // indirect
|
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.29.0 // indirect
|
||||||
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.29.0 // indirect
|
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.29.0 // indirect
|
||||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.29.0 // indirect
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.29.0 // indirect
|
||||||
go.opentelemetry.io/otel v1.4.1 // indirect
|
go.opentelemetry.io/otel v1.4.1
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.4.1 // indirect
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.4.1 // indirect
|
||||||
go.opentelemetry.io/otel/internal/metric v0.27.0 // indirect
|
go.opentelemetry.io/otel/internal/metric v0.27.0 // indirect
|
||||||
go.opentelemetry.io/otel/metric v0.27.0 // indirect
|
go.opentelemetry.io/otel/metric v0.27.0 // indirect
|
||||||
@ -122,7 +122,7 @@ require (
|
|||||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
k8s.io/apimachinery v0.24.1 // indirect; see replace for the actual version used
|
k8s.io/apimachinery v0.24.1 // indirect; see replace for the actual version used
|
||||||
k8s.io/client-go v0.24.1 // indirect; see replace for the actual version used
|
k8s.io/client-go v0.24.1 // see replace for the actual version used
|
||||||
k8s.io/klog/v2 v2.60.1 // indirect
|
k8s.io/klog/v2 v2.60.1 // indirect
|
||||||
k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9 // indirect
|
k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9 // indirect
|
||||||
sigs.k8s.io/structured-merge-diff/v4 v4.2.1 // indirect
|
sigs.k8s.io/structured-merge-diff/v4 v4.2.1 // indirect
|
||||||
@ -130,9 +130,17 @@ require (
|
|||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/cenkalti/backoff/v4 v4.1.2 // indirect
|
||||||
github.com/cyberphone/json-canonicalization v0.0.0-20210303052042-6bc126869bf4 // indirect
|
github.com/cyberphone/json-canonicalization v0.0.0-20210303052042-6bc126869bf4 // indirect
|
||||||
|
github.com/googleapis/gnostic v0.5.5 // indirect
|
||||||
|
github.com/moby/spdystream v0.2.0 // indirect
|
||||||
|
github.com/serialx/hashring v0.0.0-20190422032157-8b2912629002 // indirect
|
||||||
github.com/zmap/zcrypto v0.0.0-20220605182715-4dfcec6e9a8c // indirect
|
github.com/zmap/zcrypto v0.0.0-20220605182715-4dfcec6e9a8c // indirect
|
||||||
github.com/zmap/zlint v1.1.0 // indirect
|
github.com/zmap/zlint v1.1.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.4.1 // indirect
|
||||||
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.4.1 // indirect
|
||||||
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.4.1 // indirect
|
||||||
|
k8s.io/api v0.24.1 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
replace (
|
replace (
|
||||||
|
9
go.sum
9
go.sum
@ -246,6 +246,7 @@ github.com/campoy/unique v0.0.0-20180121183637-88950e537e7e/go.mod h1:9IOqJGCPMS
|
|||||||
github.com/cavaliercoder/go-cpio v0.0.0-20180626203310-925f9528c45e/go.mod h1:oDpT4efm8tSYHXV5tHSdRvBet/b/QzxZ+XyyPehvm3A=
|
github.com/cavaliercoder/go-cpio v0.0.0-20180626203310-925f9528c45e/go.mod h1:oDpT4efm8tSYHXV5tHSdRvBet/b/QzxZ+XyyPehvm3A=
|
||||||
github.com/cenkalti/backoff v2.1.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
|
github.com/cenkalti/backoff v2.1.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
|
||||||
github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
|
github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
|
||||||
|
github.com/cenkalti/backoff/v4 v4.1.2 h1:6Yo7N8UP2K6LWZnW94DLVSSrbobcWdVzAYOisuDPIFo=
|
||||||
github.com/cenkalti/backoff/v4 v4.1.2/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
|
github.com/cenkalti/backoff/v4 v4.1.2/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
|
||||||
github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||||
@ -498,6 +499,7 @@ github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5m
|
|||||||
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
|
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
|
||||||
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
|
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
|
||||||
github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
|
github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
|
||||||
|
github.com/elazarl/goproxy v0.0.0-20191011121108-aa519ddbe484 h1:pEtiCjIXx3RvGjlUJuCNxNOw0MNblyR9Wi+vJGBFh+8=
|
||||||
github.com/elazarl/goproxy v0.0.0-20191011121108-aa519ddbe484/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
|
github.com/elazarl/goproxy v0.0.0-20191011121108-aa519ddbe484/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
|
||||||
github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8=
|
github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8=
|
||||||
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
|
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
|
||||||
@ -761,6 +763,7 @@ github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsC
|
|||||||
github.com/googleapis/gnostic v0.2.2/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
|
github.com/googleapis/gnostic v0.2.2/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
|
||||||
github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg=
|
github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg=
|
||||||
github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU=
|
github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU=
|
||||||
|
github.com/googleapis/gnostic v0.5.5 h1:9fHAtK0uDfpveeqqo1hkEZJcFvYXAiCN3UutL8F9xHw=
|
||||||
github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA=
|
github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA=
|
||||||
github.com/gookit/color v1.2.4/go.mod h1:AhIE+pS6D4Ql0SQWbBeXPHw7gY0/sjHoA4s/n1KB7xg=
|
github.com/gookit/color v1.2.4/go.mod h1:AhIE+pS6D4Ql0SQWbBeXPHw7gY0/sjHoA4s/n1KB7xg=
|
||||||
github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
|
github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
|
||||||
@ -1022,6 +1025,7 @@ github.com/moby/buildkit v0.10.4 h1:FvC+buO8isGpUFZ1abdSLdGHZVqg9sqI4BbFL8tlzP4=
|
|||||||
github.com/moby/buildkit v0.10.4/go.mod h1:Yajz9vt1Zw5q9Pp4pdb3TCSUXJBIroIQGQ3TTs/sLug=
|
github.com/moby/buildkit v0.10.4/go.mod h1:Yajz9vt1Zw5q9Pp4pdb3TCSUXJBIroIQGQ3TTs/sLug=
|
||||||
github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg=
|
github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg=
|
||||||
github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
|
github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
|
||||||
|
github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8=
|
||||||
github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
|
github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
|
||||||
github.com/moby/sys/mount v0.1.0/go.mod h1:FVQFLDRWwyBjDTBNQXDlWnSFREqOo3OKX9aqhmeoo74=
|
github.com/moby/sys/mount v0.1.0/go.mod h1:FVQFLDRWwyBjDTBNQXDlWnSFREqOo3OKX9aqhmeoo74=
|
||||||
github.com/moby/sys/mount v0.1.1/go.mod h1:FVQFLDRWwyBjDTBNQXDlWnSFREqOo3OKX9aqhmeoo74=
|
github.com/moby/sys/mount v0.1.1/go.mod h1:FVQFLDRWwyBjDTBNQXDlWnSFREqOo3OKX9aqhmeoo74=
|
||||||
@ -1235,6 +1239,7 @@ github.com/securego/gosec v0.0.0-20200401082031-e946c8c39989/go.mod h1:i9l/TNj+y
|
|||||||
github.com/securego/gosec/v2 v2.3.0/go.mod h1:UzeVyUXbxukhLeHKV3VVqo7HdoQR9MrRfFmZYotn8ME=
|
github.com/securego/gosec/v2 v2.3.0/go.mod h1:UzeVyUXbxukhLeHKV3VVqo7HdoQR9MrRfFmZYotn8ME=
|
||||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||||
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
|
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
|
||||||
|
github.com/serialx/hashring v0.0.0-20190422032157-8b2912629002 h1:ka9QPuQg2u4LGipiZGsgkg3rJCo4iIUCy75FddM0GRQ=
|
||||||
github.com/serialx/hashring v0.0.0-20190422032157-8b2912629002/go.mod h1:/yeG0My1xr/u+HZrFQ1tOQQQQrOawfyMUH13ai5brBc=
|
github.com/serialx/hashring v0.0.0-20190422032157-8b2912629002/go.mod h1:/yeG0My1xr/u+HZrFQ1tOQQQQrOawfyMUH13ai5brBc=
|
||||||
github.com/shirou/gopsutil v0.0.0-20190901111213-e4ec7b275ada/go.mod h1:WWnYX4lzhCH5h/3YBfyVA3VbLYjlMZZAQcW9ojMexNc=
|
github.com/shirou/gopsutil v0.0.0-20190901111213-e4ec7b275ada/go.mod h1:WWnYX4lzhCH5h/3YBfyVA3VbLYjlMZZAQcW9ojMexNc=
|
||||||
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc=
|
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc=
|
||||||
@ -1465,13 +1470,16 @@ go.opentelemetry.io/otel v1.4.1/go.mod h1:StM6F/0fSwpd8dKWDCdRr7uRvEPYdW0hBSlbdT
|
|||||||
go.opentelemetry.io/otel/exporters/jaeger v1.4.1/go.mod h1:ZW7vkOu9nC1CxsD8bHNHCia5JUbwP39vxgd1q4Z5rCI=
|
go.opentelemetry.io/otel/exporters/jaeger v1.4.1/go.mod h1:ZW7vkOu9nC1CxsD8bHNHCia5JUbwP39vxgd1q4Z5rCI=
|
||||||
go.opentelemetry.io/otel/exporters/otlp v0.20.0/go.mod h1:YIieizyaN77rtLJra0buKiNBOm9XQfkPEKBeuhoMwAM=
|
go.opentelemetry.io/otel/exporters/otlp v0.20.0/go.mod h1:YIieizyaN77rtLJra0buKiNBOm9XQfkPEKBeuhoMwAM=
|
||||||
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.3.0/go.mod h1:VpP4/RMn8bv8gNo9uK7/IMY4mtWLELsS+JIP0inH0h4=
|
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.3.0/go.mod h1:VpP4/RMn8bv8gNo9uK7/IMY4mtWLELsS+JIP0inH0h4=
|
||||||
|
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.4.1 h1:imIM3vRDMyZK1ypQlQlO+brE22I9lRhJsBDXpDWjlz8=
|
||||||
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.4.1/go.mod h1:VpP4/RMn8bv8gNo9uK7/IMY4mtWLELsS+JIP0inH0h4=
|
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.4.1/go.mod h1:VpP4/RMn8bv8gNo9uK7/IMY4mtWLELsS+JIP0inH0h4=
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.3.0/go.mod h1:hO1KLR7jcKaDDKDkvI9dP/FIhpmna5lkqPUQdEjFAM8=
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.3.0/go.mod h1:hO1KLR7jcKaDDKDkvI9dP/FIhpmna5lkqPUQdEjFAM8=
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.4.1 h1:WPpPsAAs8I2rA47v5u0558meKmmwm1Dj99ZbqCV8sZ8=
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.4.1 h1:WPpPsAAs8I2rA47v5u0558meKmmwm1Dj99ZbqCV8sZ8=
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.4.1/go.mod h1:o5RW5o2pKpJLD5dNTCmjF1DorYwMeFJmb/rKr5sLaa8=
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.4.1/go.mod h1:o5RW5o2pKpJLD5dNTCmjF1DorYwMeFJmb/rKr5sLaa8=
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.3.0/go.mod h1:keUU7UfnwWTWpJ+FWnyqmogPa82nuU5VUANFq49hlMY=
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.3.0/go.mod h1:keUU7UfnwWTWpJ+FWnyqmogPa82nuU5VUANFq49hlMY=
|
||||||
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.4.1 h1:AxqDiGk8CorEXStMDZF5Hz9vo9Z7ZZ+I5m8JRl/ko40=
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.4.1/go.mod h1:c6E4V3/U+miqjs/8l950wggHGL1qzlp0Ypj9xoGrPqo=
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.4.1/go.mod h1:c6E4V3/U+miqjs/8l950wggHGL1qzlp0Ypj9xoGrPqo=
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.3.0/go.mod h1:QNX1aly8ehqqX1LEa6YniTU7VY9I6R3X/oPxhGdTceE=
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.3.0/go.mod h1:QNX1aly8ehqqX1LEa6YniTU7VY9I6R3X/oPxhGdTceE=
|
||||||
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.4.1 h1:8qOago/OqoFclMUUj/184tZyRdDZFpcejSjbk5Jrl6Y=
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.4.1/go.mod h1:VwYo0Hak6Efuy0TXsZs8o1hnV3dHDPNtDbycG0hI8+M=
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.4.1/go.mod h1:VwYo0Hak6Efuy0TXsZs8o1hnV3dHDPNtDbycG0hI8+M=
|
||||||
go.opentelemetry.io/otel/internal/metric v0.27.0 h1:9dAVGAfFiiEq5NVB9FUJ5et+btbDQAUIJehJ+ikyryk=
|
go.opentelemetry.io/otel/internal/metric v0.27.0 h1:9dAVGAfFiiEq5NVB9FUJ5et+btbDQAUIJehJ+ikyryk=
|
||||||
go.opentelemetry.io/otel/internal/metric v0.27.0/go.mod h1:n1CVxRqKqYZtqyTh9U/onvKapPGv7y/rpyOTI+LFNzw=
|
go.opentelemetry.io/otel/internal/metric v0.27.0/go.mod h1:n1CVxRqKqYZtqyTh9U/onvKapPGv7y/rpyOTI+LFNzw=
|
||||||
@ -1498,6 +1506,7 @@ go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
|||||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||||
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
|
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
|
||||||
|
go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA=
|
||||||
go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
|
go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
|
||||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
||||||
|
@ -81,6 +81,12 @@ func (s *composeService) build(ctx context.Context, project *types.Project, opti
|
|||||||
Attrs: map[string]string{"ref": image},
|
Attrs: map[string]string{"ref": image},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
if len(buildOptions.Platforms) > 1 {
|
||||||
|
buildOptions.Exports = []bclient.ExportEntry{{
|
||||||
|
Type: "image",
|
||||||
|
Attrs: map[string]string{},
|
||||||
|
}}
|
||||||
|
}
|
||||||
opts[imageName] = buildOptions
|
opts[imageName] = buildOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -162,6 +168,15 @@ func (s *composeService) getBuildOptions(project *types.Project, images map[stri
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
opt.Exports = []bclient.ExportEntry{{
|
||||||
|
Type: "docker",
|
||||||
|
Attrs: map[string]string{
|
||||||
|
"load": "true",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
if opt.Platforms, err = useDockerDefaultPlatform(project, service.Build.Platforms); err != nil {
|
||||||
|
opt.Platforms = []specs.Platform{}
|
||||||
|
}
|
||||||
opts[imageName] = opt
|
opts[imageName] = opt
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -206,7 +221,7 @@ func (s *composeService) doBuild(ctx context.Context, project *types.Project, op
|
|||||||
if buildkitEnabled, err := s.dockerCli.BuildKitEnabled(); err != nil || !buildkitEnabled {
|
if buildkitEnabled, err := s.dockerCli.BuildKitEnabled(); err != nil || !buildkitEnabled {
|
||||||
return s.doBuildClassic(ctx, project, opts)
|
return s.doBuildClassic(ctx, project, opts)
|
||||||
}
|
}
|
||||||
return s.doBuildBuildkit(ctx, project, opts, mode)
|
return s.doBuildBuildkit(ctx, opts, mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *composeService) toBuildOptions(project *types.Project, service types.ServiceConfig, imageTag string, sshKeys []types.SSHKey) (build.Options, error) {
|
func (s *composeService) toBuildOptions(project *types.Project, service types.ServiceConfig, imageTag string, sshKeys []types.SSHKey) (build.Options, error) {
|
||||||
@ -215,20 +230,9 @@ func (s *composeService) toBuildOptions(project *types.Project, service types.Se
|
|||||||
|
|
||||||
buildArgs := flatten(service.Build.Args.Resolve(envResolver(project.Environment)))
|
buildArgs := flatten(service.Build.Args.Resolve(envResolver(project.Environment)))
|
||||||
|
|
||||||
var plats []specs.Platform
|
plats, err := addPlatforms(project, service)
|
||||||
if platform, ok := project.Environment["DOCKER_DEFAULT_PLATFORM"]; ok {
|
if err != nil {
|
||||||
p, err := platforms.Parse(platform)
|
return build.Options{}, err
|
||||||
if err != nil {
|
|
||||||
return build.Options{}, err
|
|
||||||
}
|
|
||||||
plats = append(plats, p)
|
|
||||||
}
|
|
||||||
if service.Platform != "" {
|
|
||||||
p, err := platforms.Parse(service.Platform)
|
|
||||||
if err != nil {
|
|
||||||
return build.Options{}, err
|
|
||||||
}
|
|
||||||
plats = append(plats, p)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cacheFrom, err := buildflags.ParseCacheEntry(service.Build.CacheFrom)
|
cacheFrom, err := buildflags.ParseCacheEntry(service.Build.CacheFrom)
|
||||||
@ -352,3 +356,40 @@ func addSecretsConfig(project *types.Project, service types.ServiceConfig) (sess
|
|||||||
}
|
}
|
||||||
return secretsprovider.NewSecretProvider(store), nil
|
return secretsprovider.NewSecretProvider(store), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func addPlatforms(project *types.Project, service types.ServiceConfig) ([]specs.Platform, error) {
|
||||||
|
plats, err := useDockerDefaultPlatform(project, service.Build.Platforms)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if service.Platform != "" && !utils.StringContains(service.Build.Platforms, service.Platform) {
|
||||||
|
return nil, fmt.Errorf("service.platform should be part of the service.build.platforms: %q", service.Platform)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, buildPlatform := range service.Build.Platforms {
|
||||||
|
p, err := platforms.Parse(buildPlatform)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if !utils.Contains(plats, p) {
|
||||||
|
plats = append(plats, p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return plats, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func useDockerDefaultPlatform(project *types.Project, platformList types.StringList) ([]specs.Platform, error) {
|
||||||
|
var plats []specs.Platform
|
||||||
|
if platform, ok := project.Environment["DOCKER_DEFAULT_PLATFORM"]; ok {
|
||||||
|
if !utils.StringContains(platformList, platform) {
|
||||||
|
return nil, fmt.Errorf("the DOCKER_DEFAULT_PLATFORM value should be part of the service.build.platforms: %q", platform)
|
||||||
|
}
|
||||||
|
p, err := platforms.Parse(platform)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
plats = append(plats, p)
|
||||||
|
}
|
||||||
|
return plats, nil
|
||||||
|
}
|
||||||
|
@ -18,27 +18,36 @@ package compose
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
ctxkube "github.com/docker/buildx/driver/kubernetes/context"
|
||||||
|
"github.com/docker/buildx/store"
|
||||||
|
"github.com/docker/buildx/store/storeutil"
|
||||||
|
"github.com/docker/cli/cli/command"
|
||||||
|
"github.com/docker/cli/cli/context/docker"
|
||||||
|
ctxstore "github.com/docker/cli/cli/context/store"
|
||||||
|
dockerclient "github.com/docker/docker/client"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
|
"k8s.io/client-go/tools/clientcmd"
|
||||||
|
|
||||||
"github.com/compose-spec/compose-go/types"
|
|
||||||
"github.com/docker/buildx/build"
|
"github.com/docker/buildx/build"
|
||||||
"github.com/docker/buildx/driver"
|
"github.com/docker/buildx/driver"
|
||||||
|
_ "github.com/docker/buildx/driver/docker" //nolint:blank-imports
|
||||||
|
_ "github.com/docker/buildx/driver/docker-container" //nolint:blank-imports
|
||||||
|
_ "github.com/docker/buildx/driver/kubernetes" //nolint:blank-imports
|
||||||
xprogress "github.com/docker/buildx/util/progress"
|
xprogress "github.com/docker/buildx/util/progress"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *composeService) doBuildBuildkit(ctx context.Context, project *types.Project, opts map[string]build.Options, mode string) (map[string]string, error) {
|
func (s *composeService) doBuildBuildkit(ctx context.Context, opts map[string]build.Options, mode string) (map[string]string, error) {
|
||||||
const drivername = "default"
|
dis, err := s.getDrivers(ctx)
|
||||||
d, err := driver.GetDriver(ctx, drivername, nil, s.apiClient(), s.configFile(), nil, nil, nil, nil, nil, project.WorkingDir)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
driverInfo := []build.DriverInfo{
|
|
||||||
{
|
|
||||||
Name: drivername,
|
|
||||||
Driver: d,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// Progress needs its own context that lives longer than the
|
// Progress needs its own context that lives longer than the
|
||||||
// build one otherwise it won't read all the messages from
|
// build one otherwise it won't read all the messages from
|
||||||
@ -47,8 +56,7 @@ func (s *composeService) doBuildBuildkit(ctx context.Context, project *types.Pro
|
|||||||
defer cancel()
|
defer cancel()
|
||||||
w := xprogress.NewPrinter(progressCtx, s.stdout(), os.Stdout, mode)
|
w := xprogress.NewPrinter(progressCtx, s.stdout(), os.Stdout, mode)
|
||||||
|
|
||||||
// We rely on buildx "docker" builder integrated in docker engine, so don't need a DockerAPI here
|
response, err := build.Build(ctx, dis, opts, &internalAPI{dockerCli: s.dockerCli}, filepath.Dir(s.configFile().Filename), w)
|
||||||
response, err := build.Build(ctx, driverInfo, opts, nil, filepath.Dir(s.configFile().Filename), w)
|
|
||||||
errW := w.Wait()
|
errW := w.Wait()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
err = errW
|
err = errW
|
||||||
@ -71,3 +79,187 @@ func (s *composeService) doBuildBuildkit(ctx context.Context, project *types.Pro
|
|||||||
|
|
||||||
return imagesBuilt, err
|
return imagesBuilt, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *composeService) getDrivers(ctx context.Context) ([]build.DriverInfo, error) { //nolint:gocyclo
|
||||||
|
txn, release, err := storeutil.GetStore(s.dockerCli)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer release()
|
||||||
|
|
||||||
|
ng, err := storeutil.GetCurrentInstance(txn, s.dockerCli)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
dis := make([]build.DriverInfo, len(ng.Nodes))
|
||||||
|
var f driver.Factory
|
||||||
|
if ng.Driver != "" {
|
||||||
|
factories := driver.GetFactories()
|
||||||
|
for _, fac := range factories {
|
||||||
|
if fac.Name() == ng.Driver {
|
||||||
|
f = fac
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if f == nil {
|
||||||
|
if f = driver.GetFactory(ng.Driver, true); f == nil {
|
||||||
|
return nil, fmt.Errorf("failed to find buildx driver %q", ng.Driver)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ep := ng.Nodes[0].Endpoint
|
||||||
|
dockerapi, err := clientForEndpoint(s.dockerCli, ep)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
f, err = driver.GetDefaultFactory(ctx, dockerapi, false)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ng.Driver = f.Name()
|
||||||
|
}
|
||||||
|
|
||||||
|
imageopt, err := storeutil.GetImageConfig(s.dockerCli, ng)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
eg, _ := errgroup.WithContext(ctx)
|
||||||
|
for i, n := range ng.Nodes {
|
||||||
|
func(i int, n store.Node) {
|
||||||
|
eg.Go(func() error {
|
||||||
|
di := build.DriverInfo{
|
||||||
|
Name: n.Name,
|
||||||
|
Platform: n.Platforms,
|
||||||
|
ProxyConfig: storeutil.GetProxyConfig(s.dockerCli),
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
dis[i] = di
|
||||||
|
}()
|
||||||
|
|
||||||
|
dockerapi, err := clientForEndpoint(s.dockerCli, n.Endpoint)
|
||||||
|
if err != nil {
|
||||||
|
di.Err = err
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// TODO: replace the following line with dockerclient.WithAPIVersionNegotiation option in clientForEndpoint
|
||||||
|
dockerapi.NegotiateAPIVersion(ctx)
|
||||||
|
|
||||||
|
contextStore := s.dockerCli.ContextStore()
|
||||||
|
|
||||||
|
var kcc driver.KubeClientConfig
|
||||||
|
kcc, err = configFromContext(n.Endpoint, contextStore)
|
||||||
|
if err != nil {
|
||||||
|
// err is returned if n.Endpoint is non-context name like "unix:///var/run/docker.sock".
|
||||||
|
// try again with name="default".
|
||||||
|
// FIXME: n should retain real context name.
|
||||||
|
kcc, err = configFromContext("default", contextStore)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tryToUseKubeConfigInCluster := false
|
||||||
|
if kcc == nil {
|
||||||
|
tryToUseKubeConfigInCluster = true
|
||||||
|
} else {
|
||||||
|
if _, err := kcc.ClientConfig(); err != nil {
|
||||||
|
tryToUseKubeConfigInCluster = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if tryToUseKubeConfigInCluster {
|
||||||
|
kccInCluster := driver.KubeClientConfigInCluster{}
|
||||||
|
if _, err := kccInCluster.ClientConfig(); err == nil {
|
||||||
|
logrus.Debug("using kube config in cluster")
|
||||||
|
kcc = kccInCluster
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
d, err := driver.GetDriver(ctx, "buildx_buildkit_"+n.Name, f, dockerapi, imageopt.Auth, kcc, n.Flags, n.Files, n.DriverOpts, n.Platforms, "")
|
||||||
|
if err != nil {
|
||||||
|
di.Err = err
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
di.Driver = d
|
||||||
|
di.ImageOpt = imageopt
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}(i, n)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := eg.Wait(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return dis, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func clientForEndpoint(dockerCli command.Cli, name string) (dockerclient.APIClient, error) {
|
||||||
|
list, err := dockerCli.ContextStore().List()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for _, l := range list {
|
||||||
|
if l.Name != name {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
dep, ok := l.Endpoints["docker"]
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("context %q does not have a Docker endpoint", name)
|
||||||
|
}
|
||||||
|
epm, ok := dep.(docker.EndpointMeta)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("endpoint %q is not of type EndpointMeta, %T", dep, dep)
|
||||||
|
}
|
||||||
|
ep, err := docker.WithTLSData(dockerCli.ContextStore(), name, epm)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
clientOpts, err := ep.ClientOpts()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return dockerclient.NewClientWithOpts(clientOpts...)
|
||||||
|
}
|
||||||
|
|
||||||
|
ep := docker.Endpoint{
|
||||||
|
EndpointMeta: docker.EndpointMeta{
|
||||||
|
Host: name,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
clientOpts, err := ep.ClientOpts()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return dockerclient.NewClientWithOpts(clientOpts...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func configFromContext(endpointName string, s ctxstore.Reader) (clientcmd.ClientConfig, error) {
|
||||||
|
if strings.HasPrefix(endpointName, "kubernetes://") {
|
||||||
|
u, _ := url.Parse(endpointName)
|
||||||
|
if kubeconfig := u.Query().Get("kubeconfig"); kubeconfig != "" {
|
||||||
|
_ = os.Setenv(clientcmd.RecommendedConfigPathEnvVar, kubeconfig)
|
||||||
|
}
|
||||||
|
rules := clientcmd.NewDefaultClientConfigLoadingRules()
|
||||||
|
apiConfig, err := rules.Load()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return clientcmd.NewDefaultClientConfig(*apiConfig, &clientcmd.ConfigOverrides{}), nil
|
||||||
|
}
|
||||||
|
return ctxkube.ConfigFromContext(endpointName, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
type internalAPI struct {
|
||||||
|
dockerCli command.Cli
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *internalAPI) DockerAPI(name string) (dockerclient.APIClient, error) {
|
||||||
|
if name == "" {
|
||||||
|
name = a.dockerCli.CurrentContext()
|
||||||
|
}
|
||||||
|
return clientForEndpoint(a.dockerCli, name)
|
||||||
|
}
|
||||||
|
@ -89,6 +89,10 @@ func (s *composeService) doBuildClassicSimpleImage(ctx context.Context, options
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(options.Platforms) > 1 {
|
||||||
|
return "", errors.Errorf("this builder doesn't support multi-arch build, set DOCKER_BUILDKIT=1 to use multi-arch builder")
|
||||||
|
}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case isLocalDir(specifiedContext):
|
case isLocalDir(specifiedContext):
|
||||||
contextDir, relDockerfile, err = build.GetContextFromLocalDir(specifiedContext, dockerfileName)
|
contextDir, relDockerfile, err = build.GetContextFromLocalDir(specifiedContext, dockerfileName)
|
||||||
|
@ -243,3 +243,105 @@ func TestBuildImageDependencies(t *testing.T) {
|
|||||||
t.Skip("See https://github.com/docker/compose/issues/9232")
|
t.Skip("See https://github.com/docker/compose/issues/9232")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestBuildPlatformsWithCorrectBuildxConfig(t *testing.T) {
|
||||||
|
c := NewParallelCLI(t)
|
||||||
|
|
||||||
|
// declare builder
|
||||||
|
result := c.RunDockerCmd(t, "buildx", "create", "--name", "build-platform", "--use", "--bootstrap")
|
||||||
|
assert.NilError(t, result.Error)
|
||||||
|
|
||||||
|
t.Cleanup(func() {
|
||||||
|
c.RunDockerComposeCmd(t, "--project-directory", "fixtures/build-test/platforms", "down")
|
||||||
|
_ = c.RunDockerCmd(t, "buildx", "rm", "-f", "build-platform")
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("platform not supported by builder", func(t *testing.T) {
|
||||||
|
res := c.RunDockerComposeCmdNoCheck(t, "--project-directory", "fixtures/build-test/platforms",
|
||||||
|
"-f", "fixtures/build-test/platforms/compose-unsupported-platform.yml", "build")
|
||||||
|
res.Assert(t, icmd.Expected{
|
||||||
|
ExitCode: 17,
|
||||||
|
Err: "failed to solve: alpine: no match for platform in",
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("multi-arch build ok", func(t *testing.T) {
|
||||||
|
res := c.RunDockerComposeCmdNoCheck(t, "--project-directory", "fixtures/build-test/platforms", "build")
|
||||||
|
assert.NilError(t, res.Error, res.Stderr())
|
||||||
|
res.Assert(t, icmd.Expected{Out: "I am building for linux/arm64"})
|
||||||
|
res.Assert(t, icmd.Expected{Out: "I am building for linux/amd64"})
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("multi-arch multi service builds ok", func(t *testing.T) {
|
||||||
|
res := c.RunDockerComposeCmdNoCheck(t, "--project-directory", "fixtures/build-test/platforms",
|
||||||
|
"-f", "fixtures/build-test/platforms/compose-multiple-platform-builds.yaml", "build")
|
||||||
|
assert.NilError(t, res.Error, res.Stderr())
|
||||||
|
res.Assert(t, icmd.Expected{Out: "I'm Service A and I am building for linux/arm64"})
|
||||||
|
res.Assert(t, icmd.Expected{Out: "I'm Service A and I am building for linux/amd64"})
|
||||||
|
res.Assert(t, icmd.Expected{Out: "I'm Service B and I am building for linux/arm64"})
|
||||||
|
res.Assert(t, icmd.Expected{Out: "I'm Service B and I am building for linux/amd64"})
|
||||||
|
res.Assert(t, icmd.Expected{Out: "I'm Service C and I am building for linux/arm64"})
|
||||||
|
res.Assert(t, icmd.Expected{Out: "I'm Service C and I am building for linux/amd64"})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("multi-arch up --build", func(t *testing.T) {
|
||||||
|
res := c.RunDockerComposeCmdNoCheck(t, "--project-directory", "fixtures/build-test/platforms", "up", "--build")
|
||||||
|
assert.NilError(t, res.Error, res.Stderr())
|
||||||
|
res.Assert(t, icmd.Expected{Out: "platforms-platforms-1 exited with code 0"})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("use DOCKER_DEFAULT_PLATFORM value when up --build", func(t *testing.T) {
|
||||||
|
cmd := c.NewDockerComposeCmd(t, "--project-directory", "fixtures/build-test/platforms", "up", "--build")
|
||||||
|
res := icmd.RunCmd(cmd, func(cmd *icmd.Cmd) {
|
||||||
|
cmd.Env = append(cmd.Env, "DOCKER_DEFAULT_PLATFORM=linux/amd64")
|
||||||
|
})
|
||||||
|
assert.NilError(t, res.Error, res.Stderr())
|
||||||
|
res.Assert(t, icmd.Expected{Out: "I am building for linux/amd64"})
|
||||||
|
assert.Assert(t, !strings.Contains(res.Stdout(), "I am building for linux/arm64"))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBuildPlatformsStandardErrors(t *testing.T) {
|
||||||
|
c := NewParallelCLI(t)
|
||||||
|
|
||||||
|
t.Run("no platform support with Classic Builder", func(t *testing.T) {
|
||||||
|
cmd := c.NewDockerComposeCmd(t, "--project-directory", "fixtures/build-test/platforms", "build")
|
||||||
|
|
||||||
|
res := icmd.RunCmd(cmd, func(cmd *icmd.Cmd) {
|
||||||
|
cmd.Env = append(cmd.Env, "DOCKER_BUILDKIT=0")
|
||||||
|
})
|
||||||
|
res.Assert(t, icmd.Expected{
|
||||||
|
ExitCode: 1,
|
||||||
|
Err: "this builder doesn't support multi-arch build, set DOCKER_BUILDKIT=1 to use multi-arch builder",
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("builder does not support multi-arch", func(t *testing.T) {
|
||||||
|
res := c.RunDockerComposeCmdNoCheck(t, "--project-directory", "fixtures/build-test/platforms", "build")
|
||||||
|
res.Assert(t, icmd.Expected{
|
||||||
|
ExitCode: 17,
|
||||||
|
Err: `multiple platforms feature is currently not supported for docker driver. Please switch to a different driver (eg. "docker buildx create --use")`,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("service platform not defined in platforms build section", func(t *testing.T) {
|
||||||
|
res := c.RunDockerComposeCmdNoCheck(t, "--project-directory", "fixtures/build-test/platforms",
|
||||||
|
"-f", "fixtures/build-test/platforms/compose-service-platform-not-in-build-platforms.yaml", "build")
|
||||||
|
res.Assert(t, icmd.Expected{
|
||||||
|
ExitCode: 1,
|
||||||
|
Err: `service.platform should be part of the service.build.platforms: "linux/riscv64"`,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("DOCKER_DEFAULT_PLATFORM value not defined in platforms build section", func(t *testing.T) {
|
||||||
|
cmd := c.NewDockerComposeCmd(t, "--project-directory", "fixtures/build-test/platforms", "build")
|
||||||
|
res := icmd.RunCmd(cmd, func(cmd *icmd.Cmd) {
|
||||||
|
cmd.Env = append(cmd.Env, "DOCKER_DEFAULT_PLATFORM=windows/amd64")
|
||||||
|
})
|
||||||
|
res.Assert(t, icmd.Expected{
|
||||||
|
ExitCode: 1,
|
||||||
|
Err: `DOCKER_DEFAULT_PLATFORM value should be part of the service.build.platforms: "windows/amd64"`,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
22
pkg/e2e/fixtures/build-test/platforms/Dockerfile
Normal file
22
pkg/e2e/fixtures/build-test/platforms/Dockerfile
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# Copyright 2020 Docker Compose CLI authors
|
||||||
|
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
FROM --platform=$BUILDPLATFORM golang:alpine AS build
|
||||||
|
|
||||||
|
ARG TARGETPLATFORM
|
||||||
|
ARG BUILDPLATFORM
|
||||||
|
RUN echo "I am building for $TARGETPLATFORM, running on $BUILDPLATFORM" > /log
|
||||||
|
|
||||||
|
FROM alpine
|
||||||
|
COPY --from=build /log /log
|
@ -0,0 +1,23 @@
|
|||||||
|
services:
|
||||||
|
serviceA:
|
||||||
|
image: build-test-platform-a:test
|
||||||
|
build:
|
||||||
|
context: ./contextServiceA
|
||||||
|
platforms:
|
||||||
|
- linux/amd64
|
||||||
|
- linux/arm64
|
||||||
|
serviceB:
|
||||||
|
image: build-test-platform-b:test
|
||||||
|
build:
|
||||||
|
context: ./contextServiceB
|
||||||
|
platforms:
|
||||||
|
- linux/amd64
|
||||||
|
- linux/arm64
|
||||||
|
serviceC:
|
||||||
|
image: build-test-platform-c:test
|
||||||
|
build:
|
||||||
|
context: ./contextServiceC
|
||||||
|
platforms:
|
||||||
|
- linux/amd64
|
||||||
|
- linux/arm64
|
||||||
|
|
@ -0,0 +1,9 @@
|
|||||||
|
services:
|
||||||
|
platforms:
|
||||||
|
image: build-test-platform:test
|
||||||
|
platform: linux/riscv64
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
platforms:
|
||||||
|
- linux/amd64
|
||||||
|
- linux/arm64
|
@ -0,0 +1,8 @@
|
|||||||
|
services:
|
||||||
|
platforms:
|
||||||
|
image: build-test-platform:test
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
platforms:
|
||||||
|
- unsupported/unsupported
|
||||||
|
- linux/amd64
|
9
pkg/e2e/fixtures/build-test/platforms/compose.yaml
Normal file
9
pkg/e2e/fixtures/build-test/platforms/compose.yaml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
services:
|
||||||
|
platforms:
|
||||||
|
image: build-test-platform:test
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
platforms:
|
||||||
|
- linux/amd64
|
||||||
|
- linux/arm64
|
||||||
|
|
@ -0,0 +1,22 @@
|
|||||||
|
# Copyright 2020 Docker Compose CLI authors
|
||||||
|
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
FROM --platform=$BUILDPLATFORM golang:alpine AS build
|
||||||
|
|
||||||
|
ARG TARGETPLATFORM
|
||||||
|
ARG BUILDPLATFORM
|
||||||
|
RUN echo "I'm Service A and I am building for $TARGETPLATFORM, running on $BUILDPLATFORM" > /log
|
||||||
|
|
||||||
|
FROM alpine
|
||||||
|
COPY --from=build /log /log
|
@ -0,0 +1,22 @@
|
|||||||
|
# Copyright 2020 Docker Compose CLI authors
|
||||||
|
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
FROM --platform=$BUILDPLATFORM golang:alpine AS build
|
||||||
|
|
||||||
|
ARG TARGETPLATFORM
|
||||||
|
ARG BUILDPLATFORM
|
||||||
|
RUN echo "I'm Service B and I am building for $TARGETPLATFORM, running on $BUILDPLATFORM" > /log
|
||||||
|
|
||||||
|
FROM alpine
|
||||||
|
COPY --from=build /log /log
|
@ -0,0 +1,22 @@
|
|||||||
|
# Copyright 2020 Docker Compose CLI authors
|
||||||
|
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
FROM --platform=$BUILDPLATFORM golang:alpine AS build
|
||||||
|
|
||||||
|
ARG TARGETPLATFORM
|
||||||
|
ARG BUILDPLATFORM
|
||||||
|
RUN echo "I'm Service C and I am building for $TARGETPLATFORM, running on $BUILDPLATFORM" > /log
|
||||||
|
|
||||||
|
FROM alpine
|
||||||
|
COPY --from=build /log /log
|
30
pkg/utils/slices.go
Normal file
30
pkg/utils/slices.go
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2020 Docker Compose CLI authors
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package utils
|
||||||
|
|
||||||
|
import "reflect"
|
||||||
|
|
||||||
|
// Contains helps to detect if a non-comparable struct is part of an array
|
||||||
|
// only use this method if you can't rely on existing golang Contains function of slices (https://pkg.go.dev/golang.org/x/exp/slices#Contains)
|
||||||
|
func Contains[T any](origin []T, element T) bool {
|
||||||
|
for _, v := range origin {
|
||||||
|
if reflect.DeepEqual(v, element) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
95
pkg/utils/slices_test.go
Normal file
95
pkg/utils/slices_test.go
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2020 Docker Compose CLI authors
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
specs "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestContains(t *testing.T) {
|
||||||
|
source := []specs.Platform{
|
||||||
|
{
|
||||||
|
Architecture: "linux/amd64",
|
||||||
|
OS: "darwin",
|
||||||
|
OSVersion: "",
|
||||||
|
OSFeatures: nil,
|
||||||
|
Variant: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Architecture: "linux/arm64",
|
||||||
|
OS: "linux",
|
||||||
|
OSVersion: "12",
|
||||||
|
OSFeatures: nil,
|
||||||
|
Variant: "v8",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Architecture: "",
|
||||||
|
OS: "",
|
||||||
|
OSVersion: "",
|
||||||
|
OSFeatures: nil,
|
||||||
|
Variant: "",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
type args struct {
|
||||||
|
origin []specs.Platform
|
||||||
|
element specs.Platform
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
want bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "element found",
|
||||||
|
args: args{
|
||||||
|
origin: source,
|
||||||
|
element: specs.Platform{
|
||||||
|
Architecture: "linux/arm64",
|
||||||
|
OS: "linux",
|
||||||
|
OSVersion: "12",
|
||||||
|
OSFeatures: nil,
|
||||||
|
Variant: "v8",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "element not found",
|
||||||
|
args: args{
|
||||||
|
origin: source,
|
||||||
|
element: specs.Platform{
|
||||||
|
Architecture: "linux/arm64",
|
||||||
|
OS: "darwin",
|
||||||
|
OSVersion: "12",
|
||||||
|
OSFeatures: nil,
|
||||||
|
Variant: "v8",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
if got := Contains(tt.args.origin, tt.args.element); got != tt.want {
|
||||||
|
t.Errorf("Contains() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user