diff --git a/go.mod b/go.mod index 6de398b0c..c6d5d2c6d 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/Microsoft/go-winio v0.6.2 github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d github.com/buger/goterm v1.0.4 - github.com/compose-spec/compose-go/v2 v2.4.9-0.20250302154753-e508c724a35f + github.com/compose-spec/compose-go/v2 v2.4.9-0.20250306081139-60e14f61e9ef github.com/containerd/containerd/v2 v2.0.2 github.com/containerd/platforms v1.0.0-rc.1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc @@ -25,6 +25,7 @@ require ( github.com/hashicorp/go-version v1.7.0 github.com/jonboulle/clockwork v0.5.0 github.com/mattn/go-shellwords v1.0.12 + github.com/mikefarah/yq/v4 v4.45.1 github.com/mitchellh/go-ps v1.0.0 github.com/mitchellh/mapstructure v1.5.0 github.com/moby/buildkit v0.20.0 @@ -55,6 +56,7 @@ require ( golang.org/x/sync v0.12.0 golang.org/x/sys v0.31.0 google.golang.org/grpc v1.71.0 + gopkg.in/op/go-logging.v1 v1.0.0-20160211212156-b2cb9fa56473 gopkg.in/yaml.v3 v3.0.1 gotest.tools/v3 v3.5.2 tags.cncf.io/container-device-interface v0.8.1 @@ -65,6 +67,8 @@ require ( github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 // indirect github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect github.com/Masterminds/semver/v3 v3.2.1 // indirect + github.com/a8m/envsubst v1.4.2 // indirect + github.com/alecthomas/participle/v2 v2.1.1 // indirect github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect github.com/aws/aws-sdk-go-v2 v1.30.3 // indirect github.com/aws/aws-sdk-go-v2/config v1.27.27 // indirect @@ -91,11 +95,14 @@ require ( github.com/containerd/ttrpc v1.2.7 // indirect github.com/containerd/typeurl/v2 v2.2.3 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.6 // indirect + github.com/dimchansky/utfbom v1.1.1 // indirect github.com/docker/distribution v2.8.3+incompatible // indirect github.com/docker/docker-credential-helpers v0.8.2 // indirect github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c // indirect github.com/docker/go-metrics v0.0.1 // indirect + github.com/elliotchance/orderedmap v1.7.1 // indirect github.com/emicklei/go-restful/v3 v3.11.0 // indirect + github.com/fatih/color v1.18.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fvbommel/sortorder v1.1.0 // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect @@ -105,6 +112,8 @@ require ( github.com/go-openapi/jsonreference v0.20.2 // indirect github.com/go-openapi/swag v0.22.4 // indirect github.com/go-viper/mapstructure/v2 v2.0.0 // indirect + github.com/goccy/go-json v0.10.4 // indirect + github.com/goccy/go-yaml v1.13.3 // indirect github.com/gofrs/flock v0.12.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.4 // indirect @@ -120,13 +129,15 @@ require ( github.com/imdario/mergo v0.3.16 // indirect github.com/in-toto/in-toto-golang v0.5.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/jinzhu/copier v0.4.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect github.com/klauspost/compress v1.17.11 // indirect + github.com/magiconair/properties v1.8.9 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.17 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect github.com/miekg/pkcs11 v1.1.1 // indirect @@ -147,6 +158,7 @@ require ( github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect github.com/otiai10/mint v1.6.3 // indirect github.com/pelletier/go-toml v1.9.5 // indirect + github.com/pelletier/go-toml/v2 v2.2.3 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect @@ -169,6 +181,7 @@ require ( github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xeipuuv/gojsonschema v1.2.0 // indirect github.com/xhit/go-str2duration/v2 v2.1.0 // indirect + github.com/yuin/gopher-lua v1.1.1 // indirect github.com/zclconf/go-cty v1.16.0 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.56.0 // indirect diff --git a/go.sum b/go.sum index 0c85121a3..44beb6940 100644 --- a/go.sum +++ b/go.sum @@ -21,8 +21,16 @@ github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod h1:HBCaDe github.com/Shopify/logrus-bugsnag v0.0.0-20170309145241-6dbc35f2c30d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d h1:UrqY+r/OJnIp5u0s1SbQ8dVfLCZJsnvazdBP5hS4iRs= github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= +github.com/a8m/envsubst v1.4.2 h1:4yWIHXOLEJHQEFd4UjrWDrYeYlV7ncFWJOCBRLOZHQg= +github.com/a8m/envsubst v1.4.2/go.mod h1:MVUTQNGQ3tsjOOtKCNd+fl8RzhsXcDvvAEzkhGtlsbY= github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8= github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo= +github.com/alecthomas/assert/v2 v2.3.0 h1:mAsH2wmvjsuvyBvAmCtm7zFsBlb8mIHx5ySLVdDZXL0= +github.com/alecthomas/assert/v2 v2.3.0/go.mod h1:pXcQ2Asjp247dahGEmsZ6ru0UVwnkhktn7S0bBDLxvQ= +github.com/alecthomas/participle/v2 v2.1.1 h1:hrjKESvSqGHzRb4yW1ciisFJ4p3MGYih6icjJvbsmV8= +github.com/alecthomas/participle/v2 v2.1.1/go.mod h1:Y1+hAs8DHPmc3YUFzqllV+eSQ9ljPTk0ZkPMtEdAx2c= +github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc= +github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092 h1:aM1rlcoLz8y5B2r4tTLMiVTrMtpfY0O8EScKJxaSaEc= @@ -81,8 +89,8 @@ github.com/cloudflare/cfssl v0.0.0-20180223231731-4e2dcbde5004 h1:lkAMpLVBDaj17e github.com/cloudflare/cfssl v0.0.0-20180223231731-4e2dcbde5004/go.mod h1:yMWuSON2oQp+43nFtAV/uvKQIFpSPerB57DCt9t8sSA= github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb h1:EDmT6Q9Zs+SbUoc7Ik9EfrFqcylYqgPZ9ANSbTAntnE= github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb/go.mod h1:ZjrT6AXHbDs86ZSdt/osfBi5qfexBrKUdONk989Wnk4= -github.com/compose-spec/compose-go/v2 v2.4.9-0.20250302154753-e508c724a35f h1:kbmTPhf7d9kTnmH0ghAQTqxs1zenKnwKczJlC4z5WSc= -github.com/compose-spec/compose-go/v2 v2.4.9-0.20250302154753-e508c724a35f/go.mod h1:6k5l/0TxCg0/2uLEhRVEsoBWBprS2uvZi32J7xub3lo= +github.com/compose-spec/compose-go/v2 v2.4.9-0.20250306081139-60e14f61e9ef h1:1PcqLEYTxUY28/oZCxtkkF4SpleCrO+Vckw8Skpymz4= +github.com/compose-spec/compose-go/v2 v2.4.9-0.20250306081139-60e14f61e9ef/go.mod h1:6k5l/0TxCg0/2uLEhRVEsoBWBprS2uvZi32J7xub3lo= github.com/containerd/cgroups/v3 v3.0.5 h1:44na7Ud+VwyE7LIoJ8JTNQOa549a8543BmzaJHo6Bzo= github.com/containerd/cgroups/v3 v3.0.5/go.mod h1:SA5DLYnXO8pTGYiAHXz94qvLQTKfVM5GEVisn4jpins= github.com/containerd/console v1.0.4 h1:F2g4+oChYvBTsASRTz8NP6iIAi97J3TtSAsLbIFn4ro= @@ -125,6 +133,8 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/denisenkom/go-mssqldb v0.0.0-20191128021309-1d7a30a10f73/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= +github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi/U= +github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/docker/buildx v0.21.2 h1:r09paH8q9nvAX2PR1ntRrc+C6FBH93bvKUsn1WOb/jU= @@ -155,9 +165,13 @@ github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7/go.mod h1:cyGadeNE github.com/dvsekhvalnov/jose2go v0.0.0-20170216131308-f21a8cedbbae/go.mod h1:7BvyPhdbLxMXIYTFPLsyJRFMsKmOZnQmzh6Gb+uquuM= github.com/eiannone/keyboard v0.0.0-20220611211555-0d226195f203 h1:XBBHcIb256gUJtLmY22n99HaZTz+r2Z51xUPi01m3wg= github.com/eiannone/keyboard v0.0.0-20220611211555-0d226195f203/go.mod h1:E1jcSv8FaEny+OP/5k9UxZVw9YFWGj7eI4KR/iOBqCg= +github.com/elliotchance/orderedmap v1.7.1 h1:8SR2DB391dw0HVI9572ElrY+KU0Q89OCXYwWZx7aAZc= +github.com/elliotchance/orderedmap v1.7.1/go.mod h1:wsDwEaX5jEoyhbs7x93zk2H/qv0zwuhg4inXhDkYqys= github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0= +github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= +github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fsnotify/fsevents v0.2.0 h1:BRlvlqjvNTfogHfeBOFvSC9N0Ddy+wzQCQukyoD7o/c= @@ -169,6 +183,8 @@ github.com/fvbommel/sortorder v1.1.0 h1:fUmoe+HLsBTctBDoaBwpQo5N+nrCp8g/BjKb/6ZQ github.com/fvbommel/sortorder v1.1.0/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0= github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= +github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= +github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= @@ -184,6 +200,12 @@ github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU= github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= +github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= +github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= +github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= +github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= +github.com/go-playground/validator/v10 v10.22.1 h1:40JcKH+bBNGFczGuoBYgX4I6m/i27HYW8P9FDk5PbgA= +github.com/go-playground/validator/v10 v10.22.1/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= github.com/go-sql-driver/mysql v1.3.0 h1:pgwjLi/dvffoP9aabwkT3AKpXQM93QARkjFhDDqC1UE= github.com/go-sql-driver/mysql v1.3.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= @@ -191,6 +213,10 @@ github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1v github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/go-viper/mapstructure/v2 v2.0.0 h1:dhn8MZ1gZ0mzeodTG3jt5Vj/o87xZKuNAprG2mQfMfc= github.com/go-viper/mapstructure/v2 v2.0.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/goccy/go-json v0.10.4 h1:JSwxQzIqKfmFX1swYPpUThQZp/Ka4wzJdK0LWVytLPM= +github.com/goccy/go-json v0.10.4/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= +github.com/goccy/go-yaml v1.13.3 h1:IXRULR8mAa0MXQobzzp0VOfMUJ8EnaQ4x3jhf7S0/nI= +github.com/goccy/go-yaml v1.13.3/go.mod h1:IjYwxUiJDoqpx2RmbdjMUceGHZwYLon3sfOGl5Hi9lc= github.com/gofrs/flock v0.12.1 h1:MTLVXXHf8ekldpJk3AKicLij9MdwOWkZ+a/jHHZby9E= github.com/gofrs/flock v0.12.1/go.mod h1:9zxTsyu5xtJ9DK+1tFZyibEV7y3uwDxPPfbxeeHCoD0= github.com/gogo/protobuf v1.0.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= @@ -241,6 +267,8 @@ github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+l github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= +github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec h1:qv2VnGeEQHchGaZ/u7lxST/RaJw+cv273q79D81Xbog= github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec/go.mod h1:Q48J4R4DvxnHolD5P8pOtXigYlRuPLGl6moFx3ulM68= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= @@ -251,6 +279,8 @@ github.com/in-toto/in-toto-golang v0.5.0/go.mod h1:/Rq0IZHLV7Ku5gielPT4wPHJfH1Gd github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8= +github.com/jinzhu/copier v0.4.0/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg= github.com/jinzhu/gorm v0.0.0-20170222002820-5409931a1bb8 h1:CZkYfurY6KGhVtlalI4QwQ6T0Cu6iuY3e0x5RLu96WE= github.com/jinzhu/gorm v0.0.0-20170222002820-5409931a1bb8/go.mod h1:Vla75njaFJ8clLU1W44h34PjIkijhjHIYnZxMqCdxqo= github.com/jinzhu/inflection v0.0.0-20170102125226-1c35d901db3d h1:jRQLvyVGL+iVtDElaEIDdKwpPqUIZJfzkNLV34htpEc= @@ -285,9 +315,12 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= +github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= github.com/lib/pq v0.0.0-20150723085316-0dad96c0b94f/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/magiconair/properties v1.5.3 h1:C8fxWnhYyME3n0klPOhVM7PtYUB3eV1W3DeFmN3j53Y= github.com/magiconair/properties v1.5.3/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/magiconair/properties v1.8.9 h1:nWcCbLq1N2v/cpNsy5WvQ37Fb+YElfq20WJ/a8RkpQM= +github.com/magiconair/properties v1.8.9/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= @@ -295,8 +328,8 @@ github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxec github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= -github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk= @@ -308,6 +341,8 @@ github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyex github.com/miekg/pkcs11 v1.0.2/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= github.com/miekg/pkcs11 v1.1.1 h1:Ugu9pdy6vAYku5DEpVWVFPYnzV+bxB+iRdbuFSu7TvU= github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= +github.com/mikefarah/yq/v4 v4.45.1 h1:EW+HjKEVa55pUYFJseEHEHdQ0+ulunY+q42zF3M7ZaQ= +github.com/mikefarah/yq/v4 v4.45.1/go.mod h1:djgN2vD749hpjVNGYTShr5Kmv5LYljhCG3lUTuEe3LM= github.com/mitchellh/go-ps v1.0.0 h1:i6ampVEEF4wQFF+bkYfwYgY+F/uYJDktmvLPf7qIgjc= github.com/mitchellh/go-ps v1.0.0/go.mod h1:J4lOc8z8yJs6vUwklHw2XEIiT4z4C40KtWVN3nvg8Pg= github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4= @@ -385,6 +420,10 @@ github.com/otiai10/mint v1.6.3 h1:87qsV/aw1F5as1eH1zS/yqHY85ANKVMgkDrf9rcxbQs= github.com/otiai10/mint v1.6.3/go.mod h1:MJm72SBthJjz8qhefc4z1PYEieWmy8Bku7CjcAqyUSM= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= +github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e h1:aoZm08cpOy4WuID//EZDgcC4zIxODThtZNPirFr42+A= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -499,6 +538,8 @@ github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtX github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/yuin/gopher-lua v1.1.1 h1:kYKnWBjvbNP4XLT3+bPEwAXJx262OhaHDWDVOPjL46M= +github.com/yuin/gopher-lua v1.1.1/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw= github.com/zclconf/go-cty v1.16.0 h1:xPKEhst+BW5D0wxebMZkxgapvOE/dw7bFTlgSc9nD6w= github.com/zclconf/go-cty v1.16.0/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= @@ -597,6 +638,7 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= @@ -646,6 +688,8 @@ gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMy gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/op/go-logging.v1 v1.0.0-20160211212156-b2cb9fa56473 h1:6D+BvnJ/j6e222UW8s2qTSe3wGBtvo0MbVQG/c5k8RE= +gopkg.in/op/go-logging.v1 v1.0.0-20160211212156-b2cb9fa56473/go.mod h1:N1eN2tsCx0Ydtgjl4cqmbRCsY4/+z4cYDeqwZTk6zog= gopkg.in/rethinkdb/rethinkdb-go.v6 v6.2.1 h1:d4KQkxAaAiRY2h5Zqis161Pv91A37uZyJOx73duwUwM= gopkg.in/rethinkdb/rethinkdb-go.v6 v6.2.1/go.mod h1:WbjuEoo1oadwzQ4apSDU+JTvmllEHtsNHS6y7vFc7iw= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= diff --git a/pkg/compose/publish.go b/pkg/compose/publish.go index 8dcdcc074..3fa4d01e0 100644 --- a/pkg/compose/publish.go +++ b/pkg/compose/publish.go @@ -18,10 +18,12 @@ package compose import ( "context" + "crypto/sha256" "errors" "fmt" "os" + "github.com/compose-spec/compose-go/v2/loader" "github.com/compose-spec/compose-go/v2/types" "github.com/distribution/reference" "github.com/docker/buildx/util/imagetools" @@ -30,8 +32,33 @@ import ( "github.com/docker/compose/v2/pkg/api" "github.com/docker/compose/v2/pkg/progress" "github.com/docker/compose/v2/pkg/prompt" + "github.com/mikefarah/yq/v4/pkg/yqlib" + "github.com/sirupsen/logrus" + "gopkg.in/op/go-logging.v1" ) +// _backend redirects go-logging.v1 (used by yqlib) to logrus +type _backend struct{} + +func (b *_backend) Log(l logging.Level, _ int, r *logging.Record) error { + switch l { + case logging.CRITICAL, logging.ERROR: + logrus.Error(r.Message()) + case logging.WARNING: + logrus.Warn(r.Message()) + case logging.NOTICE, logging.INFO: + logrus.Info(r.Message()) + case logging.DEBUG: + + logrus.Debug(r.Message()) + } + return nil +} + +func init() { + logging.SetBackend(&_backend{}) +} + func (s *composeService) Publish(ctx context.Context, project *types.Project, repository string, options api.PublishOptions) error { return progress.RunWithTitle(ctx, func(ctx context.Context) error { return s.publish(ctx, project, repository, options) @@ -60,20 +87,28 @@ func (s *composeService) publish(ctx context.Context, project *types.Project, re Auth: s.configFile(), }) + yqlib.InitExpressionParser() var layers []ocipush.Pushable + extFiles := map[string]string{} for _, file := range project.ComposeFiles { - f, err := os.ReadFile(file) + data, err := processFile(ctx, file, project, extFiles) if err != nil { return err } - layerDescriptor := ocipush.DescriptorForComposeFile(file, f) + layerDescriptor := ocipush.DescriptorForComposeFile(file, data) layers = append(layers, ocipush.Pushable{ Descriptor: layerDescriptor, - Data: f, + Data: data, }) } + extLayers, err := processExtends(ctx, project, extFiles) + if err != nil { + return err + } + layers = append(layers, extLayers...) + if options.WithEnvironment { layers = append(layers, envFileLayers(project)...) } @@ -116,6 +151,94 @@ func (s *composeService) publish(ctx context.Context, project *types.Project, re return nil } +func processExtends(ctx context.Context, project *types.Project, extFiles map[string]string) ([]ocipush.Pushable, error) { + var layers []ocipush.Pushable + moreExtFiles := map[string]string{} + for xf, hash := range extFiles { + data, err := processFile(ctx, xf, project, moreExtFiles) + if err != nil { + return nil, err + } + + layerDescriptor := ocipush.DescriptorForComposeFile(hash, data) + layerDescriptor.Annotations["com.docker.compose.extends"] = "true" + layers = append(layers, ocipush.Pushable{ + Descriptor: layerDescriptor, + Data: data, + }) + } + for f, hash := range moreExtFiles { + if _, ok := extFiles[f]; ok { + delete(moreExtFiles, f) + } + extFiles[f] = hash + } + if len(moreExtFiles) > 0 { + extLayers, err := processExtends(ctx, project, moreExtFiles) + if err != nil { + return nil, err + } + layers = append(layers, extLayers...) + } + return layers, nil +} + +func processFile(ctx context.Context, file string, project *types.Project, extFiles map[string]string) ([]byte, error) { + f, err := os.ReadFile(file) + if err != nil { + return nil, err + } + + base, err := loader.LoadWithContext(ctx, types.ConfigDetails{ + WorkingDir: project.WorkingDir, + Environment: project.Environment, + ConfigFiles: []types.ConfigFile{ + { + Filename: file, + Content: f, + }, + }, + }, func(options *loader.Options) { + options.SkipValidation = true + options.SkipExtends = true + options.SkipConsistencyCheck = true + options.ResolvePaths = true + }) + if err != nil { + return nil, err + } + for name, service := range base.Services { + if service.Extends == nil { + continue + } + xf := service.Extends.File + if xf == "" { + continue + } + if _, err = os.Stat(service.Extends.File); os.IsNotExist(err) { + // No local file, while we loaded the project successfully: This is actually a remote resource + continue + } + + hash := fmt.Sprintf("%x.yaml", sha256.Sum256([]byte(xf))) + extFiles[xf] = hash + + // FIXME implement without relying on yqlib so we don't get extra dependencies + exp := fmt.Sprintf(".services.%s.extends.file = %q", name, hash) + encoder := yqlib.NewYamlEncoder(yqlib.YamlPreferences{ + ColorsEnabled: false, + }) + decoder := yqlib.NewYamlDecoder(yqlib.YamlPreferences{}) + out, err := yqlib.NewStringEvaluator().Evaluate(exp, string(f), encoder, decoder) + if err != nil { + return nil, err + } + + f = []byte(out) + } + return f, nil +} + func (s *composeService) generateImageDigestsOverride(ctx context.Context, project *types.Project) ([]byte, error) { project, err := project.WithProfiles([]string{"*"}) if err != nil { diff --git a/pkg/compose/publish_test.go b/pkg/compose/publish_test.go new file mode 100644 index 000000000..680b691fc --- /dev/null +++ b/pkg/compose/publish_test.go @@ -0,0 +1,75 @@ +/* + 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 ( + "context" + "os" + "testing" + + "github.com/compose-spec/compose-go/v2/loader" + "github.com/compose-spec/compose-go/v2/types" + "github.com/docker/compose/v2/internal/ocipush" + "github.com/docker/compose/v2/pkg/api" + v1 "github.com/opencontainers/image-spec/specs-go/v1" + "gotest.tools/v3/assert" +) + +func Test_processExtends(t *testing.T) { + project, err := loader.LoadWithContext(context.TODO(), types.ConfigDetails{ + WorkingDir: "testdata/publish/", + Environment: types.Mapping{}, + ConfigFiles: []types.ConfigFile{ + { + Filename: "testdata/publish/compose.yaml", + }, + }, + }) + assert.NilError(t, err) + extFiles := map[string]string{} + file, err := processFile(context.TODO(), "testdata/publish/compose.yaml", project, extFiles) + assert.NilError(t, err) + + assert.Equal(t, string(file), `name: test +services: + test: + extends: + file: f8f9ede3d201ec37d5a5e3a77bbadab79af26035e53135e19571f50d541d390c.yaml + service: foo +`) + + layers, err := processExtends(context.TODO(), project, extFiles) + assert.NilError(t, err) + + b, err := os.ReadFile("testdata/publish/common.yaml") + assert.NilError(t, err) + assert.DeepEqual(t, []ocipush.Pushable{ + { + Descriptor: v1.Descriptor{ + MediaType: "application/vnd.docker.compose.file+yaml", + Digest: "sha256:d3ba84507b56ec783f4b6d24306b99a15285f0a23a835f0b668c2dbf9c59c241", + Size: 32, + Annotations: map[string]string{ + "com.docker.compose.extends": "true", + "com.docker.compose.file": "f8f9ede3d201ec37d5a5e3a77bbadab79af26035e53135e19571f50d541d390c.yaml", + "com.docker.compose.version": api.ComposeVersion, + }, + }, + Data: b, + }, + }, layers) +} diff --git a/pkg/compose/testdata/publish/common.yaml b/pkg/compose/testdata/publish/common.yaml new file mode 100644 index 000000000..ce048e366 --- /dev/null +++ b/pkg/compose/testdata/publish/common.yaml @@ -0,0 +1,3 @@ +services: + foo: + image: bar diff --git a/pkg/compose/testdata/publish/compose.yaml b/pkg/compose/testdata/publish/compose.yaml new file mode 100644 index 000000000..413851cee --- /dev/null +++ b/pkg/compose/testdata/publish/compose.yaml @@ -0,0 +1,6 @@ +name: test +services: + test: + extends: + file: common.yaml + service: foo diff --git a/pkg/e2e/fixtures/publish/another/compose.yml b/pkg/e2e/fixtures/publish/common.yaml similarity index 100% rename from pkg/e2e/fixtures/publish/another/compose.yml rename to pkg/e2e/fixtures/publish/common.yaml diff --git a/pkg/e2e/fixtures/publish/compose-local-include.yml b/pkg/e2e/fixtures/publish/compose-local-include.yml index ad228af45..1af74e926 100644 --- a/pkg/e2e/fixtures/publish/compose-local-include.yml +++ b/pkg/e2e/fixtures/publish/compose-local-include.yml @@ -1,5 +1,5 @@ include: - - ./another/compose.yml + - common.yaml services: test: diff --git a/pkg/e2e/fixtures/publish/compose-with-extends.yml b/pkg/e2e/fixtures/publish/compose-with-extends.yml new file mode 100644 index 000000000..f8c1349f5 --- /dev/null +++ b/pkg/e2e/fixtures/publish/compose-with-extends.yml @@ -0,0 +1,5 @@ +services: + test: + extends: + file: common.yaml + service: foo diff --git a/pkg/e2e/publish_test.go b/pkg/e2e/publish_test.go index 611ca2cc2..d457455c2 100644 --- a/pkg/e2e/publish_test.go +++ b/pkg/e2e/publish_test.go @@ -91,6 +91,12 @@ or remove sensitive data from your Compose configuration assert.Assert(t, !strings.Contains(res.Combined(), "test/test published"), res.Combined()) }) + t.Run("publish with extends", func(t *testing.T) { + res := c.RunDockerComposeCmd(t, "-f", "./fixtures/publish/compose-with-extends.yml", + "-p", projectName, "alpha", "publish", "test/test", "--dry-run") + assert.Assert(t, strings.Contains(res.Combined(), "test/test published"), res.Combined()) + }) + t.Run("publish list env variables", func(t *testing.T) { cmd := c.NewDockerComposeCmd(t, "-f", "./fixtures/publish/compose-multi-env-config.yml", "-p", projectName, "alpha", "publish", "test/test", "--with-env", "--dry-run") diff --git a/pkg/remote/git.go b/pkg/remote/git.go index e37e52bf0..4668d9075 100644 --- a/pkg/remote/git.go +++ b/pkg/remote/git.go @@ -43,7 +43,7 @@ func gitRemoteLoaderEnabled() (bool, error) { } return enabled, err } - return false, nil + return true, nil } func NewGitRemoteLoader(dockerCli command.Cli, offline bool) loader.ResourceLoader { @@ -73,7 +73,7 @@ func (g gitRemoteLoader) Load(ctx context.Context, path string) (string, error) return "", err } if !enabled { - return "", fmt.Errorf("experimental git remote resource is disabled. %q must be set", GIT_REMOTE_ENABLED) + return "", fmt.Errorf("git remote resource is disabled by %q", GIT_REMOTE_ENABLED) } ref, err := gitutil.ParseGitRef(path) diff --git a/pkg/remote/oci.go b/pkg/remote/oci.go index b5ce3a8ae..5dff332ef 100644 --- a/pkg/remote/oci.go +++ b/pkg/remote/oci.go @@ -47,7 +47,7 @@ func ociRemoteLoaderEnabled() (bool, error) { } return enabled, err } - return false, nil + return true, nil } func NewOCIRemoteLoader(dockerCli command.Cli, offline bool) loader.ResourceLoader { @@ -74,7 +74,7 @@ func (g ociRemoteLoader) Load(ctx context.Context, path string) (string, error) return "", err } if !enabled { - return "", fmt.Errorf("experimental OCI remote resource is disabled. %q must be set", OCI_REMOTE_ENABLED) + return "", fmt.Errorf("OCI remote resource is disabled by %q", OCI_REMOTE_ENABLED) } if g.offline { @@ -105,7 +105,6 @@ func (g ociRemoteLoader) Load(ctx context.Context, path string) (string, error) } local = filepath.Join(cache, descriptor.Digest.Hex()) - composeFile := filepath.Join(local, "compose.yaml") if _, err = os.Stat(local); os.IsNotExist(err) { var manifest v1.Manifest err = json.Unmarshal(content, &manifest) @@ -113,11 +112,11 @@ func (g ociRemoteLoader) Load(ctx context.Context, path string) (string, error) return "", err } - err2 := g.pullComposeFiles(ctx, local, composeFile, manifest, ref, resolver) - if err2 != nil { + err = g.pullComposeFiles(ctx, local, manifest, ref, resolver) + if err != nil { // we need to clean up the directory to be sure we won't let empty files present _ = os.RemoveAll(local) - return "", err2 + return "", err } } g.known[path] = local @@ -129,12 +128,12 @@ func (g ociRemoteLoader) Dir(path string) string { return g.known[path] } -func (g ociRemoteLoader) pullComposeFiles(ctx context.Context, local string, composeFile string, manifest v1.Manifest, ref reference.Named, resolver *imagetools.Resolver) error { +func (g ociRemoteLoader) pullComposeFiles(ctx context.Context, local string, manifest v1.Manifest, ref reference.Named, resolver *imagetools.Resolver) error { //nolint:gocyclo err := os.MkdirAll(local, 0o700) if err != nil { return err } - + composeFile := filepath.Join(local, "compose.yaml") f, err := os.Create(composeFile) if err != nil { return err @@ -157,7 +156,15 @@ func (g ociRemoteLoader) pullComposeFiles(ctx context.Context, local string, com switch layer.MediaType { case ocipush.ComposeYAMLMediaType: - if err := writeComposeFile(layer, i, f, content); err != nil { + target := f + _, extends := layer.Annotations["com.docker.compose.extends"] + if extends { + target, err = os.Create(filepath.Join(local, layer.Annotations["com.docker.compose.file"])) + if err != nil { + return err + } + } + if err := writeComposeFile(layer, i, target, content); err != nil { return err } case ocipush.ComposeEnvFileMediaType: