From 07986b466c5befb6f61fa9a1e223bc85b20cc55c Mon Sep 17 00:00:00 2001 From: Eric Hripko Date: Sat, 1 May 2021 10:18:02 +0100 Subject: [PATCH] Use BuildKit FDK (#4) --- go.mod | 19 +- go.sum | 52 +- internal/app/packer-frontend/build.go | 7 +- internal/app/packer-frontend/build_test.go | 7 +- internal/app/packer-frontend/frontend.go | 3 + internal/app/packer-frontend/helper.go | 47 ++ internal/app/packer-frontend/helper_test.go | 139 +++++ pkg/cib/cib.go | 53 -- pkg/cib/helper.go | 83 --- pkg/cib/helper_test.go | 238 --------- pkg/cib/mock/cib.go | 243 --------- pkg/cib/mock/client.go | 196 ------- pkg/cib/service.go | 266 --------- pkg/cib/service_test.go | 505 ------------------ pkg/cib/vendor.go | 64 --- pkg/{cib => packer2llb/config}/config.go | 12 +- pkg/{cib => packer2llb/config}/config_test.go | 10 +- pkg/packer2llb/mock/packer2llb.go | 5 +- pkg/packer2llb/packer2llb.go | 10 +- pkg/packer2llb/packer2llb_test.go | 12 +- pkg/plugins/golang/golang.go | 15 +- pkg/plugins/golang/golang_test.go | 18 +- 22 files changed, 292 insertions(+), 1712 deletions(-) create mode 100644 internal/app/packer-frontend/frontend.go create mode 100644 internal/app/packer-frontend/helper.go create mode 100644 internal/app/packer-frontend/helper_test.go delete mode 100644 pkg/cib/cib.go delete mode 100644 pkg/cib/helper.go delete mode 100644 pkg/cib/helper_test.go delete mode 100644 pkg/cib/mock/cib.go delete mode 100644 pkg/cib/mock/client.go delete mode 100644 pkg/cib/service.go delete mode 100644 pkg/cib/service_test.go delete mode 100644 pkg/cib/vendor.go rename pkg/{cib => packer2llb/config}/config.go (77%) rename pkg/{cib => packer2llb/config}/config_test.go (90%) diff --git a/go.mod b/go.mod index e08cdef..108c7f3 100644 --- a/go.mod +++ b/go.mod @@ -3,22 +3,19 @@ module github.com/EricHripko/pack.yaml go 1.15 require ( - github.com/containerd/containerd v1.4.1-0.20201117152358-0edc412565dc - github.com/docker/distribution v2.7.1+incompatible - github.com/docker/docker v20.10.0-beta1.0.20201110211921-af34b94a78a1+incompatible - github.com/golang/mock v1.4.4 + github.com/EricHripko/buildkit-fdk v0.0.2 + github.com/containerd/containerd v1.4.4 + github.com/golang/mock v1.5.0 github.com/mitchellh/mapstructure v1.3.1 - github.com/moby/buildkit v0.8.1 - github.com/opencontainers/go-digest v1.0.0 + github.com/moby/buildkit v0.8.2 github.com/opencontainers/image-spec v1.0.1 github.com/pkg/errors v0.9.1 - github.com/sirupsen/logrus v1.7.0 - github.com/stretchr/testify v1.5.1 + github.com/sirupsen/logrus v1.8.1 + github.com/stretchr/testify v1.7.0 github.com/tonistiigi/fsutil v0.0.0-20201103201449-0834f99b7b85 golang.org/x/mod v0.3.0 - golang.org/x/net v0.0.0-20201021035429-f5854403a974 // indirect - golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 + golang.org/x/sync v0.0.0-20210220032951-036812b2e83c golang.org/x/sys v0.0.0-20210112080510-489259a85091 // indirect - golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect + golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d gopkg.in/yaml.v2 v2.3.0 ) diff --git a/go.sum b/go.sum index 60ff5cf..513b8ca 100644 --- a/go.sum +++ b/go.sum @@ -88,6 +88,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/Djarvur/go-err113 v0.0.0-20200410182137-af658d038157/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= github.com/Djarvur/go-err113 v0.1.0/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= +github.com/EricHripko/buildkit-fdk v0.0.2 h1:yhNr5nebBKZ0tg+2ERdC2yNNJqFEws2CTAHUminhfYs= +github.com/EricHripko/buildkit-fdk v0.0.2/go.mod h1:+VXcEFOUjQeXUrEfH7P2k3Vhfqn+uyaTV2w8fJCt4cw= github.com/GoogleCloudPlatform/cloudsql-proxy v0.0.0-20191009163259-e802c2cb94ae/go.mod h1:mjwGPas4yKduTyubHvD1Atl9r1rUq8DfVy+gkVvZ+oo= github.com/GoogleCloudPlatform/k8s-cloud-provider v0.0.0-20190822182118-27a4ced34534/go.mod h1:iroGtC8B3tQiqtds1l+mgk/BBOrxbqjH+eUfFQYRc14= github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= @@ -187,6 +189,8 @@ github.com/containerd/containerd v1.3.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMX github.com/containerd/containerd v1.4.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= github.com/containerd/containerd v1.4.1-0.20201117152358-0edc412565dc h1:XbZ/DDsFDigeOQ9M3YXhvE6d1AEHdxKAzIgkswip7dI= github.com/containerd/containerd v1.4.1-0.20201117152358-0edc412565dc/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.4.4 h1:rtRG4N6Ct7GNssATwgpvMGfnjnwfjnu/Zs9W3Ikzq+M= +github.com/containerd/containerd v1.4.4/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= github.com/containerd/continuity v0.0.0-20200710164510-efbc4488d8fe/go.mod h1:cECdGN1O8G9bgKTlLhuPJimka6Xb/Gg7vYzCTNVxhvo= github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= @@ -249,9 +253,12 @@ github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7/go.mod h1:eEKB0N0r github.com/docker/docker v17.12.0-ce-rc1.0.20200730172259-9f28837c1d93+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v20.10.0-beta1.0.20201110211921-af34b94a78a1+incompatible h1:J2OhsbfqoBRRT048iD/tqXBvEQWQATQ8vew6LqQmDSU= github.com/docker/docker v20.10.0-beta1.0.20201110211921-af34b94a78a1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v20.10.6+incompatible h1:oXI3Vas8TI8Eu/EjH4srKHJBVqraSzJybhxY7Om9faQ= +github.com/docker/docker v20.10.6+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= +github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c h1:+pKlWGMw7gf6bQ+oDZB4KHQFypsfjYlq/C4rfL7D3g8= github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI= github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= @@ -351,6 +358,7 @@ github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4er github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= @@ -360,8 +368,8 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.3 h1:GV+pQPG/EUUbkh47niozDcADz6go/dUwhVzdUQHIVRw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/mock v1.5.0 h1:jlYHihg//f7RRwuPfptm04yp4s7O6Kw8EZiVYIGcH0g= +github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -377,6 +385,8 @@ github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvq github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2/go.mod h1:k9Qvh+8juN+UKMCS/3jFtGICgW8O96FVaZsaxdzDkR4= github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a/go.mod h1:ryS0uhF+x9jgbj/N71xsEqODy9BN81/GonCZiOzirOk= @@ -407,6 +417,9 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.4.1 h1:/exdXoGamhu5ONeUJH0deniYLWYvQwW66yvlfiiKTu0= github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-containerregistry v0.0.0-20191010200024-a3d713f9b7f8/go.mod h1:KyKXa9ciM8+lgMXwOVsXi7UxGrsf9mM61Mzs+xKUrKE= github.com/google/go-containerregistry v0.1.2/go.mod h1:GPivBPgdAyd2SU+vf6EpsgOtWDuPqjW0hJZt4rNdTZ4= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= @@ -433,6 +446,8 @@ github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3 github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/wire v0.3.0/go.mod h1:i1DMg/Lu8Sz5yYl25iOdmc5CT5qusaa+zmRWs16741s= github.com/google/wire v0.4.0/go.mod h1:ngWDr9Qvq3yZA10YrxfyGELY/AFWGVpy9c1LTRi1EoU= github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= @@ -605,8 +620,8 @@ github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh github.com/mitchellh/mapstructure v1.3.1 h1:cCBH2gTD2K0OtLlv/Y5H01VQCqmlDxz30kS5Y5bqfLA= github.com/mitchellh/mapstructure v1.3.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A= -github.com/moby/buildkit v0.8.1 h1:zrGxLwffKM8nVxBvaJa7H404eQLfqlg1GB6YVIzXVQ0= -github.com/moby/buildkit v0.8.1/go.mod h1:/kyU1hKy/aYCuP39GZA9MaKioovHku57N6cqlKZIaiQ= +github.com/moby/buildkit v0.8.2 h1:kvb0cLWss4mOhCxcXSTENzzA+t1JR1eIyXFhDrI+73g= +github.com/moby/buildkit v0.8.2/go.mod h1:5PZi7ALzuxG604ggYSeN+rzC+CyJscuXS7WetulJr1Y= 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/sys/mount v0.1.0/go.mod h1:FVQFLDRWwyBjDTBNQXDlWnSFREqOo3OKX9aqhmeoo74= @@ -670,6 +685,8 @@ github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/ github.com/opencontainers/runtime-spec v1.0.3-0.20200728170252-4d89ac9fbff6/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs= github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE= +github.com/opencontainers/selinux v1.8.0 h1:+77ba4ar4jsCbL1GLbFL8fFM57w6suPfSS9PDLDY7KM= +github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo= github.com/opentracing-contrib/go-stdlib v1.0.0/go.mod h1:qtI1ogk+2JhVPIXVc6q+NHziSmy2W5GbdQZFUHADCBU= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= @@ -758,6 +775,8 @@ github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6Mwd github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/assertions v1.0.0/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM= github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9/go.mod h1:SnhjPscd9TpLiy1LpzGSKh3bXCfxxXuqd9xmQJy3slM= @@ -790,6 +809,7 @@ github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5q github.com/stretchr/objx v0.0.0-20180129172003-8a3f7159479f/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v0.0.0-20180303142811-b89eecf5ca5d/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= @@ -798,6 +818,8 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= @@ -841,6 +863,8 @@ github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYp github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= github.com/vmware/govmomi v0.20.3/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU= github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= +github.com/willf/bitset v1.1.11 h1:N7Z7E9UvjW+sGsEl7k/SJrvY2reP1A07MrGuCjIOjRE= +github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI= github.com/xanzy/go-gitlab v0.31.0/go.mod h1:sPLojNBn68fMUWSxIJtdVVIP8uSBYqesTfDUseX11Ug= github.com/xanzy/go-gitlab v0.32.0/go.mod h1:sPLojNBn68fMUWSxIJtdVVIP8uSBYqesTfDUseX11Ug= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= @@ -866,6 +890,7 @@ go.opencensus.io v0.19.2/go.mod h1:NO/8qkisMZLZ1FCsKNqtJPwc8/TaclWyY0B6wcYNg9M= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3 h1:8sGtKOrtQqkN1bp2AtX+misvLIlOmsEsNd+9NIcPEm8= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= 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= @@ -970,8 +995,8 @@ golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381 h1:VXak5I6aEWmAXeQjA+QSZzlgNrpq9mjcfDemuexIKsU= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20201021035429-f5854403a974 h1:IX6qOQeG5uLjB/hjjwjedwfjND0hgjPMMyO1RoIXQNI= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb h1:eBmm0M9fYhWpKZLjQUUKka/LtIxf46G4fxeEz5KJr9U= +golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= 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= @@ -992,8 +1017,8 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 h1:qwRHBd0NqMbJxfbotnDhm2ByMI1Shq4Y6oRJo21SGJA= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 h1:SQFwaSi55rU7vdNs9Yr0Z324VNlrF+0wMqRXT4St8ck= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1070,6 +1095,8 @@ golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3 golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc= +golang.org/x/text v0.3.4/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= @@ -1218,6 +1245,8 @@ google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20200527145253-8367513e4ece h1:1YM0uhfumvoDu9sx8+RyWwTI63zoCQvI23IYFRlvte0= google.golang.org/genproto v0.0.0-20200527145253-8367513e4ece/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20201022181438-0ff5f38871d5 h1:YejJbGvoWsTXHab4OKNrzk27Dr7s4lPLnewbHue1+gM= +google.golang.org/genproto v0.0.0-20201022181438-0ff5f38871d5/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= @@ -1235,6 +1264,8 @@ google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8 google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= google.golang.org/grpc v1.29.1 h1:EC2SB8S04d2r73uptxphDSUG+kTKVgjRPF+N3xpxRB4= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.33.1 h1:DGeFlSan2f+WEtCERJ4J9GJWk15TxUi8QGagfI87Xyc= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -1245,6 +1276,8 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.24.0 h1:UhZDfRO8JRQru4/+LlLE0BRKGF8L+PICnvYZmx/fEGA= google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -1277,6 +1310,9 @@ gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ= +gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= gotest.tools/v3 v3.0.2 h1:kG1BFyqVHuQoVQiR1bWGnfz/fmHvvuiSPIV7rvl360E= diff --git a/internal/app/packer-frontend/build.go b/internal/app/packer-frontend/build.go index 04fffc6..2764ffd 100644 --- a/internal/app/packer-frontend/build.go +++ b/internal/app/packer-frontend/build.go @@ -6,9 +6,10 @@ import ( "fmt" "strconv" - "github.com/EricHripko/pack.yaml/pkg/cib" "github.com/EricHripko/pack.yaml/pkg/packer2llb" + "github.com/EricHripko/pack.yaml/pkg/packer2llb/config" + "github.com/EricHripko/buildkit-fdk/pkg/cib" "github.com/containerd/containerd/platforms" "github.com/moby/buildkit/exporter/containerimage/exptypes" "github.com/moby/buildkit/frontend/gateway/client" @@ -63,7 +64,7 @@ func BuildWithService(ctx context.Context, c client.Client, svc cib.Service) (*c if err != nil { return err } - metadata, err := cib.ReadConfig(dtMetadata) + metadata, err := config.Read(dtMetadata) if err != nil { return err } @@ -106,7 +107,7 @@ func BuildWithService(ctx context.Context, c client.Client, svc cib.Service) (*c } else { // Find command var cmd string - cmd, err = cib.FindCommand(ctx, ref) + cmd, err = findCommand(ctx, ref) if err != nil { return err } diff --git a/internal/app/packer-frontend/build_test.go b/internal/app/packer-frontend/build_test.go index 857c039..de681c0 100644 --- a/internal/app/packer-frontend/build_test.go +++ b/internal/app/packer-frontend/build_test.go @@ -6,11 +6,10 @@ import ( "path" "testing" - "github.com/EricHripko/pack.yaml/pkg/cib" - cib_mock "github.com/EricHripko/pack.yaml/pkg/cib/mock" "github.com/EricHripko/pack.yaml/pkg/packer2llb" packer2llb_mock "github.com/EricHripko/pack.yaml/pkg/packer2llb/mock" + cib_mock "github.com/EricHripko/buildkit-fdk/pkg/cib/mock" "github.com/golang/mock/gomock" "github.com/moby/buildkit/client/llb" "github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb" @@ -231,7 +230,7 @@ func (suite *singleTestSuite) TestFindCommandFails() { _, err := BuildWithService(suite.ctx, suite.client, suite.build) // Assert - require.Same(suite.T(), cib.ErrNoCommand, err) + require.Same(suite.T(), errNoCommand, err) } func (suite *singleTestSuite) TestSucceedsImplicitCommand() { @@ -257,7 +256,7 @@ func (suite *singleTestSuite) TestSucceedsImplicitCommand() { ref := cib_mock.NewMockReference(suite.ctrl) files := []*fsutil.Stat{ - {Path: path.Join(cib.DirInstall, "command"), Mode: 0755}, + {Path: path.Join(packer2llb.DirInstall, "command"), Mode: 0755}, } ref.EXPECT(). ReadDir(gomock.Any(), gomock.Any()). diff --git a/internal/app/packer-frontend/frontend.go b/internal/app/packer-frontend/frontend.go new file mode 100644 index 0000000..b09bcab --- /dev/null +++ b/internal/app/packer-frontend/frontend.go @@ -0,0 +1,3 @@ +// Package frontend houses a custom BuildKit frontend for projects that use +// pack.yaml. +package frontend diff --git a/internal/app/packer-frontend/helper.go b/internal/app/packer-frontend/helper.go new file mode 100644 index 0000000..96f1d79 --- /dev/null +++ b/internal/app/packer-frontend/helper.go @@ -0,0 +1,47 @@ +package frontend + +import ( + "context" + "errors" + "os" + "strings" + + "github.com/EricHripko/pack.yaml/pkg/packer2llb" + + "github.com/EricHripko/buildkit-fdk/pkg/cib" + "github.com/moby/buildkit/frontend/gateway/client" + fsutil "github.com/tonistiigi/fsutil/types" +) + +// Returned when no command was found in the produced image. +var errNoCommand = errors.New("frontend: no command found") + +// Looks in the known install directory and attempts to automatically detect +// the command for the image. +func findCommand(ctx context.Context, ref client.Reference) (command string, err error) { + prefix := packer2llb.DirInstall[1:] + err = cib.WalkRecursive(ctx, ref, func(file *fsutil.Stat) error { + // Must be in install location + if !strings.HasPrefix(file.Path, prefix) { + return nil + } + // Must not be a directory + if os.FileMode(file.Mode).IsDir() { + return nil + } + // Must be executable + if file.Mode&0100 == 0 { + return nil + } + // Multiple commands found + if command != "" { + return errors.New("frontend: multiple commands found (" + command + ")") + } + command = "/" + file.Path + return nil + }) + if command == "" { + err = errNoCommand + } + return +} diff --git a/internal/app/packer-frontend/helper_test.go b/internal/app/packer-frontend/helper_test.go new file mode 100644 index 0000000..b9799d0 --- /dev/null +++ b/internal/app/packer-frontend/helper_test.go @@ -0,0 +1,139 @@ +package frontend + +import ( + "context" + "os" + "testing" + + cib_mock "github.com/EricHripko/buildkit-fdk/pkg/cib/mock" + "github.com/golang/mock/gomock" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" + fsutil "github.com/tonistiigi/fsutil/types" +) + +type findCommandTestSuite struct { + suite.Suite + ctrl *gomock.Controller + ctx context.Context + ref *cib_mock.MockReference +} + +func (suite *findCommandTestSuite) SetupTest() { + suite.ctrl = gomock.NewController(suite.T()) + suite.ctx = context.Background() + suite.ref = cib_mock.NewMockReference(suite.ctrl) +} + +func (suite *findCommandTestSuite) TearDownTest() { + suite.ctrl.Finish() +} + +func (suite *findCommandTestSuite) TestNotFound() { + // Arrange + files := []*fsutil.Stat{} + suite.ref.EXPECT(). + ReadDir(suite.ctx, gomock.Any()). + Return(files, nil) + + // Act + cmd, err := findCommand(suite.ctx, suite.ref) + + // Assert + require.Empty(suite.T(), cmd) + require.Same(suite.T(), errNoCommand, err) +} + +func (suite *findCommandTestSuite) TestIgnoresNonPrefix() { + // Arrange + files := []*fsutil.Stat{ + {Path: "README.md"}, + } + suite.ref.EXPECT(). + ReadDir(suite.ctx, gomock.Any()). + Return(files, nil) + + // Act + cmd, err := findCommand(suite.ctx, suite.ref) + + // Assert + require.Empty(suite.T(), cmd) + require.Same(suite.T(), errNoCommand, err) +} + +func (suite *findCommandTestSuite) TestIgnoresDirs() { + // Arrange + files := []*fsutil.Stat{ + {Path: "usr/local/bin/data", Mode: uint32(os.ModeDir)}, + } + suite.ref.EXPECT(). + ReadDir(suite.ctx, gomock.Any()). + Return(files, nil) + suite.ref.EXPECT(). + ReadDir(suite.ctx, gomock.Any()). + Return([]*fsutil.Stat{}, nil) + + // Act + cmd, err := findCommand(suite.ctx, suite.ref) + + // Assert + require.Empty(suite.T(), cmd) + require.Same(suite.T(), errNoCommand, err) +} + +func (suite *findCommandTestSuite) TestIgnoresNonExecutable() { + // Arrange + files := []*fsutil.Stat{ + {Path: "usr/local/bin/README.md"}, + } + suite.ref.EXPECT(). + ReadDir(suite.ctx, gomock.Any()). + Return(files, nil) + + // Act + cmd, err := findCommand(suite.ctx, suite.ref) + + // Assert + require.Empty(suite.T(), cmd) + require.Same(suite.T(), errNoCommand, err) +} + +func (suite *findCommandTestSuite) TestMultipleCommands() { + // Arrange + files := []*fsutil.Stat{ + {Path: "usr/local/bin/hello1", Mode: 0755}, + {Path: "usr/local/bin/hello2", Mode: 0755}, + } + suite.ref.EXPECT(). + ReadDir(suite.ctx, gomock.Any()). + Return(files, nil) + + // Act + _, err := findCommand(suite.ctx, suite.ref) + + // Assert + require.NotNil(suite.T(), err) + require.Contains(suite.T(), err.Error(), "multiple commands") + require.Contains(suite.T(), err.Error(), files[0].Path) +} + +func (suite *findCommandTestSuite) TestSucceeds() { + // Arrange + files := []*fsutil.Stat{ + {Path: "usr/local/bin/hello", Mode: 0755}, + } + suite.ref.EXPECT(). + ReadDir(suite.ctx, gomock.Any()). + Return(files, nil) + + // Act + cmd, err := findCommand(suite.ctx, suite.ref) + + // Assert + require.Equal(suite.T(), "/usr/local/bin/hello", cmd) + require.Nil(suite.T(), err) +} + +func TestFindCommand(t *testing.T) { + suite.Run(t, new(findCommandTestSuite)) +} diff --git a/pkg/cib/cib.go b/pkg/cib/cib.go deleted file mode 100644 index 274ab77..0000000 --- a/pkg/cib/cib.go +++ /dev/null @@ -1,53 +0,0 @@ -// Package cib contains the primitives for container image building. -package cib - -import ( - "github.com/moby/buildkit/client/llb" - "github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb" - "github.com/moby/buildkit/frontend/gateway/client" - "github.com/moby/buildkit/util/apicaps" - specs "github.com/opencontainers/image-spec/specs-go/v1" -) - -// DirInstall represents the target path that the binaries will be installed -// in. -const DirInstall = "/usr/local/bin" - -//go:generate mockgen -package cib_mock -destination mock/cib.go . Service -//go:generate mockgen -package cib_mock -destination mock/client.go github.com/moby/buildkit/frontend/gateway/client Client,Reference - -// Service that wraps low-level BuildKit actions and provides a simple -// interface for container image build. -type Service interface { - // GetOpts returns client options. - GetOpts() map[string]string - // GetCaps returns the capabilities of the service. - GetCaps() apicaps.CapSet - // GetMarshalOpts returns options for marshalling LLB. - GetMarshalOpts() []llb.ConstraintsOpt - // GetResolveMode returns the resolution mode for base images. - GetResolveMode() (llb.ResolveMode, error) - // GetMetadataFileName returns the name for the metadata file. This is - // typically pack.yaml. - GetMetadataFileName() string - // GetMetadata returns the contents of the metadata file. - GetMetadata() ([]byte, error) - // GetExcludes returns the list of paths to exclude from the build context. - GetExcludes() ([]string, error) - // GetBuildPlatform returns the build platform for the client. - GetBuildPlatform() *specs.Platform - // GetTargetPlatforms returns the list of target platforms for the image(s) being built. - GetTargetPlatforms() ([]*specs.Platform, error) - // GetIgnoreCache indicates whether the cache should be ignored. - GetIgnoreCache() bool - - // Src returns the reference to the source code (created lazily). - Src() (ref client.Reference, err error) - // SrcState returns the LLB state of the source code (created lazily). - SrcState() (state llb.State, err error) - - // FetchImageConfig returns the configuration of the image for the given platform. - FetchImageConfig(name string, platform *specs.Platform) (dockerfile2llb.Image, error) - // From creates a new LLB state from the specified base image. - From(base string, platform *specs.Platform, comment string) (llb.State, *dockerfile2llb.Image, error) -} diff --git a/pkg/cib/helper.go b/pkg/cib/helper.go deleted file mode 100644 index e2c64ed..0000000 --- a/pkg/cib/helper.go +++ /dev/null @@ -1,83 +0,0 @@ -package cib - -import ( - "context" - "errors" - "os" - "path" - "strings" - - "github.com/moby/buildkit/frontend/gateway/client" - fsutil "github.com/tonistiigi/fsutil/types" -) - -// ErrNoCommand is returned when no command was found in the produced image. -var ErrNoCommand = errors.New("cib: no command found") - -// WalkFunc is the type of function called for each file or directory visited -// by WalkRecursive. -type WalkFunc func(file *fsutil.Stat) error - -// WalkRecursive iterates all the files in the reference recursively. -func WalkRecursive(ctx context.Context, ref client.Reference, walkFn WalkFunc) error { - return walkRecursive(ctx, ref, ".", walkFn) -} - -func walkRecursive(ctx context.Context, ref client.Reference, root string, walkFn WalkFunc) error { - files, err := ref.ReadDir(ctx, client.ReadDirRequest{Path: root}) - if err != nil { - return err - } - - for _, file := range files { - // Make path absolute for easier integration - file.Path = path.Join(root, file.Path) - - // Callback - err = walkFn(file) - if err != nil { - return err - } - - // Walk folders - mode := os.FileMode(file.Mode) - if mode.IsDir() { - err = walkRecursive(ctx, ref, file.Path, walkFn) - if err != nil { - return err - } - } - } - return nil - -} - -// FindCommand looks in the known install directory and attempts to -// automatically detect the command for the image. -func FindCommand(ctx context.Context, ref client.Reference) (command string, err error) { - prefix := DirInstall[1:] - err = WalkRecursive(ctx, ref, func(file *fsutil.Stat) error { - // Must be in install location - if !strings.HasPrefix(file.Path, prefix) { - return nil - } - // Must not be a directory - if os.FileMode(file.Mode).IsDir() { - return nil - } - // Must be executable - if file.Mode&0100 == 0 { - return nil - } - // Multiple commands found - if command != "" { - return errors.New("cib: multiple commands found (" + command + ")") - } - command = "/" + file.Path - return nil - }) - if command == "" { - err = ErrNoCommand - } - return -} diff --git a/pkg/cib/helper_test.go b/pkg/cib/helper_test.go deleted file mode 100644 index d91b4d3..0000000 --- a/pkg/cib/helper_test.go +++ /dev/null @@ -1,238 +0,0 @@ -package cib - -import ( - "context" - "errors" - "os" - "testing" - - cib_mock "github.com/EricHripko/pack.yaml/pkg/cib/mock" - - "github.com/golang/mock/gomock" - "github.com/moby/buildkit/frontend/gateway/client" - "github.com/stretchr/testify/require" - "github.com/stretchr/testify/suite" - fsutil "github.com/tonistiigi/fsutil/types" -) - -func walkFnNoop(*fsutil.Stat) error { - return nil -} - -type walkRecursiveTestSuite struct { - suite.Suite - ctrl *gomock.Controller - ctx context.Context - ref *cib_mock.MockReference -} - -func (suite *walkRecursiveTestSuite) SetupTest() { - suite.ctrl = gomock.NewController(suite.T()) - suite.ctx = context.Background() - suite.ref = cib_mock.NewMockReference(suite.ctrl) -} - -func (suite *walkRecursiveTestSuite) TearDownTest() { - suite.ctrl.Finish() -} - -func (suite *walkRecursiveTestSuite) TestReadDirFails() { - // Arrange - actual := errors.New("something went wrong") - req := client.ReadDirRequest{Path: "."} - suite.ref.EXPECT(). - ReadDir(suite.ctx, req). - Return(nil, actual) - - // Act - expected := WalkRecursive(suite.ctx, suite.ref, walkFnNoop) - - // Assert - require.Same(suite.T(), expected, actual) -} - -func (suite *walkRecursiveTestSuite) TestWalkFnFails() { - // Arrange - req := client.ReadDirRequest{Path: "."} - files := []*fsutil.Stat{ - {Path: "README.md"}, - } - suite.ref.EXPECT(). - ReadDir(suite.ctx, req). - Return(files, nil) - actual := errors.New("something went wrong") - walkFn := func(*fsutil.Stat) error { return actual } - - // Act - expected := WalkRecursive(suite.ctx, suite.ref, walkFn) - - // Assert - require.Same(suite.T(), expected, actual) -} - -func (suite *walkRecursiveTestSuite) TestNestedFails() { - // Arrange - req := client.ReadDirRequest{Path: "."} - files := []*fsutil.Stat{ - {Path: "vendor", Mode: uint32(os.ModeDir)}, - } - suite.ref.EXPECT(). - ReadDir(suite.ctx, req). - Return(files, nil) - req = client.ReadDirRequest{Path: "vendor"} - actual := errors.New("something went wrong") - suite.ref.EXPECT(). - ReadDir(suite.ctx, req). - Return(nil, actual) - - // Act - expected := WalkRecursive(suite.ctx, suite.ref, walkFnNoop) - - // Assert - require.Same(suite.T(), expected, actual) -} - -func (suite *walkRecursiveTestSuite) TestSucceeds() { - // Arrange - req := client.ReadDirRequest{Path: "."} - files := []*fsutil.Stat{} - suite.ref.EXPECT(). - ReadDir(suite.ctx, req). - Return(files, nil) - - // Act - err := WalkRecursive(suite.ctx, suite.ref, walkFnNoop) - - // Assert - require.Nil(suite.T(), err) -} - -func TestWalkRecursive(t *testing.T) { - suite.Run(t, new(walkRecursiveTestSuite)) -} - -type findCommandTestSuite struct { - suite.Suite - ctrl *gomock.Controller - ctx context.Context - ref *cib_mock.MockReference -} - -func (suite *findCommandTestSuite) SetupTest() { - suite.ctrl = gomock.NewController(suite.T()) - suite.ctx = context.Background() - suite.ref = cib_mock.NewMockReference(suite.ctrl) -} - -func (suite *findCommandTestSuite) TearDownTest() { - suite.ctrl.Finish() -} - -func (suite *findCommandTestSuite) TestNotFound() { - // Arrange - files := []*fsutil.Stat{} - suite.ref.EXPECT(). - ReadDir(suite.ctx, gomock.Any()). - Return(files, nil) - - // Act - cmd, err := FindCommand(suite.ctx, suite.ref) - - // Assert - require.Empty(suite.T(), cmd) - require.Same(suite.T(), ErrNoCommand, err) -} - -func (suite *findCommandTestSuite) TestIgnoresNonPrefix() { - // Arrange - files := []*fsutil.Stat{ - {Path: "README.md"}, - } - suite.ref.EXPECT(). - ReadDir(suite.ctx, gomock.Any()). - Return(files, nil) - - // Act - cmd, err := FindCommand(suite.ctx, suite.ref) - - // Assert - require.Empty(suite.T(), cmd) - require.Same(suite.T(), ErrNoCommand, err) -} - -func (suite *findCommandTestSuite) TestIgnoresDirs() { - // Arrange - files := []*fsutil.Stat{ - {Path: "usr/local/bin/data", Mode: uint32(os.ModeDir)}, - } - suite.ref.EXPECT(). - ReadDir(suite.ctx, gomock.Any()). - Return(files, nil) - suite.ref.EXPECT(). - ReadDir(suite.ctx, gomock.Any()). - Return([]*fsutil.Stat{}, nil) - - // Act - cmd, err := FindCommand(suite.ctx, suite.ref) - - // Assert - require.Empty(suite.T(), cmd) - require.Same(suite.T(), ErrNoCommand, err) -} - -func (suite *findCommandTestSuite) TestIgnoresNonExecutable() { - // Arrange - files := []*fsutil.Stat{ - {Path: "usr/local/bin/README.md"}, - } - suite.ref.EXPECT(). - ReadDir(suite.ctx, gomock.Any()). - Return(files, nil) - - // Act - cmd, err := FindCommand(suite.ctx, suite.ref) - - // Assert - require.Empty(suite.T(), cmd) - require.Same(suite.T(), ErrNoCommand, err) -} - -func (suite *findCommandTestSuite) TestMultipleCommands() { - // Arrange - files := []*fsutil.Stat{ - {Path: "usr/local/bin/hello1", Mode: 0755}, - {Path: "usr/local/bin/hello2", Mode: 0755}, - } - suite.ref.EXPECT(). - ReadDir(suite.ctx, gomock.Any()). - Return(files, nil) - - // Act - _, err := FindCommand(suite.ctx, suite.ref) - - // Assert - require.NotNil(suite.T(), err) - require.Contains(suite.T(), err.Error(), "multiple commands") - require.Contains(suite.T(), err.Error(), files[0].Path) -} - -func (suite *findCommandTestSuite) TestSucceeds() { - // Arrange - files := []*fsutil.Stat{ - {Path: "usr/local/bin/hello", Mode: 0755}, - } - suite.ref.EXPECT(). - ReadDir(suite.ctx, gomock.Any()). - Return(files, nil) - - // Act - cmd, err := FindCommand(suite.ctx, suite.ref) - - // Assert - require.Equal(suite.T(), "/usr/local/bin/hello", cmd) - require.Nil(suite.T(), err) -} - -func TestFindCommand(t *testing.T) { - suite.Run(t, new(findCommandTestSuite)) -} diff --git a/pkg/cib/mock/cib.go b/pkg/cib/mock/cib.go deleted file mode 100644 index 53ed846..0000000 --- a/pkg/cib/mock/cib.go +++ /dev/null @@ -1,243 +0,0 @@ -// Code generated by MockGen. DO NOT EDIT. -// Source: github.com/EricHripko/pack.yaml/pkg/cib (interfaces: Service) - -// Package cib_mock is a generated GoMock package. -package cib_mock - -import ( - gomock "github.com/golang/mock/gomock" - llb "github.com/moby/buildkit/client/llb" - dockerfile2llb "github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb" - client "github.com/moby/buildkit/frontend/gateway/client" - apicaps "github.com/moby/buildkit/util/apicaps" - v1 "github.com/opencontainers/image-spec/specs-go/v1" - reflect "reflect" -) - -// MockService is a mock of Service interface -type MockService struct { - ctrl *gomock.Controller - recorder *MockServiceMockRecorder -} - -// MockServiceMockRecorder is the mock recorder for MockService -type MockServiceMockRecorder struct { - mock *MockService -} - -// NewMockService creates a new mock instance -func NewMockService(ctrl *gomock.Controller) *MockService { - mock := &MockService{ctrl: ctrl} - mock.recorder = &MockServiceMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use -func (m *MockService) EXPECT() *MockServiceMockRecorder { - return m.recorder -} - -// FetchImageConfig mocks base method -func (m *MockService) FetchImageConfig(arg0 string, arg1 *v1.Platform) (dockerfile2llb.Image, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "FetchImageConfig", arg0, arg1) - ret0, _ := ret[0].(dockerfile2llb.Image) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// FetchImageConfig indicates an expected call of FetchImageConfig -func (mr *MockServiceMockRecorder) FetchImageConfig(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchImageConfig", reflect.TypeOf((*MockService)(nil).FetchImageConfig), arg0, arg1) -} - -// From mocks base method -func (m *MockService) From(arg0 string, arg1 *v1.Platform, arg2 string) (llb.State, *dockerfile2llb.Image, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "From", arg0, arg1, arg2) - ret0, _ := ret[0].(llb.State) - ret1, _ := ret[1].(*dockerfile2llb.Image) - ret2, _ := ret[2].(error) - return ret0, ret1, ret2 -} - -// From indicates an expected call of From -func (mr *MockServiceMockRecorder) From(arg0, arg1, arg2 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "From", reflect.TypeOf((*MockService)(nil).From), arg0, arg1, arg2) -} - -// GetBuildPlatform mocks base method -func (m *MockService) GetBuildPlatform() *v1.Platform { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetBuildPlatform") - ret0, _ := ret[0].(*v1.Platform) - return ret0 -} - -// GetBuildPlatform indicates an expected call of GetBuildPlatform -func (mr *MockServiceMockRecorder) GetBuildPlatform() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBuildPlatform", reflect.TypeOf((*MockService)(nil).GetBuildPlatform)) -} - -// GetCaps mocks base method -func (m *MockService) GetCaps() apicaps.CapSet { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetCaps") - ret0, _ := ret[0].(apicaps.CapSet) - return ret0 -} - -// GetCaps indicates an expected call of GetCaps -func (mr *MockServiceMockRecorder) GetCaps() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCaps", reflect.TypeOf((*MockService)(nil).GetCaps)) -} - -// GetExcludes mocks base method -func (m *MockService) GetExcludes() ([]string, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetExcludes") - ret0, _ := ret[0].([]string) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetExcludes indicates an expected call of GetExcludes -func (mr *MockServiceMockRecorder) GetExcludes() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetExcludes", reflect.TypeOf((*MockService)(nil).GetExcludes)) -} - -// GetIgnoreCache mocks base method -func (m *MockService) GetIgnoreCache() bool { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetIgnoreCache") - ret0, _ := ret[0].(bool) - return ret0 -} - -// GetIgnoreCache indicates an expected call of GetIgnoreCache -func (mr *MockServiceMockRecorder) GetIgnoreCache() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetIgnoreCache", reflect.TypeOf((*MockService)(nil).GetIgnoreCache)) -} - -// GetMarshalOpts mocks base method -func (m *MockService) GetMarshalOpts() []llb.ConstraintsOpt { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetMarshalOpts") - ret0, _ := ret[0].([]llb.ConstraintsOpt) - return ret0 -} - -// GetMarshalOpts indicates an expected call of GetMarshalOpts -func (mr *MockServiceMockRecorder) GetMarshalOpts() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMarshalOpts", reflect.TypeOf((*MockService)(nil).GetMarshalOpts)) -} - -// GetMetadata mocks base method -func (m *MockService) GetMetadata() ([]byte, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetMetadata") - ret0, _ := ret[0].([]byte) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetMetadata indicates an expected call of GetMetadata -func (mr *MockServiceMockRecorder) GetMetadata() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMetadata", reflect.TypeOf((*MockService)(nil).GetMetadata)) -} - -// GetMetadataFileName mocks base method -func (m *MockService) GetMetadataFileName() string { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetMetadataFileName") - ret0, _ := ret[0].(string) - return ret0 -} - -// GetMetadataFileName indicates an expected call of GetMetadataFileName -func (mr *MockServiceMockRecorder) GetMetadataFileName() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMetadataFileName", reflect.TypeOf((*MockService)(nil).GetMetadataFileName)) -} - -// GetOpts mocks base method -func (m *MockService) GetOpts() map[string]string { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetOpts") - ret0, _ := ret[0].(map[string]string) - return ret0 -} - -// GetOpts indicates an expected call of GetOpts -func (mr *MockServiceMockRecorder) GetOpts() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetOpts", reflect.TypeOf((*MockService)(nil).GetOpts)) -} - -// GetResolveMode mocks base method -func (m *MockService) GetResolveMode() (llb.ResolveMode, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetResolveMode") - ret0, _ := ret[0].(llb.ResolveMode) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetResolveMode indicates an expected call of GetResolveMode -func (mr *MockServiceMockRecorder) GetResolveMode() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetResolveMode", reflect.TypeOf((*MockService)(nil).GetResolveMode)) -} - -// GetTargetPlatforms mocks base method -func (m *MockService) GetTargetPlatforms() ([]*v1.Platform, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetTargetPlatforms") - ret0, _ := ret[0].([]*v1.Platform) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetTargetPlatforms indicates an expected call of GetTargetPlatforms -func (mr *MockServiceMockRecorder) GetTargetPlatforms() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTargetPlatforms", reflect.TypeOf((*MockService)(nil).GetTargetPlatforms)) -} - -// Src mocks base method -func (m *MockService) Src() (client.Reference, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Src") - ret0, _ := ret[0].(client.Reference) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// Src indicates an expected call of Src -func (mr *MockServiceMockRecorder) Src() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Src", reflect.TypeOf((*MockService)(nil).Src)) -} - -// SrcState mocks base method -func (m *MockService) SrcState() (llb.State, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SrcState") - ret0, _ := ret[0].(llb.State) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// SrcState indicates an expected call of SrcState -func (mr *MockServiceMockRecorder) SrcState() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SrcState", reflect.TypeOf((*MockService)(nil).SrcState)) -} diff --git a/pkg/cib/mock/client.go b/pkg/cib/mock/client.go deleted file mode 100644 index dcea68a..0000000 --- a/pkg/cib/mock/client.go +++ /dev/null @@ -1,196 +0,0 @@ -// Code generated by MockGen. DO NOT EDIT. -// Source: github.com/moby/buildkit/frontend/gateway/client (interfaces: Client,Reference) - -// Package cib_mock is a generated GoMock package. -package cib_mock - -import ( - context "context" - gomock "github.com/golang/mock/gomock" - llb "github.com/moby/buildkit/client/llb" - client "github.com/moby/buildkit/frontend/gateway/client" - digest "github.com/opencontainers/go-digest" - types "github.com/tonistiigi/fsutil/types" - reflect "reflect" -) - -// MockClient is a mock of Client interface -type MockClient struct { - ctrl *gomock.Controller - recorder *MockClientMockRecorder -} - -// MockClientMockRecorder is the mock recorder for MockClient -type MockClientMockRecorder struct { - mock *MockClient -} - -// NewMockClient creates a new mock instance -func NewMockClient(ctrl *gomock.Controller) *MockClient { - mock := &MockClient{ctrl: ctrl} - mock.recorder = &MockClientMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use -func (m *MockClient) EXPECT() *MockClientMockRecorder { - return m.recorder -} - -// BuildOpts mocks base method -func (m *MockClient) BuildOpts() client.BuildOpts { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "BuildOpts") - ret0, _ := ret[0].(client.BuildOpts) - return ret0 -} - -// BuildOpts indicates an expected call of BuildOpts -func (mr *MockClientMockRecorder) BuildOpts() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BuildOpts", reflect.TypeOf((*MockClient)(nil).BuildOpts)) -} - -// Inputs mocks base method -func (m *MockClient) Inputs(arg0 context.Context) (map[string]llb.State, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Inputs", arg0) - ret0, _ := ret[0].(map[string]llb.State) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// Inputs indicates an expected call of Inputs -func (mr *MockClientMockRecorder) Inputs(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Inputs", reflect.TypeOf((*MockClient)(nil).Inputs), arg0) -} - -// NewContainer mocks base method -func (m *MockClient) NewContainer(arg0 context.Context, arg1 client.NewContainerRequest) (client.Container, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "NewContainer", arg0, arg1) - ret0, _ := ret[0].(client.Container) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// NewContainer indicates an expected call of NewContainer -func (mr *MockClientMockRecorder) NewContainer(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewContainer", reflect.TypeOf((*MockClient)(nil).NewContainer), arg0, arg1) -} - -// ResolveImageConfig mocks base method -func (m *MockClient) ResolveImageConfig(arg0 context.Context, arg1 string, arg2 llb.ResolveImageConfigOpt) (digest.Digest, []byte, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ResolveImageConfig", arg0, arg1, arg2) - ret0, _ := ret[0].(digest.Digest) - ret1, _ := ret[1].([]byte) - ret2, _ := ret[2].(error) - return ret0, ret1, ret2 -} - -// ResolveImageConfig indicates an expected call of ResolveImageConfig -func (mr *MockClientMockRecorder) ResolveImageConfig(arg0, arg1, arg2 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ResolveImageConfig", reflect.TypeOf((*MockClient)(nil).ResolveImageConfig), arg0, arg1, arg2) -} - -// Solve mocks base method -func (m *MockClient) Solve(arg0 context.Context, arg1 client.SolveRequest) (*client.Result, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Solve", arg0, arg1) - ret0, _ := ret[0].(*client.Result) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// Solve indicates an expected call of Solve -func (mr *MockClientMockRecorder) Solve(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Solve", reflect.TypeOf((*MockClient)(nil).Solve), arg0, arg1) -} - -// MockReference is a mock of Reference interface -type MockReference struct { - ctrl *gomock.Controller - recorder *MockReferenceMockRecorder -} - -// MockReferenceMockRecorder is the mock recorder for MockReference -type MockReferenceMockRecorder struct { - mock *MockReference -} - -// NewMockReference creates a new mock instance -func NewMockReference(ctrl *gomock.Controller) *MockReference { - mock := &MockReference{ctrl: ctrl} - mock.recorder = &MockReferenceMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use -func (m *MockReference) EXPECT() *MockReferenceMockRecorder { - return m.recorder -} - -// ReadDir mocks base method -func (m *MockReference) ReadDir(arg0 context.Context, arg1 client.ReadDirRequest) ([]*types.Stat, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ReadDir", arg0, arg1) - ret0, _ := ret[0].([]*types.Stat) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// ReadDir indicates an expected call of ReadDir -func (mr *MockReferenceMockRecorder) ReadDir(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReadDir", reflect.TypeOf((*MockReference)(nil).ReadDir), arg0, arg1) -} - -// ReadFile mocks base method -func (m *MockReference) ReadFile(arg0 context.Context, arg1 client.ReadRequest) ([]byte, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ReadFile", arg0, arg1) - ret0, _ := ret[0].([]byte) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// ReadFile indicates an expected call of ReadFile -func (mr *MockReferenceMockRecorder) ReadFile(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReadFile", reflect.TypeOf((*MockReference)(nil).ReadFile), arg0, arg1) -} - -// StatFile mocks base method -func (m *MockReference) StatFile(arg0 context.Context, arg1 client.StatRequest) (*types.Stat, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "StatFile", arg0, arg1) - ret0, _ := ret[0].(*types.Stat) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// StatFile indicates an expected call of StatFile -func (mr *MockReferenceMockRecorder) StatFile(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StatFile", reflect.TypeOf((*MockReference)(nil).StatFile), arg0, arg1) -} - -// ToState mocks base method -func (m *MockReference) ToState() (llb.State, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ToState") - ret0, _ := ret[0].(llb.State) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// ToState indicates an expected call of ToState -func (mr *MockReferenceMockRecorder) ToState() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ToState", reflect.TypeOf((*MockReference)(nil).ToState)) -} diff --git a/pkg/cib/service.go b/pkg/cib/service.go deleted file mode 100644 index d3806c0..0000000 --- a/pkg/cib/service.go +++ /dev/null @@ -1,266 +0,0 @@ -package cib - -import ( - "bytes" - "context" - "encoding/json" - - "github.com/containerd/containerd/platforms" - "github.com/docker/distribution/reference" - "github.com/docker/docker/builder/dockerignore" - "github.com/moby/buildkit/client/llb" - dockerfile "github.com/moby/buildkit/frontend/dockerfile/builder" - "github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb" - "github.com/moby/buildkit/frontend/gateway/client" - "github.com/moby/buildkit/util/apicaps" - specs "github.com/opencontainers/image-spec/specs-go/v1" - "github.com/pkg/errors" -) - -type service struct { - // Context for actions. - ctx context.Context - // Client for dispatching low-level actions. - client client.Client - // Source code used for image build (build context). - src client.Reference - // Context of the metadata file. - metadata []byte - // Paths to exclude from the build context. - excludes []string -} - -// NewService creates an instance of container image building service. -func NewService(ctx context.Context, client client.Client) Service { - return &service{ctx, client, nil, nil, nil} -} - -func (s *service) initSrc() error { - // LLB - state := llb.Local(dockerfile.DefaultLocalNameContext, - llb.SessionID(s.client.BuildOpts().SessionID), - dockerfile2llb.WithInternalName("load context"), - ) - // Marshal - def, err := state.Marshal(s.ctx, s.GetMarshalOpts()...) - if err != nil { - return err - } - // Solve - res, err := s.client.Solve(s.ctx, client.SolveRequest{ - Definition: def.ToPB(), - }) - if err != nil { - return err - } - s.src, err = res.SingleRef() - return err -} - -func (s *service) Src() (ref client.Reference, err error) { - if s.src == nil { - err = s.initSrc() - } - ref = s.src - return -} - -func (s *service) SrcState() (state llb.State, err error) { - if s.src == nil { - err = s.initSrc() - } - if err == nil { - state, err = s.src.ToState() - } - return -} - -func (s *service) GetOpts() map[string]string { - return s.client.BuildOpts().Opts -} - -func (s *service) GetCaps() apicaps.CapSet { - return s.client.BuildOpts().LLBCaps -} - -func (s *service) GetMarshalOpts() []llb.ConstraintsOpt { - return []llb.ConstraintsOpt{llb.WithCaps(s.GetCaps())} -} - -func (s *service) GetResolveMode() (llb.ResolveMode, error) { - return parseResolveMode(s.GetOpts()[keyImageResolveMode]) -} - -func (s *service) GetMetadataFileName() string { - if name, ok := s.GetOpts()[keyFilename]; ok { - return name - } - return "pack.yaml" -} - -func (s *service) initMetadata() error { - filename := s.GetMetadataFileName() - - // LLB - state := llb.Local(dockerfile.DefaultLocalNameDockerfile, - llb.FollowPaths([]string{filename}), - llb.SessionID(s.client.BuildOpts().SessionID), - llb.SharedKeyHint(dockerfile.DefaultLocalNameDockerfile), - dockerfile2llb.WithInternalName("load build definition from "+filename), - ) - // Marshal - def, err := state.Marshal(s.ctx, s.GetMarshalOpts()...) - if err != nil { - return errors.Wrapf(err, "failed to marshal local source") - } - // Solve - res, err := s.client.Solve(s.ctx, client.SolveRequest{ - Definition: def.ToPB(), - }) - if err != nil { - return errors.Wrapf(err, "failed to resolve metadata") - } - ref, err := res.SingleRef() - if err != nil { - return err - } - // Read - s.metadata, err = ref.ReadFile(s.ctx, client.ReadRequest{ - Filename: filename, - }) - if err != nil { - return errors.Wrapf(err, "failed to read metadata") - } - return nil -} - -func (s *service) GetMetadata() (data []byte, err error) { - if s.metadata == nil { - err = s.initMetadata() - } - - data = s.metadata - return -} - -func (s *service) initExcludes() error { - // LLB - state := llb.Local(dockerfile.DefaultLocalNameContext, - llb.SessionID(s.client.BuildOpts().SessionID), - llb.FollowPaths([]string{dockerignoreFilename}), - llb.SharedKeyHint(dockerfile.DefaultLocalNameContext+"-"+dockerignoreFilename), - dockerfile2llb.WithInternalName("load "+dockerignoreFilename), - ) - // Marshal - def, err := state.Marshal(s.ctx, s.GetMarshalOpts()...) - if err != nil { - return err - } - // Solve - res, err := s.client.Solve(s.ctx, client.SolveRequest{ - Definition: def.ToPB(), - }) - if err != nil { - return errors.Wrapf(err, "failed to resolve excludes") - } - ref, err := res.SingleRef() - if err != nil { - return err - } - // Read - data, _ := ref.ReadFile(s.ctx, client.ReadRequest{ - Filename: dockerignoreFilename, - }) - if data == nil { - s.excludes = []string{} - } else { - excludes, err := dockerignore.ReadAll(bytes.NewBuffer(data)) - if excludes == nil || err != nil { - return errors.Wrap(err, "failed to parse dockerignore") - } - s.excludes = excludes - } - return nil -} - -func (s *service) GetExcludes() (excludes []string, err error) { - if s.excludes == nil { - err = s.initExcludes() - } - - excludes = s.excludes - return -} - -func (s *service) FetchImageConfig(name string, platform *specs.Platform) (img dockerfile2llb.Image, err error) { - resolveMode, err := s.GetResolveMode() - if err != nil { - return - } - - _, data, err := s.client.ResolveImageConfig(s.ctx, name, llb.ResolveImageConfigOpt{ - Platform: platform, - ResolveMode: resolveMode.String(), - LogName: "load metadata for " + name, - }) - if err != nil { - return - } - if err = json.Unmarshal(data, &img); err != nil { - return - } - img.Created = nil - return -} - -func (s *service) GetBuildPlatform() *specs.Platform { - platform := platforms.DefaultSpec() - if workers := s.client.BuildOpts().Workers; len(workers) > 0 && len(workers[0].Platforms) > 0 { - platform = workers[0].Platforms[0] - } - return &platform -} - -func (s *service) GetTargetPlatforms() (platforms []*specs.Platform, err error) { - if v := s.GetOpts()[keyTargetPlatform]; v != "" { - platforms, err = parsePlatforms(v) - if err != nil { - return - } - } else { - platforms = []*specs.Platform{s.GetBuildPlatform()} - } - return -} - -func (s *service) GetIgnoreCache() bool { - _, ignoreCache := s.GetOpts()[keyNoCache] - return ignoreCache -} - -func (s *service) From(base string, platform *specs.Platform, comment string) (llb.State, *dockerfile2llb.Image, error) { - // Parse - ref, err := reference.ParseNormalizedNamed(base) - if err != nil { - return llb.State{}, nil, err - } - base = reference.TagNameOnly(ref).String() - // Resolve - resolveMode, err := s.GetResolveMode() - if err != nil { - return llb.State{}, nil, err - } - // LLB - state := llb.Image(base, resolveMode, llb.Platform(*platform), llb.WithCustomName(comment)) - img, err := s.FetchImageConfig(base, platform) - // Initialise with environment - for _, env := range img.Config.Env { - k, v := parseKeyValue(env) - state = state.AddEnv(k, v) - } - // Initialise with user - if img.Config.User != "" { - state = state.User(img.Config.User) - } - return state, &img, err -} diff --git a/pkg/cib/service_test.go b/pkg/cib/service_test.go deleted file mode 100644 index 302462a..0000000 --- a/pkg/cib/service_test.go +++ /dev/null @@ -1,505 +0,0 @@ -package cib - -import ( - "context" - "errors" - "testing" - - cib_mock "github.com/EricHripko/pack.yaml/pkg/cib/mock" - - "github.com/golang/mock/gomock" - "github.com/moby/buildkit/client/llb" - "github.com/moby/buildkit/frontend/gateway/client" - "github.com/moby/buildkit/solver/pb" - "github.com/moby/buildkit/util/apicaps" - "github.com/opencontainers/go-digest" - specs "github.com/opencontainers/image-spec/specs-go/v1" - "github.com/stretchr/testify/require" - "github.com/stretchr/testify/suite" -) - -func TestNewServiceSucceeds(t *testing.T) { - // Act - build := NewService(context.Background(), nil) - - // Arrange - require.NotNil(t, build) -} - -type serviceTestSuite struct { - suite.Suite - ctrl *gomock.Controller - ctx context.Context - client *cib_mock.MockClient - build Service -} - -func (suite *serviceTestSuite) SetupTest() { - suite.ctrl = gomock.NewController(suite.T()) - suite.ctx = context.Background() - suite.client = cib_mock.NewMockClient(suite.ctrl) - suite.build = NewService(suite.ctx, suite.client) - - suite.client.EXPECT(). - BuildOpts(). - Return(client.BuildOpts{ - Opts: map[string]string{ - "key": "value", - keyImageResolveMode: pb.AttrImageResolveModePreferLocal, - }, - LLBCaps: apicaps.CapSet{}, - Workers: []client.WorkerInfo{ - {Platforms: []specs.Platform{ - { - Architecture: "amd64", - OS: "linux", - OSVersion: "0.0.0", - }, - }}, - }, - }). - AnyTimes() -} - -func (suite *serviceTestSuite) TearDownTest() { - suite.ctrl.Finish() -} - -func (suite *serviceTestSuite) TestSrcSolveFails() { - // Arrange - actual := errors.New("something went wrong") - suite.client.EXPECT(). - Solve(suite.ctx, gomock.Any()). - Return(nil, actual) - - // Act - _, expected := suite.build.Src() - - // Assert - require.Same(suite.T(), expected, actual) -} - -func (suite *serviceTestSuite) TestSrcSucceeds() { - // Arrange - expected := cib_mock.NewMockReference(suite.ctrl) - res := client.NewResult() - res.SetRef(expected) - suite.client.EXPECT(). - Solve(suite.ctx, gomock.Any()). - Return(res, nil) - - // Act - actual, err := suite.build.Src() - - // Assert - require.Nil(suite.T(), err) - require.Same(suite.T(), expected, actual) -} - -func (suite *serviceTestSuite) TestSrcState() { - // Arrange - ref := cib_mock.NewMockReference(suite.ctrl) - res := client.NewResult() - res.SetRef(ref) - suite.client.EXPECT(). - Solve(suite.ctx, gomock.Any()). - Return(res, nil) - - expected := llb.Local("test") - ref.EXPECT(). - ToState(). - Return(expected, nil) - - // Act - _, err := suite.build.SrcState() - - // Assert - require.Nil(suite.T(), err) -} - -func (suite *serviceTestSuite) TestGetOpts() { - // Act - opts := suite.build.GetOpts() - - // Assert - require.Contains(suite.T(), opts, "key") - require.Equal(suite.T(), opts["key"], "value") -} - -func (suite *serviceTestSuite) TestGetCaps() { - // Act - caps := suite.build.GetCaps() - - // Assert - require.Equal(suite.T(), apicaps.CapSet{}, caps) -} - -func (suite *serviceTestSuite) TestGetResolveMode() { - // Act - resolveMode, err := suite.build.GetResolveMode() - - // Assert - require.Nil(suite.T(), err) - require.Equal(suite.T(), llb.ResolveModePreferLocal, resolveMode) -} - -func (suite *serviceTestSuite) TestGetMetadataFileName() { - // Act - name := suite.build.GetMetadataFileName() - - // Assert - require.Equal(suite.T(), "pack.yaml", name) -} - -func (suite *serviceTestSuite) TestGetMetadataSolveFails() { - // Arrange - suite.client.EXPECT(). - Solve(suite.ctx, gomock.Any()). - Return(nil, errors.New("something went wrong")) - - // Act - _, err := suite.build.GetMetadata() - - // Assert - require.NotNil(suite.T(), err) - require.Contains(suite.T(), err.Error(), "something went wrong") -} - -func (suite *serviceTestSuite) TestGetMetadataRefFails() { - // Arrange - res := client.NewResult() - res.AddRef("test", cib_mock.NewMockReference(suite.ctrl)) - suite.client.EXPECT(). - Solve(suite.ctx, gomock.Any()). - Return(res, nil) - - // Act - _, err := suite.build.GetMetadata() - - // Assert - require.NotNil(suite.T(), err) -} - -func (suite *serviceTestSuite) TestGetMetadataReadFails() { - // Arrange - req := client.ReadRequest{Filename: "pack.yaml"} - ref := cib_mock.NewMockReference(suite.ctrl) - ref.EXPECT(). - ReadFile(suite.ctx, req). - Return(nil, errors.New("something went wrong")) - - res := client.NewResult() - res.SetRef(ref) - suite.client.EXPECT(). - Solve(suite.ctx, gomock.Any()). - Return(res, nil) - - // Act - _, err := suite.build.GetMetadata() - - // Assert - require.NotNil(suite.T(), err) - require.Contains(suite.T(), err.Error(), "something went wrong") -} - -func (suite *serviceTestSuite) TestGetMetadataSucceeds() { - // Arrange - expected := []byte("hello world") - req := client.ReadRequest{Filename: "pack.yaml"} - ref := cib_mock.NewMockReference(suite.ctrl) - ref.EXPECT(). - ReadFile(suite.ctx, req). - Return(expected, nil) - - res := client.NewResult() - res.SetRef(ref) - suite.client.EXPECT(). - Solve(suite.ctx, gomock.Any()). - Return(res, nil) - - // Act - actual, err := suite.build.GetMetadata() - - // Assert - require.Nil(suite.T(), err) - require.Equal(suite.T(), expected, actual) -} - -func (suite *serviceTestSuite) TestGetExcludesSolveFails() { - // Arrange - suite.client.EXPECT(). - Solve(suite.ctx, gomock.Any()). - Return(nil, errors.New("something went wrong")) - - // Act - _, err := suite.build.GetExcludes() - - // Assert - require.NotNil(suite.T(), err) - require.Contains(suite.T(), err.Error(), "something went wrong") -} - -func (suite *serviceTestSuite) TestGetExcludesRefFails() { - // Arrange - res := client.NewResult() - res.AddRef("test", cib_mock.NewMockReference(suite.ctrl)) - suite.client.EXPECT(). - Solve(suite.ctx, gomock.Any()). - Return(res, nil) - - // Act - _, err := suite.build.GetExcludes() - - // Assert - require.NotNil(suite.T(), err) -} - -func (suite *serviceTestSuite) TestGetExcludesReadFails() { - // Arrange - req := client.ReadRequest{Filename: ".dockerignore"} - ref := cib_mock.NewMockReference(suite.ctrl) - ref.EXPECT(). - ReadFile(suite.ctx, req). - Return(nil, errors.New("something went wrong")) - - res := client.NewResult() - res.SetRef(ref) - suite.client.EXPECT(). - Solve(suite.ctx, gomock.Any()). - Return(res, nil) - - // Act - excludes, err := suite.build.GetExcludes() - - // Assert - require.Nil(suite.T(), err) - require.Empty(suite.T(), excludes) -} - -func (suite *serviceTestSuite) TestGetExcludesSucceeds() { - // Arrange - data := []byte("vendor") - req := client.ReadRequest{Filename: ".dockerignore"} - ref := cib_mock.NewMockReference(suite.ctrl) - ref.EXPECT(). - ReadFile(suite.ctx, req). - Return(data, nil) - - res := client.NewResult() - res.SetRef(ref) - suite.client.EXPECT(). - Solve(suite.ctx, gomock.Any()). - Return(res, nil) - - // Act - excludes, err := suite.build.GetExcludes() - - // Assert - require.Nil(suite.T(), err) - require.Contains(suite.T(), excludes, "vendor") -} - -func (suite *serviceTestSuite) TestFetchImageConfigResolveFails() { - // Arrange - platform := &specs.Platform{} - opt := llb.ResolveImageConfigOpt{ - Platform: platform, - ResolveMode: "local", - LogName: "load metadata for fakeimage", - } - expected := errors.New("something went wrong") - suite.client.EXPECT(). - ResolveImageConfig(suite.ctx, "fakeimage", opt). - Return(digest.Digest("sha256:fake"), nil, expected) - - // Act - _, actual := suite.build.FetchImageConfig("fakeimage", platform) - - // Assert - require.Equal(suite.T(), expected, actual) -} - -func (suite *serviceTestSuite) TestFetchImageConfigUnmarshalFails() { - // Arrange - platform := &specs.Platform{} - opt := llb.ResolveImageConfigOpt{ - Platform: platform, - ResolveMode: "local", - LogName: "load metadata for fakeimage", - } - data := []byte("not json") - suite.client.EXPECT(). - ResolveImageConfig(suite.ctx, "fakeimage", opt). - Return(digest.Digest("sha256:fake"), data, nil) - - // Act - _, err := suite.build.FetchImageConfig("fakeimage", platform) - - // Assert - require.NotNil(suite.T(), err) -} - -func (suite *serviceTestSuite) TestFetchImageConfigSucceeds() { - // Arrange - platform := &specs.Platform{} - opt := llb.ResolveImageConfigOpt{ - Platform: platform, - ResolveMode: "local", - LogName: "load metadata for fakeimage", - } - data := []byte(`{"Architecture": "amd64"}`) - suite.client.EXPECT(). - ResolveImageConfig(suite.ctx, "fakeimage", opt). - Return(digest.Digest("sha256:fake"), data, nil) - - // Act - img, err := suite.build.FetchImageConfig("fakeimage", platform) - - // Assert - require.Nil(suite.T(), err) - require.Equal(suite.T(), "amd64", img.Architecture) -} - -func (suite *serviceTestSuite) TestGetBuildPlatform() { - // Act - platform := suite.build.GetBuildPlatform() - - // Assert - require.Contains(suite.T(), platform.Architecture, "amd64") - require.Equal(suite.T(), platform.OS, "linux") - require.Equal(suite.T(), platform.OSVersion, "0.0.0") -} - -func (suite *serviceTestSuite) TestGetTargetPlatformsImplicit() { - // Arrange - build := suite.build.GetBuildPlatform() - - // Act - targets, err := suite.build.GetTargetPlatforms() - - // Assert - require.Nil(suite.T(), err) - require.Len(suite.T(), targets, 1) - require.Equal(suite.T(), build, targets[0]) -} - -func (suite *serviceTestSuite) TestGetIgnoreCache() { - // Act - ignoreCache := suite.build.GetIgnoreCache() - - // Assert - require.False(suite.T(), ignoreCache) -} - -func (suite *serviceTestSuite) TestFromInvalidReference() { - // Arrange - platform := suite.build.GetBuildPlatform() - - // Act - _, _, err := suite.build.From("nope::nope", platform, "") - - // Assert - require.NotNil(suite.T(), err) -} - -func (suite *serviceTestSuite) TestFromSucceeds() { - // Arrange - expected := suite.build.GetBuildPlatform() - opt := llb.ResolveImageConfigOpt{ - Platform: expected, - ResolveMode: "local", - LogName: "load metadata for docker.io/library/fakeimage:latest", - } - data := []byte(`{"Config":{"User": "somebody","Env":["Key=Val"]}}`) - suite.client.EXPECT(). - ResolveImageConfig(suite.ctx, "docker.io/library/fakeimage:latest", opt). - Return(digest.Digest("sha256:fake"), data, nil) - - // Act - state, img, err := suite.build.From("fakeimage", expected, "") - - // Assert - require.Nil(suite.T(), err) - require.Equal(suite.T(), "somebody", img.Config.User) - require.Contains(suite.T(), img.Config.Env, "Key=Val") - - actual, err := state.GetPlatform(suite.ctx) - require.Nil(suite.T(), err) - require.Equal(suite.T(), expected.OS, actual.OS) - require.Equal(suite.T(), expected.Architecture, actual.Architecture) - - value, exists, err := state.GetEnv(suite.ctx, "Key") - require.True(suite.T(), exists) - require.Nil(suite.T(), err) - require.Equal(suite.T(), "Val", value) -} - -func TestService(t *testing.T) { - suite.Run(t, new(serviceTestSuite)) -} - -func TestGetMetadataFileNameCustom(t *testing.T) { - // Arrange - ctrl := gomock.NewController(t) - defer ctrl.Finish() - cli := cib_mock.NewMockClient(ctrl) - cli.EXPECT(). - BuildOpts(). - Return(client.BuildOpts{ - Opts: map[string]string{ - keyFilename: "custom.yaml", - }, - }) - build := NewService(context.Background(), cli) - - // Act - name := build.GetMetadataFileName() - - // Assert - require.Equal(t, "custom.yaml", name) -} - -func TestGetTargetPlatformsExplicitFails(t *testing.T) { - // Arrange - ctrl := gomock.NewController(t) - defer ctrl.Finish() - cli := cib_mock.NewMockClient(ctrl) - cli.EXPECT(). - BuildOpts(). - Return(client.BuildOpts{ - Opts: map[string]string{ - keyTargetPlatform: "vtx:cpu32", - }, - }) - build := NewService(context.Background(), cli) - - // Act - _, err := build.GetTargetPlatforms() - - // Assert - require.NotNil(t, err) -} - -func TestGetTargetPlatformsExplicitSucceeds(t *testing.T) { - // Arrange - ctrl := gomock.NewController(t) - defer ctrl.Finish() - cli := cib_mock.NewMockClient(ctrl) - cli.EXPECT(). - BuildOpts(). - Return(client.BuildOpts{ - Opts: map[string]string{ - keyTargetPlatform: "linux/amd64", - }, - }) - build := NewService(context.Background(), cli) - - // Act - platforms, err := build.GetTargetPlatforms() - - // Assert - require.Nil(t, err) - require.Len(t, platforms, 1) - require.Equal(t, platforms[0].Architecture, "amd64") - require.Equal(t, platforms[0].OS, "linux") -} diff --git a/pkg/cib/vendor.go b/pkg/cib/vendor.go deleted file mode 100644 index 115ae25..0000000 --- a/pkg/cib/vendor.go +++ /dev/null @@ -1,64 +0,0 @@ -package cib - -import ( - "strings" - - "github.com/containerd/containerd/platforms" - "github.com/moby/buildkit/client/llb" - "github.com/moby/buildkit/solver/pb" - specs "github.com/opencontainers/image-spec/specs-go/v1" - "github.com/pkg/errors" -) - -// Taken from https://github.com/moby/buildkit/blob/master/frontend/dockerfile/builder/build.go#L33 -// for compatibility - -const ( - dockerignoreFilename = ".dockerignore" - keyImageResolveMode = "image-resolve-mode" - keyFilename = "filename" - keyTargetPlatform = "platform" - keyNoCache = "no-cache" -) - -// Taken from https://github.com/moby/buildkit/blob/master/frontend/dockerfile/dockerfile2llb/convert.go#L1160 -// for compatibility - -func parseKeyValue(env string) (string, string) { - parts := strings.SplitN(env, "=", 2) - v := "" - if len(parts) > 1 { - v = parts[1] - } - - return parts[0], v -} - -// Taken from https://github.com/moby/buildkit/blob/master/frontend/dockerfile/builder/build.go -// for compatibility - -func parsePlatforms(v string) ([]*specs.Platform, error) { - var pp []*specs.Platform - for _, v := range strings.Split(v, ",") { - p, err := platforms.Parse(v) - if err != nil { - return nil, errors.Wrapf(err, "failed to parse target platform %s", v) - } - p = platforms.Normalize(p) - pp = append(pp, &p) - } - return pp, nil -} - -func parseResolveMode(v string) (llb.ResolveMode, error) { - switch v { - case pb.AttrImageResolveModeDefault, "": - return llb.ResolveModeDefault, nil - case pb.AttrImageResolveModeForcePull: - return llb.ResolveModeForcePull, nil - case pb.AttrImageResolveModePreferLocal: - return llb.ResolveModePreferLocal, nil - default: - return 0, errors.Errorf("invalid image-resolve-mode: %s", v) - } -} diff --git a/pkg/cib/config.go b/pkg/packer2llb/config/config.go similarity index 77% rename from pkg/cib/config.go rename to pkg/packer2llb/config/config.go index e64b8b2..b7648bf 100644 --- a/pkg/cib/config.go +++ b/pkg/packer2llb/config/config.go @@ -1,4 +1,4 @@ -package cib +package config import ( "github.com/mitchellh/mapstructure" @@ -20,8 +20,8 @@ type Config struct { Other map[string]interface{} `mapstructure:",remain"` } -// NewConfig returns an instance of configuration with pre-populated defaults. -func NewConfig() *Config { +// New returns an instance of configuration with pre-populated defaults. +func New() *Config { return &Config{ Debug: true, Entrypoint: []string{}, @@ -31,8 +31,8 @@ func NewConfig() *Config { } } -// ReadConfig parses the configuration provided into a structured format. -func ReadConfig(data []byte) (*Config, error) { +// Read the configuration provided into a structured format. +func Read(data []byte) (*Config, error) { // Decode YAML m := make(map[string]interface{}) if err := yaml.Unmarshal(data, m); err != nil { @@ -40,7 +40,7 @@ func ReadConfig(data []byte) (*Config, error) { } // Map - config := NewConfig() + config := New() err := mapstructure.Decode(m, config) return config, err } diff --git a/pkg/cib/config_test.go b/pkg/packer2llb/config/config_test.go similarity index 90% rename from pkg/cib/config_test.go rename to pkg/packer2llb/config/config_test.go index b4174ac..f10928f 100644 --- a/pkg/cib/config_test.go +++ b/pkg/packer2llb/config/config_test.go @@ -1,4 +1,4 @@ -package cib +package config import ( "testing" @@ -8,7 +8,7 @@ import ( func TestNewConfig(t *testing.T) { // Act - cfg := NewConfig() + cfg := New() // Assert require.True(t, cfg.Debug) @@ -30,7 +30,7 @@ go: `) // Act - cfg, err := ReadConfig(data) + cfg, err := Read(data) // Assert require.Nil(t, err) @@ -50,7 +50,7 @@ func TestReadConfig_InvalidYAML(t *testing.T) { data := []byte("!\"%!%") // Act - _, err := ReadConfig(data) + _, err := Read(data) // Assert require.Error(t, err) @@ -61,7 +61,7 @@ func TestReadConfig_InvalidTypes(t *testing.T) { data := []byte("debug: nope") // Act - _, err := ReadConfig(data) + _, err := Read(data) // Assert require.Error(t, err) diff --git a/pkg/packer2llb/mock/packer2llb.go b/pkg/packer2llb/mock/packer2llb.go index fb52ba0..fe2c11b 100644 --- a/pkg/packer2llb/mock/packer2llb.go +++ b/pkg/packer2llb/mock/packer2llb.go @@ -6,7 +6,8 @@ package packer2llb_mock import ( context "context" - cib "github.com/EricHripko/pack.yaml/pkg/cib" + cib "github.com/EricHripko/buildkit-fdk/pkg/cib" + config "github.com/EricHripko/pack.yaml/pkg/packer2llb/config" gomock "github.com/golang/mock/gomock" llb "github.com/moby/buildkit/client/llb" dockerfile2llb "github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb" @@ -55,7 +56,7 @@ func (mr *MockPluginMockRecorder) Build(arg0, arg1, arg2 interface{}) *gomock.Ca } // Detect mocks base method -func (m *MockPlugin) Detect(arg0 context.Context, arg1 client.Reference, arg2 *cib.Config) error { +func (m *MockPlugin) Detect(arg0 context.Context, arg1 client.Reference, arg2 *config.Config) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Detect", arg0, arg1, arg2) ret0, _ := ret[0].(error) diff --git a/pkg/packer2llb/packer2llb.go b/pkg/packer2llb/packer2llb.go index 533b817..7da1d0a 100644 --- a/pkg/packer2llb/packer2llb.go +++ b/pkg/packer2llb/packer2llb.go @@ -6,16 +6,20 @@ import ( "context" "errors" - "github.com/EricHripko/pack.yaml/pkg/cib" + "github.com/EricHripko/pack.yaml/pkg/packer2llb/config" + "github.com/EricHripko/buildkit-fdk/pkg/cib" "github.com/moby/buildkit/client/llb" "github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb" "github.com/moby/buildkit/frontend/gateway/client" specs "github.com/opencontainers/image-spec/specs-go/v1" ) +// DirInstall specifies the target path that the binaries will be installed in. +const DirInstall = "/usr/local/bin" + // Detect if any of active integrations can process this project. -func Detect(ctx context.Context, build cib.Service, config *cib.Config) (plugin Plugin, err error) { +func Detect(ctx context.Context, build cib.Service, config *config.Config) (plugin Plugin, err error) { src, err := build.Src() if err != nil { return @@ -42,7 +46,7 @@ func Detect(ctx context.Context, build cib.Service, config *cib.Config) (plugin type Plugin interface { // Detect if this plugin is compatible with the project (in which case // ErrActivate is returned). - Detect(ctx context.Context, src client.Reference, config *cib.Config) error + Detect(ctx context.Context, src client.Reference, config *config.Config) error // Build a container image for the project with this plugin. Build(ctx context.Context, platform *specs.Platform, build cib.Service) (*llb.State, *dockerfile2llb.Image, error) } diff --git a/pkg/packer2llb/packer2llb_test.go b/pkg/packer2llb/packer2llb_test.go index eb5cf0f..e62aa51 100644 --- a/pkg/packer2llb/packer2llb_test.go +++ b/pkg/packer2llb/packer2llb_test.go @@ -5,10 +5,10 @@ import ( "errors" "testing" - "github.com/EricHripko/pack.yaml/pkg/cib" - cib_mock "github.com/EricHripko/pack.yaml/pkg/cib/mock" + "github.com/EricHripko/pack.yaml/pkg/packer2llb/config" packer2llb_mock "github.com/EricHripko/pack.yaml/pkg/packer2llb/mock" + cib_mock "github.com/EricHripko/buildkit-fdk/pkg/cib/mock" "github.com/golang/mock/gomock" "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" @@ -46,7 +46,7 @@ func (suite *pluginTestSuite) TestRegister() { func (suite *pluginTestSuite) TestDetectSrcFails() { // Arrange - cfg := &cib.Config{} + cfg := &config.Config{} expected := errors.New("something went wrong") suite.build.EXPECT(). Src(). @@ -61,7 +61,7 @@ func (suite *pluginTestSuite) TestDetectSrcFails() { func (suite *pluginTestSuite) TestDetectFails() { // Arrange - cfg := &cib.Config{} + cfg := &config.Config{} src := cib_mock.NewMockReference(suite.ctrl) suite.build.EXPECT(). Src(). @@ -81,7 +81,7 @@ func (suite *pluginTestSuite) TestDetectFails() { func (suite *pluginTestSuite) TestDetectNotFound() { // Arrange - cfg := &cib.Config{} + cfg := &config.Config{} src := cib_mock.NewMockReference(suite.ctrl) suite.build.EXPECT(). Src(). @@ -101,7 +101,7 @@ func (suite *pluginTestSuite) TestDetectNotFound() { func (suite *pluginTestSuite) TestDetectSucceeds() { // Arrange - cfg := &cib.Config{} + cfg := &config.Config{} src := cib_mock.NewMockReference(suite.ctrl) suite.build.EXPECT(). Src(). diff --git a/pkg/plugins/golang/golang.go b/pkg/plugins/golang/golang.go index e543218..7ee50cd 100644 --- a/pkg/plugins/golang/golang.go +++ b/pkg/plugins/golang/golang.go @@ -6,10 +6,11 @@ import ( "regexp" "strings" - "github.com/EricHripko/pack.yaml/pkg/cib" "github.com/EricHripko/pack.yaml/pkg/packer2llb" - "github.com/mitchellh/mapstructure" + "github.com/EricHripko/pack.yaml/pkg/packer2llb/config" + "github.com/EricHripko/buildkit-fdk/pkg/cib" + "github.com/mitchellh/mapstructure" "github.com/moby/buildkit/client/llb" "github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb" "github.com/moby/buildkit/frontend/gateway/client" @@ -52,7 +53,7 @@ type Config struct { // Plugin for Go ecosystem. type Plugin struct { // General configuration supplied by the user. - config *cib.Config + config *config.Config // Configuration for the plugin. pluginConfig *Config // Name of the project. @@ -62,7 +63,7 @@ type Plugin struct { // NewPlugin creates a new Go plugin with correct defaults. func NewPlugin() *Plugin { return &Plugin{ - config: cib.NewConfig(), + config: config.New(), pluginConfig: &Config{ DependencyMode: DMUnknown, }, @@ -70,7 +71,7 @@ func NewPlugin() *Plugin { } // Detect if this is a Go project and identify the context. -func (p *Plugin) Detect(ctx context.Context, src client.Reference, config *cib.Config) error { +func (p *Plugin) Detect(ctx context.Context, src client.Reference, config *config.Config) error { // Save config p.config = config if other, ok := p.config.Other["go"]; ok { @@ -214,14 +215,14 @@ func (p *Plugin) Build(ctx context.Context, platform *specs.Platform, build cib. } // Install the application state = state.File( - llb.Mkdir(cib.DirInstall, 0755, llb.WithParents(true)), + llb.Mkdir(packer2llb.DirInstall, 0755, llb.WithParents(true)), llb.WithCustomName("Create output directory"), ) state = state.File( llb.Copy( buildState, dirInstall, - cib.DirInstall, + packer2llb.DirInstall, &llb.CopyInfo{CopyDirContentsOnly: true}, ), llb.WithCustomName("Install application(s)"), diff --git a/pkg/plugins/golang/golang_test.go b/pkg/plugins/golang/golang_test.go index f11f3eb..f2eb109 100644 --- a/pkg/plugins/golang/golang_test.go +++ b/pkg/plugins/golang/golang_test.go @@ -5,10 +5,10 @@ import ( "errors" "testing" - "github.com/EricHripko/pack.yaml/pkg/cib" - cib_mock "github.com/EricHripko/pack.yaml/pkg/cib/mock" "github.com/EricHripko/pack.yaml/pkg/packer2llb" + "github.com/EricHripko/pack.yaml/pkg/packer2llb/config" + cib_mock "github.com/EricHripko/buildkit-fdk/pkg/cib/mock" "github.com/golang/mock/gomock" "github.com/moby/buildkit/client/llb" "github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb" @@ -42,7 +42,7 @@ func (suite *golangTestSuite) TearDownTest() { func (suite *golangTestSuite) TestInvalidConfig() { // Arrange - cfg := cib.NewConfig() + cfg := config.New() cfg.Other["go"] = map[string]interface{}{ "tags": "tag1", } @@ -65,7 +65,7 @@ func (suite *golangTestSuite) TestDetectNotFound() { Return(files, nil) // Act - err := suite.plugin.Detect(suite.ctx, suite.src, cib.NewConfig()) + err := suite.plugin.Detect(suite.ctx, suite.src, config.New()) // Assert require.Nil(suite.T(), err) @@ -86,7 +86,7 @@ func (suite *golangTestSuite) TestDetectFoundGoSource() { Times(2) // Act - err := suite.plugin.Detect(suite.ctx, suite.src, cib.NewConfig()) + err := suite.plugin.Detect(suite.ctx, suite.src, config.New()) // Assert require.Same(suite.T(), ErrUnknownDep, err) @@ -104,7 +104,7 @@ func (suite *golangTestSuite) TestDetectGoModNotFound() { suite.src.EXPECT(). ReadFile(suite.ctx, gomock.Any()). Return(nil, errors.New("not found")) - cfg := cib.NewConfig() + cfg := config.New() cfg.Other["go"] = map[string]interface{}{ "dependencyMode": "modules", } @@ -133,7 +133,7 @@ func (suite *golangTestSuite) TestDetectGoModFails() { Times(3) // Act - err := suite.plugin.Detect(suite.ctx, suite.src, cib.NewConfig()) + err := suite.plugin.Detect(suite.ctx, suite.src, config.New()) // Assert require.NotNil(suite.T(), err) @@ -155,7 +155,7 @@ func (suite *golangTestSuite) TestDetectGoModIncomplete() { Times(3) // Act - err := suite.plugin.Detect(suite.ctx, suite.src, cib.NewConfig()) + err := suite.plugin.Detect(suite.ctx, suite.src, config.New()) // Assert require.Same(suite.T(), ErrModIncomplete, err) @@ -180,7 +180,7 @@ go 1.15 Return(goMod, nil). Times(3) tags := []string{"tag1", "tag2"} - cfg := cib.NewConfig() + cfg := config.New() cfg.Other["go"] = map[string]interface{}{ "tags": tags, }