diff --git a/go.mod b/go.mod index f697426bf11..06bb72fde5e 100644 --- a/go.mod +++ b/go.mod @@ -36,6 +36,7 @@ require ( github.com/aws/aws-sdk-go v1.25.33 // indirect github.com/blang/semver v3.5.1+incompatible github.com/bmatcuk/doublestar v1.2.2 + github.com/buildpacks/pack v0.6.0 github.com/creack/pty v1.1.9 // indirect github.com/docker/cli v0.0.0-20191212191748-ebca1413117a github.com/docker/distribution v2.7.1+incompatible @@ -69,8 +70,6 @@ require ( github.com/krishicks/yaml-patch v0.0.10 github.com/markbates/inflect v1.0.4 // indirect github.com/mattbaird/jsonpatch v0.0.0-20171005235357-81af80346b1a // indirect - github.com/mattn/go-colorable v0.1.4 // indirect - github.com/mattn/go-isatty v0.0.10 // indirect github.com/mitchellh/go-homedir v1.1.0 github.com/moby/buildkit v0.6.3 github.com/onsi/ginkgo v1.10.3 // indirect diff --git a/go.sum b/go.sum index 96314957d36..1efcede9ce1 100644 --- a/go.sum +++ b/go.sum @@ -13,22 +13,16 @@ cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg cloud.google.com/go v0.49.0 h1:CH+lkubJzcPYB1Ggupcq0+k8Ni2ILdG2lYjDIgavDBQ= cloud.google.com/go v0.49.0/go.mod h1:hGvAdzcWNbyuxS3nWhD7H2cIJxjRRTRLQVB0bdputVY= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.2.0 h1:5wdyDJgqmqlAqzIhN6hY9E2vqE9M545UVLU1rrSr/x4= cloud.google.com/go/bigquery v1.2.0/go.mod h1:Cqg1qaK3wRdys8sKlow0jIBVFwSTiHoFx5um4ujCpyE= -cloud.google.com/go/datastore v1.0.0 h1:Kt+gOPPp2LEPWp8CSfxhsM8ik9CcyE/gYu+0r+RnZvM= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/pubsub v1.0.1 h1:W9tAK3E57P75u0XLLR82LZyw8VpAnhmyTOxW9qzmyj8= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= cloud.google.com/go/storage v1.4.0 h1:KDdqY5VTXBTqpSbctVTt0mVvfanP6JZzNzLE0qNY100= cloud.google.com/go/storage v1.4.0/go.mod h1:ZusYJWlOshgSBGbt6K3GnB3MT3H1xs2id9+TCl4fDBA= -contrib.go.opencensus.io/exporter/prometheus v0.1.0 h1:SByaIoWwNgMdPSgl5sMqM2KDE5H/ukPWBRo314xiDvg= contrib.go.opencensus.io/exporter/prometheus v0.1.0/go.mod h1:cGFniUXGZlKRjzOyuZJ6mgB+PgBcCIa79kEKR8YCW+A= -contrib.go.opencensus.io/exporter/stackdriver v0.12.8 h1:iXI5hr7pUwMx0IwMphpKz5Q3If/G5JiWFVZ5MPPxP9E= contrib.go.opencensus.io/exporter/stackdriver v0.12.8/go.mod h1:XyyafDnFOsqoxHJgTFycKZMrRUrPThLh2iYTJF6uoO0= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/Azure/azure-sdk-for-go v19.1.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/azure-sdk-for-go v36.1.0+incompatible h1:smHlbChr/JDmsyUqELZXLs0YIgpXecIGdUibuc2983s= github.com/Azure/azure-sdk-for-go v36.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= @@ -41,11 +35,8 @@ github.com/Azure/go-autorest/autorest/adal v0.6.1-0.20190906230412-69b4126ece6b github.com/Azure/go-autorest/autorest/adal v0.6.1-0.20190906230412-69b4126ece6b/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc= github.com/Azure/go-autorest/autorest/date v0.2.1-0.20190906230412-69b4126ece6b h1:ZlCWQMu0oy+olcLYnRGErn1opwgFgh5vyL0K65oXKiA= github.com/Azure/go-autorest/autorest/date v0.2.1-0.20190906230412-69b4126ece6b/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g= -github.com/Azure/go-autorest/autorest/mocks v0.3.1-0.20190906230412-69b4126ece6b h1:vLvMiJlO7uZ3Kr0LM4WtT37CbeCgX1Nu0PS6hdqvS9w= github.com/Azure/go-autorest/autorest/mocks v0.3.1-0.20190906230412-69b4126ece6b/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM= -github.com/Azure/go-autorest/autorest/to v0.3.0 h1:zebkZaadz7+wIQYgC7GXaz3Wb28yKYfVkkBKwc38VF8= github.com/Azure/go-autorest/autorest/to v0.3.0/go.mod h1:MgwOyqaIuKdG4TL/2ywSsIWKAfJfgHDo8ObuUk3t5sA= -github.com/Azure/go-autorest/autorest/validation v0.2.0 h1:15vMO4y76dehZSq7pAaOLQxC6dZYsSrj2GQpflyM/L4= github.com/Azure/go-autorest/autorest/validation v0.2.0/go.mod h1:3EEqHnBxQGHXRYq3HT1WyXAvT7LLY3tl70hw6tQIbjI= github.com/Azure/go-autorest/logger v0.1.0 h1:ruG4BSDXONFRrZZJ2GUXDiUyVpayPmb1GnWeHDdaNKY= github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= @@ -57,6 +48,8 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd/go.mod h1:64YHyfSL2R96J44Nlwm39UHepQbyR5q10x7iYa1ks2E= github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= +github.com/Masterminds/semver v1.4.2 h1:WBLTQ37jOCzSLtXNdoo8bNM8876KhNqOKvrlGITgsTc= +github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= github.com/Microsoft/go-winio v0.4.13-0.20190408173621-84b4ab48a507/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= github.com/Microsoft/go-winio v0.4.14 h1:+hMXMk01us9KgxGb7ftKQt2Xpf5hH/yky+TDA+qxleU= @@ -64,29 +57,31 @@ github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jB github.com/Microsoft/hcsshim v0.8.5/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc= -github.com/Netflix/go-expect v0.0.0-20190729225929-0e00d9168667 h1:l2RCK7mjLhjfZRIcCXTVHI34l67IRtKASBjusViLzQ0= github.com/Netflix/go-expect v0.0.0-20190729225929-0e00d9168667/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc= +github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs= github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/antihax/optional v0.0.0-20180407024304-ca021399b1a6/go.mod h1:V8iCPQYkqmusNa815XgQio277wI47sdRh1dUOLdyC6Q= github.com/apache/thrift v0.0.0-20161221203622-b2a4d4ae21c7/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/apex/log v1.1.2-0.20190827100214-baa5455d1012 h1:r9k3B0K539tmbDOdyCIuz/6qtn8q+lp+qvEStcFUIdM= +github.com/apex/log v1.1.2-0.20190827100214-baa5455d1012/go.mod h1:Ls949n1HFtXfbDcjiTTFQqkVUrte0puoIBfO3SVgwOA= +github.com/aphistic/golf v0.0.0-20180712155816-02c07f170c5a/go.mod h1:3NqKYiepwy8kCu4PNA+aP7WUV72eXWJeP9/r3/K9aLE= +github.com/aphistic/sweet v0.2.0/go.mod h1:fWDlIh/isSE9n6EPsRmC0det+whmX6dJid3stzu0Xys= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/aws/aws-sdk-go v1.15.90/go.mod h1:es1KtYUFs7le0xQ3rOihkuoVD90z7D0fR2Qm4S00/gU= +github.com/aws/aws-sdk-go v1.20.6/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.23.20/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/aws/aws-sdk-go v1.25.33 h1:8muvpP+Bq5e0CDkM9PDZ6tN74fVUq5v3zSCRaZ93ykM= github.com/aws/aws-sdk-go v1.25.33/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U2H7sSsE2t6Kca0lfwTK8JdoNGS/yzM/4iH5I= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -96,7 +91,12 @@ github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdn github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/bmatcuk/doublestar v1.2.2 h1:oC24CykoSAB8zd7XgruHo33E0cHJf/WhQA/7BeXj+x0= github.com/bmatcuk/doublestar v1.2.2/go.mod h1:wiQtGV+rzVYxB7WIlirSN++5HPtPlXEo9MEoZQC/PmE= -github.com/census-instrumentation/opencensus-proto v0.2.1 h1:glEXhBS5PSLLv4IXzLA5yPRVX4bilULVyxxbrfOtDAk= +github.com/buildpacks/imgutil v0.0.0-20191212154113-dc184e0d403b h1:SDsB0hJtURA+5i5vIjLntzRNPEqdoz6q+0MShCWdctw= +github.com/buildpacks/imgutil v0.0.0-20191212154113-dc184e0d403b/go.mod h1:E3lXJcNXcRefJQAHW5rqboonet+jtOml4qImbJhYGAo= +github.com/buildpacks/lifecycle v0.5.1-0.20191217221752-3b74c943b7b3 h1:15zYyFmNbrtx5MmyVEKVgY2/eearqEqGJXLCjmvUo58= +github.com/buildpacks/lifecycle v0.5.1-0.20191217221752-3b74c943b7b3/go.mod h1:ZIuIs9B6tjAW4dthhltKVyEUlhRfFWWix9eqoInMGX4= +github.com/buildpacks/pack v0.6.0 h1:hOnUrwmFQp5OxxrEp6qIxWVtqjXypJ0g31JuKRUGrLU= +github.com/buildpacks/pack v0.6.0/go.mod h1:5YXVrPFdS9CAQWS5iOcMhk3ul5YCMw4EvZr2pIecO7A= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.1.0 h1:yTUvW7Vhb89inJ+8irsUqiWjh8iT6sQPZiQzI6ReGkA= github.com/cespare/xxhash/v2 v2.1.0/go.mod h1:dgIUBU3pDso/gPgZ1osOZ0iQf77oPR28Tjxl5dIMyVM= @@ -121,13 +121,14 @@ github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= -github.com/creack/pty v1.1.9 h1:uDmaGzcdjhF4i/plgjmEsriH11Y0o7RKapEf/LDaM3w= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/daviddengcn/go-colortext v0.0.0-20160507010035-511bcaf42ccd/go.mod h1:dv4zxwHi5C/8AeI+4gX4dCWOIvNi7I6JCSX0HvlKPgE= +github.com/dgodd/dockerdial v1.0.1 h1:6XixGQxeytsIdVsbI4y+EHuv8QcxxH6ySJZLkm3jk5o= +github.com/dgodd/dockerdial v1.0.1/go.mod h1:MJmK56eTylC3KU7DR6bc3k9jmbpURO8rDOsGbfj+c6o= github.com/dgrijalva/jwt-go v0.0.0-20160705203006-01aeca54ebda/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= @@ -135,6 +136,7 @@ github.com/docker/cli v0.0.0-20190321234815-f40f9c240ab0/go.mod h1:JLrzqnKDaYBop github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/cli v0.0.0-20191212191748-ebca1413117a h1:rgpgmLocRiSIM3zdtVgJcyvH7S2cSiIPtL7LvFY8K/0= github.com/docker/cli v0.0.0-20191212191748-ebca1413117a/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/distribution v0.0.0-20180327202408-83389a148052/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.6.0-rc.1.0.20180327202408-83389a148052+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug= @@ -151,20 +153,18 @@ github.com/docker/go-events v0.0.0-20170721190031-9461782956ad/go.mod h1:Uw6Uezg github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8= github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw= github.com/docker/go-units v0.3.1/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/libnetwork v0.8.0-dev.2.0.20190604151032-3c26b4e7495e/go.mod h1:93m0aTqz6z+g32wla4l4WxTrdtvBRmVzYRkYvasA5Z8= -github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 h1:UhxFibDNY/bfvqU5CAUmr9zpesgbU6SWc8/B4mflAE4= github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= github.com/docker/spdystream v0.0.0-20181023171402-6480d4af844c h1:ZfSZ3P3BedhKGUhzj7BQlPSU4OvT6tfOKe3DVHzOA7s= github.com/docker/spdystream v0.0.0-20181023171402-6480d4af844c/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= -github.com/elazarl/goproxy v0.0.0-20191011121108-aa519ddbe484 h1:pEtiCjIXx3RvGjlUJuCNxNOw0MNblyR9Wi+vJGBFh+8= github.com/elazarl/goproxy v0.0.0-20191011121108-aa519ddbe484/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM= github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8= -github.com/elazarl/goproxy/ext v0.0.0-20191011121108-aa519ddbe484 h1:aBgSK7SOjFeL1wfzfbIb/pkPpfRr6EP7b1Af4o/xkpU= github.com/elazarl/goproxy/ext v0.0.0-20191011121108-aa519ddbe484/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= @@ -178,15 +178,13 @@ github.com/evanphx/json-patch v4.5.0+incompatible h1:ouOWdg56aJriqS0huScTkVXPC5I github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4= github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc= -github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= -github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v0.0.0-20180820084758-c7ce16629ff4/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0= github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -209,7 +207,6 @@ github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/gobuffalo/envy v1.6.5/go.mod h1:N+GkhhZ/93bGZc6ZKhJLP6+m+tCNPKwgSpH9kaifseQ= -github.com/gobuffalo/envy v1.7.1 h1:OQl5ys5MBea7OGCdvPbBJWRgnhC/fGona6QKfvFeau8= github.com/gobuffalo/envy v1.7.1/go.mod h1:FurDp9+EDPE4aIUS3ZLyD+7/9fpx7YRt/ukY6jIHf0w= github.com/godbus/dbus v4.1.0+incompatible/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= github.com/gofrs/flock v0.7.0/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= @@ -218,6 +215,7 @@ github.com/gogo/protobuf v0.0.0-20171007142547-342cbe0a0415/go.mod h1:r8qH/GZQm5 github.com/gogo/protobuf v1.0.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= @@ -227,8 +225,10 @@ github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4er github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191027212112-611e8accdfc9 h1:uHTyIjqVhYRhLbJ8nIiOJHkEZZ+5YoOsAbD3sk82NiE= github.com/golang/groupcache v0.0.0-20191027212112-611e8accdfc9/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= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1 h1:qGJ6qTW+x6xX/my+8YUVl4WNpX9B7+/l2tRsHGZ7f2s= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= 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= @@ -246,6 +246,7 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-containerregistry v0.0.0-20191018211754-b77a90c667af/go.mod h1:9kIomAeXUmwhqeYS2zoEuQ0sc2GOVmNW7t3y9aNQL1o= github.com/google/go-containerregistry v0.0.0-20191218175032-34fb8ff33bed h1:0AwV9UBwwKPKrfpTYLOKr8ymevanUxrsSEkAo0uU9aA= github.com/google/go-containerregistry v0.0.0-20191218175032-34fb8ff33bed/go.mod h1:rodaC7jYStJ2mjR8Y+5a/jCzcRPFRH74KmqSnJC88co= github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY= @@ -256,7 +257,6 @@ github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSN github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= @@ -275,6 +275,8 @@ github.com/googleapis/gnostic v0.3.1/go.mod h1:on+2t9HRStVgn95RSsFWFz+6Q0Snyqv1a github.com/gophercloud/gophercloud v0.0.0-20190126172459-c818fa66e4c8/go.mod h1:3WdhXV3rUYy9p6AUW8d94kr+HS62Y4VL9mBnFxsD8q4= github.com/gophercloud/gophercloud v0.6.0 h1:Xb2lcqZtml1XjgYZxbeayEemq7ASbeTp09m36gQFpEU= github.com/gophercloud/gophercloud v0.6.0/go.mod h1:GICNByuaEBibcjmjvI7QvYJSZEbGkcYwAR7EZK2WMqM= +github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= +github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gotestyourself/gotestyourself v2.2.0+incompatible/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY= @@ -292,10 +294,12 @@ github.com/hashicorp/golang-lru v0.5.3 h1:YPkqC67at8FYaadspW/6uE0COsBxS2656RLEr8 github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/uuid v0.0.0-20160311170451-ebb0a03e909c/go.mod h1:fHzc09UnyJyqyW+bFuq864eh+wC7dj65aXmXLRe5to0= +github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d h1:kJCB4vdITiW1eC1vq2e6IsrXKrZit1bv/TDYFGMp4BQ= +github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= +github.com/heroku/color v0.0.6 h1:UTFFMrmMLFcL3OweqP1lAdp8i1y/9oHqkeHjQ/b/Ny0= +github.com/heroku/color v0.0.6/go.mod h1:ZBvOcx7cTF2QKOv4LbmoBtNl5uB17qWxGuzZrsi1wLU= github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174/go.mod h1:DqJ97dSdRW1W22yXSB90986pcOyQ7r45iio1KN2ez1A= -github.com/hinshun/vt10x v0.0.0-20180809195222-d55458df857c h1:kp3AxgXgDOmIJFR7bIwqFhwJ2qWar8tEQSE5XXhCfVk= github.com/hinshun/vt10x v0.0.0-20180809195222-d55458df857c/go.mod h1:DqJ97dSdRW1W22yXSB90986pcOyQ7r45iio1KN2ez1A= -github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.8 h1:CGgOkSJeqMRmt0D9XLWExdT4m4F1vd3FV3VPt+0VxkQ= @@ -308,12 +312,11 @@ github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOl github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= -github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/joefitzgerald/rainbow-reporter v0.1.0/go.mod h1:481CNgqmVHQZzdIbN52CupLJyoVwB10FQ/IQlF1pdL8= -github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/jpillora/backoff v0.0.0-20180909062703-3050d21c67d7/go.mod h1:2iMrUgbbvHEiQClaW2NsSzMyGHqN+rDFqY705q49KG0= github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v0.0.0-20180701071628-ab8a2e0c74be/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= @@ -330,19 +333,18 @@ github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNU github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd h1:Coekwdh0v2wtGp9Gmz1Ze3eVRAWJMLokvN3QjdzCHLY= github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/konsorten/go-windows-terminal-sequences v0.0.0-20180402223658-b729f2633dfe/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= -github.com/kr/pty v1.1.8 h1:AkaSdXYQOWeaO3neb8EM634ahkXXe3jYbVh/F9lq+GI= github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/krishicks/yaml-patch v0.0.10 h1:H4FcHpnNwVmw8u0MjPRjWyIXtco6zM2F78t+57oNM3E= github.com/krishicks/yaml-patch v0.0.10/go.mod h1:Sm5TchwZS6sm7RJoyg87tzxm2ZcKzdRE4Q7TjNhPrME= @@ -353,14 +355,16 @@ github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= -github.com/markbates/inflect v1.0.4 h1:5fh1gzTFhfae06u3hzHYO9xe3l3v3nW5Pwt3naLTP5g= github.com/markbates/inflect v1.0.4/go.mod h1:1fR9+pO2KHEO9ZRtto13gDwwZaAKstQzferVeWqbgNs= github.com/mattbaird/jsonpatch v0.0.0-20171005235357-81af80346b1a h1:+J2gw7Bw77w/fbK7wnNJJDKmw1IbWft2Ul5BzrG1Qm8= github.com/mattbaird/jsonpatch v0.0.0-20171005235357-81af80346b1a/go.mod h1:M1qoD/MqPgTZIk0EWKB38wE28ACRfVcn+cU08jyArI0= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= +github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.10 h1:qxFzApOv4WsAL965uUPIsXzAKCZxN2p9UqdhFS4ZW10= github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= @@ -374,6 +378,8 @@ github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrk github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4= github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= github.com/mitchellh/hashstructure v0.0.0-20170609045927-2bca23e0e452/go.mod h1:QjSHrPWS+BGUVBYkbTZWEnOh3G1DutKwClXU/ABz6AQ= +github.com/mitchellh/ioprogress v0.0.0-20180201004757-6a23b12fa88e h1:Qa6dnn8DlasdXRnacluu8HzPts0S1I9zvvUPDbBnXFI= +github.com/mitchellh/ioprogress v0.0.0-20180201004757-6a23b12fa88e/go.mod h1:waEya8ee1Ro/lgxpVhkJI4BVASzkm3UZqkx/cFJiYHM= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/moby/buildkit v0.6.3 h1:2eFVHDz1E9uyMsbquywvjPIZ0yHT58HWCcn0K9qavWM= github.com/moby/buildkit v0.6.3/go.mod h1:JKVImCzxztxvULr5P6ZiBfA/B2P+ZpR6UHxOXQn4KiU= @@ -395,7 +401,6 @@ github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.10.3 h1:OoxbjfXVZyod1fmWYhI7SEyaD8B00ynP3T+D5GiyHOY= github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v0.0.0-20190113212917-5533ce8a0da3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= @@ -452,16 +457,19 @@ github.com/rakyll/statik v0.1.6/go.mod h1:OEi9wJV/fMUAGx1eNjq75DKDsJVuEv1U0oYdX6 github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M= github.com/rjeczalik/notify v0.9.2 h1:MiTWrPj55mNDHEiIX5YUSKefw/+lCQVoAFmD6oQm5w8= github.com/rjeczalik/notify v0.9.2/go.mod h1:aErll2f0sUX9PXZnVNyeiObbmTlk5jnMoCa4QEjJeqM= +github.com/rogpeppe/fastuuid v1.1.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYeAmZ5ZIpBWTGllZSQnw97Dj+woV0toclVaRGI8pc= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.3.2 h1:XU784Pr0wdahMY2bYcyK6N1KuaRAdLtqD4qd8D18Bfs= github.com/rogpeppe/go-internal v1.3.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sclevine/spec v1.0.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24q7p+U= github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24q7p+U= +github.com/sclevine/spec v1.4.0 h1:z/Q9idDcay5m5irkZ28M7PtQM4aOISzOpj4bUPkDee8= +github.com/sclevine/spec v1.4.0/go.mod h1:LvpgJaFyvQzRvc1kaDs0bulYwzC70PbiYjC4QnFHkOM= github.com/segmentio/textio v1.2.0 h1:Ug4IkV3kh72juJbG8azoSBlgebIbUUxVNrfFcKHfTSQ= github.com/segmentio/textio v1.2.0/go.mod h1:+Rb7v0YVODP+tK5F7FD9TCkV7gOYx9IgLHWiqtvY8ag= github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= @@ -470,11 +478,15 @@ github.com/serialx/hashring v0.0.0-20190422032157-8b2912629002/go.mod h1:/yeG0My github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.0.3/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= +github.com/sirupsen/logrus v1.1.1/go.mod h1:zrgwTnHtNr00buQ1vSptGe8m1f/BbgsPukg8qsT7A+A= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.3.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +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= +github.com/smartystreets/gunit v1.0.0/go.mod h1:qwPWnhz6pn0NnRBP++URONOVyNkPyr4SauJk4cUOwJs= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= @@ -501,6 +513,10 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/tektoncd/pipeline v0.5.1-0.20190731183258-9d7e37e85bf8 h1:NftWnvqs4oGBatJExafxwZ/GzQa2+U3CZU4QKEcmWKA= github.com/tektoncd/pipeline v0.5.1-0.20190731183258-9d7e37e85bf8/go.mod h1:IZzJdiX9EqEMuUcgdnElozdYYRh0/ZRC+NKMLj1K3Yw= +github.com/tj/assert v0.0.0-20171129193455-018094318fb0/go.mod h1:mZ9/Rh9oLWpLLDRpvE+3b7gP/C2YyLFYxNmcLnPTMe0= +github.com/tj/go-elastic v0.0.0-20171221160941-36157cbbebc2/go.mod h1:WjeM0Oo1eNAjXGDx2yma7uG2XoyRZTq1uv3M/o7imD0= +github.com/tj/go-kinesis v0.0.0-20171128231115-08b17f58cb1b/go.mod h1:/yhzCV0xPfx6jb1bBgRFjl5lytqVqZXEaeqWP8lTEao= +github.com/tj/go-spin v1.1.0/go.mod h1:Mg1mzmePZm4dva8Qz60H2lHwmJ2loum4VIrLgVnKwh4= github.com/tonistiigi/fsutil v0.0.0-20190819224149-3d2716dd0a4d/go.mod h1:pzh7kdwkDRh+Bx8J30uqaKJ1M4QrSH/um8fcIXeM8rc= github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea/go.mod h1:WPnis/6cRcDZSUvVmezrxJPkiO87ThFYsoUiMwWNDJk= github.com/uber/jaeger-client-go v0.0.0-20180103221425-e02c85f9069e/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= @@ -518,14 +534,10 @@ go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.1/go.mod h1:Ap50jQcDJrx6rB6VgeeFPtuPIf3wMRvRfrfYDO6+BmA= go.opencensus.io v0.22.2 h1:75k/FF0Q2YM8QYo07VPddOLBslDt1MZOdEslOHvmzAs= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.uber.org/atomic v1.5.0 h1:OI5t8sDa1Or+q8AeE+yKeB/SDYioSHAgcVljj9JIETY= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= -go.uber.org/multierr v1.4.0 h1:f3WCSC2KzAcBXGATIxAB1E2XuCpNU255wNKZ505qi3E= go.uber.org/multierr v1.4.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= -go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= -go.uber.org/zap v1.12.0 h1:dySoUQPFBGj6xwjmBzageVL8jGi8uxc6bEmJQjA06bw= go.uber.org/zap v1.12.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181025213731-e84da0312774/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -533,6 +545,7 @@ golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -551,6 +564,7 @@ golang.org/x/exp v0.0.0-20191127035308-9964a5a80460 h1:zNL062UG4d0GC48Bhm+lEI9lT golang.org/x/exp v0.0.0-20191127035308-9964a5a80460/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -568,6 +582,7 @@ golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -608,6 +623,7 @@ golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180926160741-c2ed4eda69e7/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181025063200-d989b31c8746/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -642,6 +658,8 @@ golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -664,6 +682,7 @@ golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190920225731-5eefd052ad72/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191017205301-920acffc3e65/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191028194131-d78a1f2664a0/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -699,6 +718,7 @@ google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRn google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190508193815-b515fa19cec8/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= @@ -707,6 +727,7 @@ google.golang.org/genproto v0.0.0-20191028173616-919d9bdd9fe6/go.mod h1:n3cpQtvx google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20191216205247-b31c10ee225f h1:0RYv5T9ZdroAqqfM2taEB0nJrArv0X1JpIdgUmY4xg8= google.golang.org/genproto v0.0.0-20191216205247-b31c10ee225f/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -721,10 +742,8 @@ gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4 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= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= gopkg.in/inf.v0 v0.9.0/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= @@ -732,11 +751,9 @@ gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/src-d/go-billy.v4 v4.3.2 h1:0SQA1pRztfTFx2miS8sA97XvooFeNOmvUenF4o0EcVg= gopkg.in/src-d/go-billy.v4 v4.3.2/go.mod h1:nDjArDMp+XMs1aFAESLRjfGSgfvoYN0hDfzEk0GjC98= -gopkg.in/src-d/go-git-fixtures.v3 v3.5.0 h1:ivZFOIltbce2Mo8IjzUHAFoq/IylO9WHhNOAJK+LsJg= gopkg.in/src-d/go-git-fixtures.v3 v3.5.0/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g= gopkg.in/src-d/go-git.v4 v4.13.1 h1:SRtFyV8Kxc0UP7aCHcijOMQGPxHSmMOPrzulQWolkYE= gopkg.in/src-d/go-git.v4 v4.13.1/go.mod h1:nx5NYcxdKxq5fpltdHnPa2Exj4Sx0EclMWZQbYDu2z8= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= @@ -747,8 +764,8 @@ gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo= gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gotest.tools v2.1.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= -gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= +honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -773,13 +790,13 @@ k8s.io/klog v0.3.1/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v0.4.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8= k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= +k8s.io/kube-openapi v0.0.0-20180731170545-e3762e86a74c/go.mod h1:BXM9ceUBTj2QnfH2MK1odQs778ajze1RxcmP6S8RVVc= k8s.io/kube-openapi v0.0.0-20190228160746-b3a7cee44a30/go.mod h1:BXM9ceUBTj2QnfH2MK1odQs778ajze1RxcmP6S8RVVc= k8s.io/kube-openapi v0.0.0-20190816220812-743ec37842bf/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E= k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a h1:UcxjrRMyNx/i/y8G7kPvLyy7rfbeuf1PYyBf973pgyU= k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E= k8s.io/kubectl v0.0.0-20190831163037-3b58a944563f h1:rngzSSBHZ0ofTBvPu8HT9R+EMc3PKE9XUD9DrK+QdAM= k8s.io/kubectl v0.0.0-20190831163037-3b58a944563f/go.mod h1:/TM8X12sDkA1rdjpK4qMqSYiDZbicsgYIGjicJ6P4EU= -k8s.io/kubernetes v1.12.10 h1:Ev14jntgqMAlW1Dyk++0dU76+Wb2FJ9VwopYK1R78m4= k8s.io/kubernetes v1.12.10/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= k8s.io/metrics v0.0.0-20190831080339-bd7772846802/go.mod h1:98g4ghmWXz8M0qrhPme3ZnY3E/zPsSSbLlqOsw7WVa4= k8s.io/utils v0.0.0-20190221042446-c2654d5206da/go.mod h1:8k8uAuAQ0rXslZKaEWd0c3oVhZz7sSzSiPnVZayjIX0= diff --git a/pkg/skaffold/build/buildpacks/build_test.go b/pkg/skaffold/build/buildpacks/build_test.go index 4f437031e78..3f519c02463 100644 --- a/pkg/skaffold/build/buildpacks/build_test.go +++ b/pkg/skaffold/build/buildpacks/build_test.go @@ -18,22 +18,35 @@ package buildpacks import ( "context" + "io" "io/ioutil" "testing" + "github.com/buildpacks/pack" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/docker" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/latest" "github.com/GoogleContainerTools/skaffold/testutil" ) +type fakePack struct { + Opts pack.BuildOptions +} + +func (f *fakePack) runPack(_ context.Context, _ io.Writer, opts pack.BuildOptions) error { + f.Opts = opts + return nil +} + func TestBuild(t *testing.T) { tests := []struct { - description string - artifact *latest.BuildpackArtifact - tag string - api *testutil.FakeAPIClient - pushImages bool - shouldErr bool + description string + artifact *latest.BuildpackArtifact + tag string + api *testutil.FakeAPIClient + pushImages bool + shouldErr bool + expectedOptions *pack.BuildOptions }{ { description: "success", @@ -44,6 +57,14 @@ func TestBuild(t *testing.T) { }, tag: "img:tag", api: &testutil.FakeAPIClient{}, + expectedOptions: &pack.BuildOptions{ + AppPath: ".", + Builder: "my/builder", + RunImage: "my/run", + Env: map[string]string{}, + Image: "img:latest", + NoPull: true, + }, }, { description: "invalid ref", @@ -66,20 +87,14 @@ func TestBuild(t *testing.T) { }, tag: "img:tag", api: &testutil.FakeAPIClient{}, - }, - { - description: "force pull error", - artifact: &latest.BuildpackArtifact{ - Builder: "my/builder", - RunImage: "my/run", - ForcePull: true, - Dependencies: defaultBuildpackDependencies(), + expectedOptions: &pack.BuildOptions{ + AppPath: ".", + Builder: "my/builder", + RunImage: "my/run", + Env: map[string]string{}, + Image: "img:latest", + NoPull: false, }, - tag: "img:tag", - api: &testutil.FakeAPIClient{ - ErrImagePull: true, - }, - shouldErr: true, }, { description: "push error", @@ -111,6 +126,9 @@ func TestBuild(t *testing.T) { for _, test := range tests { testutil.Run(t, test.description, func(t *testutil.T) { t.NewTempDir().Touch("file").Chdir() + pack := &fakePack{} + t.Override(&runPackFunc, pack.runPack) + test.api. Add(test.artifact.Builder, "builderImageID"). Add(test.artifact.RunImage, "runImageID"). @@ -126,6 +144,9 @@ func TestBuild(t *testing.T) { }, test.tag) t.CheckError(test.shouldErr, err) + if test.expectedOptions != nil { + t.CheckDeepEqual(*test.expectedOptions, pack.Opts) + } }) } } diff --git a/pkg/skaffold/build/buildpacks/lifecycle.go b/pkg/skaffold/build/buildpacks/lifecycle.go index 9d1d4aa8d2b..15b4d3b641d 100644 --- a/pkg/skaffold/build/buildpacks/lifecycle.go +++ b/pkg/skaffold/build/buildpacks/lifecycle.go @@ -18,19 +18,21 @@ package buildpacks import ( "context" - "fmt" "io" - "path/filepath" - "time" + "strings" - "github.com/docker/docker/api/types/mount" + "github.com/buildpacks/pack" "github.com/pkg/errors" "github.com/sirupsen/logrus" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/build/misc" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/docker" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/latest" - "github.com/GoogleContainerTools/skaffold/pkg/skaffold/util" +) + +// For testing +var ( + runPackFunc = runPack ) func (b *Builder) build(ctx context.Context, out io.Writer, a *latest.Artifact, tag string) (string, error) { @@ -48,17 +50,25 @@ func (b *Builder) build(ctx context.Context, out io.Writer, a *latest.Artifact, builderImage := artifact.Builder logrus.Debugln("Builder image", builderImage) - if err := b.pull(ctx, out, builderImage, artifact.ForcePull); err != nil { - return "", err + if !artifact.ForcePull { + if err := b.pull(ctx, out, builderImage); err != nil { + return "", err + } } - runImage, err := b.findRunImage(ctx, artifact, builderImage) - if err != nil { - return "", err - } - logrus.Debugln("Run image", runImage) - if err := b.pull(ctx, out, runImage, artifact.ForcePull); err != nil { - return "", err + runImage := artifact.RunImage + if !artifact.ForcePull { + // If ForcePull is true, we let pack find and pull the run image + var err error + runImage, err = b.findRunImage(ctx, artifact, builderImage) + if err != nil { + return "", err + } + logrus.Debugln("Run image", runImage) + + if err := b.pull(ctx, out, runImage); err != nil { + return "", err + } } logrus.Debugln("Evaluate env variables") @@ -67,89 +77,44 @@ func (b *Builder) build(ctx context.Context, out io.Writer, a *latest.Artifact, return "", errors.Wrap(err, "unable to evaluate env variables") } - logrus.Debugln("Get dependencies") - deps, err := GetDependencies(ctx, workspace, artifact) - if err != nil { + if err := runPackFunc(ctx, out, pack.BuildOptions{ + AppPath: workspace, + Builder: builderImage, + RunImage: runImage, + Env: envMap(env), + Image: latest, + NoPull: !artifact.ForcePull, + }); err != nil { return "", err } - var paths []string - for _, dep := range deps { - paths = append(paths, filepath.Join(workspace, dep)) - } - - copyWorkspace := func(ctx context.Context, container string) error { - uid := 1000 - gid := 1000 - modTime := time.Date(1980, time.January, 1, 0, 0, 1, 0, time.UTC) + return latest, nil +} - return b.localDocker.CopyToContainer(ctx, container, "/workspace", workspace, paths, uid, gid, modTime) +func runPack(ctx context.Context, out io.Writer, opts pack.BuildOptions) error { + packClient, err := pack.NewClient(pack.WithLogger(NewLogger(out))) + if err != nil { + return errors.Wrap(err, "unable to create pack client") } - // These volumes store the state shared between build steps. - // After the build, they are deleted. - cacheID := util.RandomID() - packWorkspace := volume(mount.TypeVolume, fmt.Sprintf("pack-%s.workspace", cacheID), "/workspace") - layers := volume(mount.TypeVolume, fmt.Sprintf("pack-%s.layers", cacheID), "/layers") - - // These volumes are kept after the build and shared with all the builds. - // They handle the caching of layer both for build time and run time. - buildCache := volume(mount.TypeVolume, "pack-cache-skaffold.build", "/cache") - launchCache := volume(mount.TypeVolume, "pack-cache-skaffold.launch", "/launch-cache") + return packClient.Build(ctx, opts) +} - // Some steps need access to the Docker socket to load/save images. - dockerSocket := volume(mount.TypeBind, "/var/run/docker.sock", "/var/run/docker.sock") +func envMap(env []string) map[string]string { + kv := make(map[string]string) - defer func() { - // Don't use ctx. It might have been cancelled by Ctrl-C - if err := b.localDocker.VolumeRemove(context.Background(), packWorkspace.Source, true); err != nil { - logrus.Warnf("unable to delete the docker volume [%s]", packWorkspace.Source) - } - if err := b.localDocker.VolumeRemove(context.Background(), layers.Source, true); err != nil { - logrus.Warnf("unable to delete the docker volume [%s]", layers.Source) - } - }() - - if err := b.localDocker.ContainerRun(ctx, out, - docker.ContainerRun{ - Image: builderImage, - Command: []string{"/lifecycle/detector"}, - BeforeStart: copyWorkspace, - Mounts: []mount.Mount{packWorkspace, layers}, - Env: env, - }, docker.ContainerRun{ - Image: builderImage, - Command: []string{"sh", "-c", "/lifecycle/restorer -path /cache && /lifecycle/analyzer -daemon " + latest}, - User: "root", - Mounts: []mount.Mount{packWorkspace, layers, buildCache, dockerSocket}, - }, docker.ContainerRun{ - Image: builderImage, - Command: []string{"/lifecycle/builder"}, - Mounts: []mount.Mount{packWorkspace, layers}, - Env: env, - }, docker.ContainerRun{ - Image: builderImage, - Command: []string{"sh", "-c", "/lifecycle/exporter -daemon -image " + runImage + " -launch-cache /launch-cache " + latest + " && /lifecycle/cacher -path /cache"}, - User: "root", - Mounts: []mount.Mount{packWorkspace, layers, launchCache, buildCache, dockerSocket}, - }, - ); err != nil { - return "", err + for _, e := range env { + parts := strings.SplitN(e, "=", 2) + kv[parts[0]] = parts[1] } - return latest, nil -} - -func volume(mountType mount.Type, source, target string) mount.Mount { - return mount.Mount{Type: mountType, Source: source, Target: target} + return kv } // pull makes sure the given image is pre-pulled. -func (b *Builder) pull(ctx context.Context, out io.Writer, image string, force bool) error { - if force || !b.localDocker.ImageExists(ctx, image) { - if err := b.localDocker.Pull(ctx, out, image); err != nil { - return err - } +func (b *Builder) pull(ctx context.Context, out io.Writer, image string) error { + if b.localDocker.ImageExists(ctx, image) { + return nil } - return nil + return b.localDocker.Pull(ctx, out, image) } diff --git a/pkg/skaffold/build/buildpacks/logger.go b/pkg/skaffold/build/buildpacks/logger.go new file mode 100644 index 00000000000..f75dfdb136e --- /dev/null +++ b/pkg/skaffold/build/buildpacks/logger.go @@ -0,0 +1,61 @@ +/* +Copyright 2019 The Skaffold 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 buildpacks + +import ( + "io" + + "github.com/sirupsen/logrus" + + "github.com/buildpacks/pack/logging" +) + +type logger struct { + *logrus.Logger + out io.Writer +} + +func NewLogger(out io.Writer) logging.Logger { + return &logger{ + Logger: logrus.StandardLogger(), + out: out, + } +} + +func (l *logger) Debug(msg string) { + l.Logger.Debug(msg) +} + +func (l *logger) Info(msg string) { + l.Logger.Info(msg) +} + +func (l *logger) Warn(msg string) { + l.Logger.Warn(msg) +} + +func (l *logger) Error(msg string) { + l.Logger.Error(msg) +} + +func (l *logger) Writer() io.Writer { + return l.out +} + +func (l *logger) IsVerbose() bool { + return false +} diff --git a/pkg/skaffold/docker/containers.go b/pkg/skaffold/docker/containers.go deleted file mode 100644 index 9254d23ff42..00000000000 --- a/pkg/skaffold/docker/containers.go +++ /dev/null @@ -1,103 +0,0 @@ -/* -Copyright 2019 The Skaffold 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 docker - -import ( - "context" - "io" - "time" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/pkg/stdcopy" - - "github.com/GoogleContainerTools/skaffold/pkg/skaffold/util" -) - -// ContainerRun runs a list of containers in sequence, stopping on the first error. -// TODO: by properly interleaving calls to the Docker API, we could speed -// things up by roughly 700ms. -func (l *localDaemon) ContainerRun(ctx context.Context, out io.Writer, runs ...ContainerRun) error { - for _, run := range runs { - container, err := l.apiClient.ContainerCreate(ctx, &container.Config{ - Image: run.Image, - Cmd: run.Command, - User: run.User, - Env: run.Env, - }, &container.HostConfig{ - Mounts: run.Mounts, - }, nil, "") - if err != nil { - return err - } - - if run.BeforeStart != nil { - run.BeforeStart(ctx, container.ID) - } - - errRun := l.runAndLog(ctx, out, container.ID) - - // Don't use ctx. It might have been cancelled by Ctrl-C - if err := l.apiClient.ContainerRemove(context.Background(), container.ID, types.ContainerRemoveOptions{Force: true}); err != nil { - return err - } - - if errRun != nil { - return errRun - } - } - - return nil -} - -func (l *localDaemon) runAndLog(ctx context.Context, out io.Writer, containerID string) error { - if err := l.apiClient.ContainerStart(ctx, containerID, types.ContainerStartOptions{}); err != nil { - return err - } - - logs, err := l.apiClient.ContainerLogs(ctx, containerID, types.ContainerLogsOptions{ - ShowStdout: true, - ShowStderr: true, - Follow: true, - }) - if err != nil { - return err - } - defer logs.Close() - - _, err = stdcopy.StdCopy(out, out, logs) - return err -} - -// CopyToContainer copies files to a running container. -func (l *localDaemon) CopyToContainer(ctx context.Context, container string, dest string, root string, paths []string, uid, gid int, modTime time.Time) error { - r, w := io.Pipe() - go func() { - if err := util.CreateTarWithParents(w, root, paths, uid, gid, modTime); err != nil { - w.CloseWithError(err) - } else { - w.Close() - } - }() - - return l.apiClient.CopyToContainer(ctx, container, dest, r, types.CopyToContainerOptions{}) -} - -// VolumeRemove removes a volume. -func (l *localDaemon) VolumeRemove(ctx context.Context, volumeID string, force bool) error { - return l.apiClient.VolumeRemove(ctx, volumeID, force) -} diff --git a/pkg/skaffold/docker/image.go b/pkg/skaffold/docker/image.go index 7986c561174..21524756a40 100644 --- a/pkg/skaffold/docker/image.go +++ b/pkg/skaffold/docker/image.go @@ -24,7 +24,6 @@ import ( "sort" "strings" "sync" - "time" "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/mount" @@ -67,9 +66,6 @@ type LocalDaemon interface { ImageRemove(ctx context.Context, image string, opts types.ImageRemoveOptions) ([]types.ImageDeleteResponseItem, error) ImageExists(ctx context.Context, ref string) bool Prune(ctx context.Context, out io.Writer, images []string, pruneChildren bool) error - ContainerRun(ctx context.Context, out io.Writer, runs ...ContainerRun) error - CopyToContainer(ctx context.Context, container string, dest string, root string, paths []string, uid, gid int, modTime time.Time) error - VolumeRemove(ctx context.Context, volumeID string, force bool) error } type localDaemon struct { diff --git a/pkg/skaffold/util/tar.go b/pkg/skaffold/util/tar.go index 8df455319e0..bf14c8ede20 100644 --- a/pkg/skaffold/util/tar.go +++ b/pkg/skaffold/util/tar.go @@ -23,7 +23,6 @@ import ( "os" "path/filepath" "runtime" - "time" "github.com/pkg/errors" "github.com/sirupsen/logrus" @@ -59,40 +58,6 @@ func CreateTar(w io.Writer, root string, paths []string) error { return nil } -func CreateTarWithParents(w io.Writer, root string, paths []string, uid, gid int, modTime time.Time) error { - headerModifier := func(header *tar.Header) { - header.ModTime = modTime - header.Uid = uid - header.Gid = gid - header.Uname = "" - header.Gname = "" - } - - tw := tar.NewWriter(w) - defer tw.Close() - - // Make sure parent folders are added before files - // TODO(dgageot): this should probably also be done in CreateTar - // but I'd rather not break things that people didn't complain about! - added := map[string]bool{} - - for _, path := range paths { - var parentsFirst []string - for p := path; p != "." && !added[p]; p = filepath.Dir(p) { - parentsFirst = append(parentsFirst, p) - added[p] = true - } - - for i := len(parentsFirst) - 1; i >= 0; i-- { - if err := addFileToTar(root, parentsFirst[i], "", tw, headerModifier); err != nil { - return err - } - } - } - - return nil -} - func CreateTarGz(w io.Writer, root string, paths []string) error { gw := gzip.NewWriter(w) defer gw.Close() diff --git a/pkg/skaffold/util/tar_test.go b/pkg/skaffold/util/tar_test.go index 668f53e2317..948de738b28 100644 --- a/pkg/skaffold/util/tar_test.go +++ b/pkg/skaffold/util/tar_test.go @@ -24,7 +24,6 @@ import ( "io/ioutil" "runtime" "testing" - "time" "github.com/GoogleContainerTools/skaffold/testutil" ) @@ -62,46 +61,6 @@ func TestCreateTar(t *testing.T) { }) } -func TestCreateTarWithParents(t *testing.T) { - testutil.Run(t, "", func(t *testutil.T) { - files := map[string]string{ - "foo": "baz1", - "bar/bat": "baz2", - "bar/baz": "baz3", - } - _, paths := prepareFiles(t, files) - - var b bytes.Buffer - err := CreateTarWithParents(&b, ".", paths, 10, 100, time.Now()) - t.CheckNoError(err) - - // Make sure the contents match. - tarFiles := make(map[string]string) - tr := tar.NewReader(&b) - for { - hdr, err := tr.Next() - if err == io.EOF { - break - } - t.CheckNoError(err) - t.CheckDeepEqual(10, hdr.Uid) - t.CheckDeepEqual(100, hdr.Gid) - - content, err := ioutil.ReadAll(tr) - t.CheckNoError(err) - - tarFiles[hdr.Name] = string(content) - } - - t.CheckDeepEqual(map[string]string{ - "foo": "baz1", - "bar": "", - "bar/bat": "baz2", - "bar/baz": "baz3", - }, tarFiles) - }) -} - func TestCreateTarGz(t *testing.T) { testutil.Run(t, "", func(t *testutil.T) { files := map[string]string{ diff --git a/testutil/fake_image_api.go b/testutil/fake_image_api.go index 56244fc6e4f..8926a805fbd 100644 --- a/testutil/fake_image_api.go +++ b/testutil/fake_image_api.go @@ -23,19 +23,14 @@ import ( "io" "io/ioutil" "os" - "strconv" "strings" - "sync" "github.com/docker/docker/api/types" - containertypes "github.com/docker/docker/api/types/container" - networktypes "github.com/docker/docker/api/types/network" "github.com/docker/docker/api/types/registry" "github.com/docker/docker/client" reg "github.com/docker/docker/registry" digest "github.com/opencontainers/go-digest" v1 "github.com/opencontainers/image-spec/specs-go/v1" - "github.com/pkg/errors" ) type ContainerState int @@ -58,10 +53,6 @@ type FakeAPIClient struct { nextImageID int Pushed map[string]string Built []types.ImageBuildOptions - - nextContainerID int - containerStates map[string]ContainerState - containerLock sync.Mutex } func (f *FakeAPIClient) Add(tag, imageID string) *FakeAPIClient { @@ -210,93 +201,6 @@ func (f *FakeAPIClient) ImageLoad(ctx context.Context, input io.Reader, quiet bo }, nil } -func (f *FakeAPIClient) ContainerCreate(ctx context.Context, config *containertypes.Config, hostConfig *containertypes.HostConfig, networkingConfig *networktypes.NetworkingConfig, containerName string) (containertypes.ContainerCreateCreatedBody, error) { - f.containerLock.Lock() - defer f.containerLock.Unlock() - - f.nextContainerID++ - containerID := strconv.Itoa(f.nextContainerID) - - if f.containerStates == nil { - f.containerStates = make(map[string]ContainerState) - } - f.containerStates[containerID] = Created - - return containertypes.ContainerCreateCreatedBody{ - ID: containerID, - }, nil -} - -func (f *FakeAPIClient) ContainerStart(ctx context.Context, container string, options types.ContainerStartOptions) error { - f.containerLock.Lock() - defer f.containerLock.Unlock() - - state, present := f.containerStates[container] - if !present { - return errors.New("not found") - } - - if state == Started { - return errors.New("already started") - } - - f.containerStates[container] = Started - return nil -} - -func (f *FakeAPIClient) CopyToContainer(ctx context.Context, container, path string, content io.Reader, options types.CopyToContainerOptions) error { - f.containerLock.Lock() - defer f.containerLock.Unlock() - - state, present := f.containerStates[container] - if !present { - return errors.New("not found") - } - - if state != Started { - return errors.New("not started") - } - - return nil -} - -func (f *FakeAPIClient) ContainerLogs(ctx context.Context, container string, config types.ContainerLogsOptions) (io.ReadCloser, error) { - f.containerLock.Lock() - defer f.containerLock.Unlock() - - state, present := f.containerStates[container] - if !present { - return nil, errors.New("not found") - } - - if state != Started { - return nil, errors.New("not started") - } - - return ioutil.NopCloser(strings.NewReader("")), nil -} - -func (f *FakeAPIClient) ContainerRemove(ctx context.Context, container string, options types.ContainerRemoveOptions) error { - f.containerLock.Lock() - defer f.containerLock.Unlock() - - state, present := f.containerStates[container] - if !present { - return errors.New("not found") - } - - if state != Started { - return errors.New("not started") - } - - delete(f.containerStates, container) - return nil -} - -func (f *FakeAPIClient) VolumeRemove(ctx context.Context, volumeID string, force bool) error { - return nil -} - func (f *FakeAPIClient) Close() error { return nil } // TODO(dgageot): create something that looks more like an actual tar file. diff --git a/vendor/github.com/Masterminds/semver/.travis.yml b/vendor/github.com/Masterminds/semver/.travis.yml new file mode 100644 index 00000000000..3d9ebadb933 --- /dev/null +++ b/vendor/github.com/Masterminds/semver/.travis.yml @@ -0,0 +1,27 @@ +language: go + +go: + - 1.6.x + - 1.7.x + - 1.8.x + - 1.9.x + - 1.10.x + - tip + +# Setting sudo access to false will let Travis CI use containers rather than +# VMs to run the tests. For more details see: +# - http://docs.travis-ci.com/user/workers/container-based-infrastructure/ +# - http://docs.travis-ci.com/user/workers/standard-infrastructure/ +sudo: false + +script: + - make setup + - make test + +notifications: + webhooks: + urls: + - https://webhooks.gitter.im/e/06e3328629952dabe3e0 + on_success: change # options: [always|never|change] default: always + on_failure: always # options: [always|never|change] default: always + on_start: never # options: [always|never|change] default: always diff --git a/vendor/github.com/Masterminds/semver/CHANGELOG.md b/vendor/github.com/Masterminds/semver/CHANGELOG.md new file mode 100644 index 00000000000..b888e20abaa --- /dev/null +++ b/vendor/github.com/Masterminds/semver/CHANGELOG.md @@ -0,0 +1,86 @@ +# 1.4.2 (2018-04-10) + +## Changed +- #72: Updated the docs to point to vert for a console appliaction +- #71: Update the docs on pre-release comparator handling + +## Fixed +- #70: Fix the handling of pre-releases and the 0.0.0 release edge case + +# 1.4.1 (2018-04-02) + +## Fixed +- Fixed #64: Fix pre-release precedence issue (thanks @uudashr) + +# 1.4.0 (2017-10-04) + +## Changed +- #61: Update NewVersion to parse ints with a 64bit int size (thanks @zknill) + +# 1.3.1 (2017-07-10) + +## Fixed +- Fixed #57: number comparisons in prerelease sometimes inaccurate + +# 1.3.0 (2017-05-02) + +## Added +- #45: Added json (un)marshaling support (thanks @mh-cbon) +- Stability marker. See https://masterminds.github.io/stability/ + +## Fixed +- #51: Fix handling of single digit tilde constraint (thanks @dgodd) + +## Changed +- #55: The godoc icon moved from png to svg + +# 1.2.3 (2017-04-03) + +## Fixed +- #46: Fixed 0.x.x and 0.0.x in constraints being treated as * + +# Release 1.2.2 (2016-12-13) + +## Fixed +- #34: Fixed issue where hyphen range was not working with pre-release parsing. + +# Release 1.2.1 (2016-11-28) + +## Fixed +- #24: Fixed edge case issue where constraint "> 0" does not handle "0.0.1-alpha" + properly. + +# Release 1.2.0 (2016-11-04) + +## Added +- #20: Added MustParse function for versions (thanks @adamreese) +- #15: Added increment methods on versions (thanks @mh-cbon) + +## Fixed +- Issue #21: Per the SemVer spec (section 9) a pre-release is unstable and + might not satisfy the intended compatibility. The change here ignores pre-releases + on constraint checks (e.g., ~ or ^) when a pre-release is not part of the + constraint. For example, `^1.2.3` will ignore pre-releases while + `^1.2.3-alpha` will include them. + +# Release 1.1.1 (2016-06-30) + +## Changed +- Issue #9: Speed up version comparison performance (thanks @sdboyer) +- Issue #8: Added benchmarks (thanks @sdboyer) +- Updated Go Report Card URL to new location +- Updated Readme to add code snippet formatting (thanks @mh-cbon) +- Updating tagging to v[SemVer] structure for compatibility with other tools. + +# Release 1.1.0 (2016-03-11) + +- Issue #2: Implemented validation to provide reasons a versions failed a + constraint. + +# Release 1.0.1 (2015-12-31) + +- Fixed #1: * constraint failing on valid versions. + +# Release 1.0.0 (2015-10-20) + +- Initial release diff --git a/vendor/github.com/Masterminds/semver/LICENSE.txt b/vendor/github.com/Masterminds/semver/LICENSE.txt new file mode 100644 index 00000000000..0da4aeadb09 --- /dev/null +++ b/vendor/github.com/Masterminds/semver/LICENSE.txt @@ -0,0 +1,20 @@ +The Masterminds +Copyright (C) 2014-2015, Matt Butcher and Matt Farina + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/github.com/Masterminds/semver/Makefile b/vendor/github.com/Masterminds/semver/Makefile new file mode 100644 index 00000000000..a7a1b4e36de --- /dev/null +++ b/vendor/github.com/Masterminds/semver/Makefile @@ -0,0 +1,36 @@ +.PHONY: setup +setup: + go get -u gopkg.in/alecthomas/gometalinter.v1 + gometalinter.v1 --install + +.PHONY: test +test: validate lint + @echo "==> Running tests" + go test -v + +.PHONY: validate +validate: + @echo "==> Running static validations" + @gometalinter.v1 \ + --disable-all \ + --enable deadcode \ + --severity deadcode:error \ + --enable gofmt \ + --enable gosimple \ + --enable ineffassign \ + --enable misspell \ + --enable vet \ + --tests \ + --vendor \ + --deadline 60s \ + ./... || exit_code=1 + +.PHONY: lint +lint: + @echo "==> Running linters" + @gometalinter.v1 \ + --disable-all \ + --enable golint \ + --vendor \ + --deadline 60s \ + ./... || : diff --git a/vendor/github.com/Masterminds/semver/README.md b/vendor/github.com/Masterminds/semver/README.md new file mode 100644 index 00000000000..3e934ed71ec --- /dev/null +++ b/vendor/github.com/Masterminds/semver/README.md @@ -0,0 +1,165 @@ +# SemVer + +The `semver` package provides the ability to work with [Semantic Versions](http://semver.org) in Go. Specifically it provides the ability to: + +* Parse semantic versions +* Sort semantic versions +* Check if a semantic version fits within a set of constraints +* Optionally work with a `v` prefix + +[![Stability: +Active](https://masterminds.github.io/stability/active.svg)](https://masterminds.github.io/stability/active.html) +[![Build Status](https://travis-ci.org/Masterminds/semver.svg)](https://travis-ci.org/Masterminds/semver) [![Build status](https://ci.appveyor.com/api/projects/status/jfk66lib7hb985k8/branch/master?svg=true&passingText=windows%20build%20passing&failingText=windows%20build%20failing)](https://ci.appveyor.com/project/mattfarina/semver/branch/master) [![GoDoc](https://godoc.org/github.com/Masterminds/semver?status.svg)](https://godoc.org/github.com/Masterminds/semver) [![Go Report Card](https://goreportcard.com/badge/github.com/Masterminds/semver)](https://goreportcard.com/report/github.com/Masterminds/semver) + +## Parsing Semantic Versions + +To parse a semantic version use the `NewVersion` function. For example, + +```go + v, err := semver.NewVersion("1.2.3-beta.1+build345") +``` + +If there is an error the version wasn't parseable. The version object has methods +to get the parts of the version, compare it to other versions, convert the +version back into a string, and get the original string. For more details +please see the [documentation](https://godoc.org/github.com/Masterminds/semver). + +## Sorting Semantic Versions + +A set of versions can be sorted using the [`sort`](https://golang.org/pkg/sort/) +package from the standard library. For example, + +```go + raw := []string{"1.2.3", "1.0", "1.3", "2", "0.4.2",} + vs := make([]*semver.Version, len(raw)) + for i, r := range raw { + v, err := semver.NewVersion(r) + if err != nil { + t.Errorf("Error parsing version: %s", err) + } + + vs[i] = v + } + + sort.Sort(semver.Collection(vs)) +``` + +## Checking Version Constraints + +Checking a version against version constraints is one of the most featureful +parts of the package. + +```go + c, err := semver.NewConstraint(">= 1.2.3") + if err != nil { + // Handle constraint not being parseable. + } + + v, _ := semver.NewVersion("1.3") + if err != nil { + // Handle version not being parseable. + } + // Check if the version meets the constraints. The a variable will be true. + a := c.Check(v) +``` + +## Basic Comparisons + +There are two elements to the comparisons. First, a comparison string is a list +of comma separated and comparisons. These are then separated by || separated or +comparisons. For example, `">= 1.2, < 3.0.0 || >= 4.2.3"` is looking for a +comparison that's greater than or equal to 1.2 and less than 3.0.0 or is +greater than or equal to 4.2.3. + +The basic comparisons are: + +* `=`: equal (aliased to no operator) +* `!=`: not equal +* `>`: greater than +* `<`: less than +* `>=`: greater than or equal to +* `<=`: less than or equal to + +_Note, according to the Semantic Version specification pre-releases may not be +API compliant with their release counterpart. It says,_ + +> _A pre-release version indicates that the version is unstable and might not satisfy the intended compatibility requirements as denoted by its associated normal version._ + +_SemVer comparisons without a pre-release value will skip pre-release versions. +For example, `>1.2.3` will skip pre-releases when looking at a list of values +while `>1.2.3-alpha.1` will evaluate pre-releases._ + +## Hyphen Range Comparisons + +There are multiple methods to handle ranges and the first is hyphens ranges. +These look like: + +* `1.2 - 1.4.5` which is equivalent to `>= 1.2, <= 1.4.5` +* `2.3.4 - 4.5` which is equivalent to `>= 2.3.4, <= 4.5` + +## Wildcards In Comparisons + +The `x`, `X`, and `*` characters can be used as a wildcard character. This works +for all comparison operators. When used on the `=` operator it falls +back to the pack level comparison (see tilde below). For example, + +* `1.2.x` is equivalent to `>= 1.2.0, < 1.3.0` +* `>= 1.2.x` is equivalent to `>= 1.2.0` +* `<= 2.x` is equivalent to `<= 3` +* `*` is equivalent to `>= 0.0.0` + +## Tilde Range Comparisons (Patch) + +The tilde (`~`) comparison operator is for patch level ranges when a minor +version is specified and major level changes when the minor number is missing. +For example, + +* `~1.2.3` is equivalent to `>= 1.2.3, < 1.3.0` +* `~1` is equivalent to `>= 1, < 2` +* `~2.3` is equivalent to `>= 2.3, < 2.4` +* `~1.2.x` is equivalent to `>= 1.2.0, < 1.3.0` +* `~1.x` is equivalent to `>= 1, < 2` + +## Caret Range Comparisons (Major) + +The caret (`^`) comparison operator is for major level changes. This is useful +when comparisons of API versions as a major change is API breaking. For example, + +* `^1.2.3` is equivalent to `>= 1.2.3, < 2.0.0` +* `^1.2.x` is equivalent to `>= 1.2.0, < 2.0.0` +* `^2.3` is equivalent to `>= 2.3, < 3` +* `^2.x` is equivalent to `>= 2.0.0, < 3` + +# Validation + +In addition to testing a version against a constraint, a version can be validated +against a constraint. When validation fails a slice of errors containing why a +version didn't meet the constraint is returned. For example, + +```go + c, err := semver.NewConstraint("<= 1.2.3, >= 1.4") + if err != nil { + // Handle constraint not being parseable. + } + + v, _ := semver.NewVersion("1.3") + if err != nil { + // Handle version not being parseable. + } + + // Validate a version against a constraint. + a, msgs := c.Validate(v) + // a is false + for _, m := range msgs { + fmt.Println(m) + + // Loops over the errors which would read + // "1.3 is greater than 1.2.3" + // "1.3 is less than 1.4" + } +``` + +# Contribute + +If you find an issue or want to contribute please file an [issue](https://github.com/Masterminds/semver/issues) +or [create a pull request](https://github.com/Masterminds/semver/pulls). diff --git a/vendor/github.com/Masterminds/semver/appveyor.yml b/vendor/github.com/Masterminds/semver/appveyor.yml new file mode 100644 index 00000000000..b2778df15a4 --- /dev/null +++ b/vendor/github.com/Masterminds/semver/appveyor.yml @@ -0,0 +1,44 @@ +version: build-{build}.{branch} + +clone_folder: C:\gopath\src\github.com\Masterminds\semver +shallow_clone: true + +environment: + GOPATH: C:\gopath + +platform: + - x64 + +install: + - go version + - go env + - go get -u gopkg.in/alecthomas/gometalinter.v1 + - set PATH=%PATH%;%GOPATH%\bin + - gometalinter.v1.exe --install + +build_script: + - go install -v ./... + +test_script: + - "gometalinter.v1 \ + --disable-all \ + --enable deadcode \ + --severity deadcode:error \ + --enable gofmt \ + --enable gosimple \ + --enable ineffassign \ + --enable misspell \ + --enable vet \ + --tests \ + --vendor \ + --deadline 60s \ + ./... || exit_code=1" + - "gometalinter.v1 \ + --disable-all \ + --enable golint \ + --vendor \ + --deadline 60s \ + ./... || :" + - go test -v + +deploy: off diff --git a/vendor/github.com/Masterminds/semver/collection.go b/vendor/github.com/Masterminds/semver/collection.go new file mode 100644 index 00000000000..a78235895fd --- /dev/null +++ b/vendor/github.com/Masterminds/semver/collection.go @@ -0,0 +1,24 @@ +package semver + +// Collection is a collection of Version instances and implements the sort +// interface. See the sort package for more details. +// https://golang.org/pkg/sort/ +type Collection []*Version + +// Len returns the length of a collection. The number of Version instances +// on the slice. +func (c Collection) Len() int { + return len(c) +} + +// Less is needed for the sort interface to compare two Version objects on the +// slice. If checks if one is less than the other. +func (c Collection) Less(i, j int) bool { + return c[i].LessThan(c[j]) +} + +// Swap is needed for the sort interface to replace the Version objects +// at two different positions in the slice. +func (c Collection) Swap(i, j int) { + c[i], c[j] = c[j], c[i] +} diff --git a/vendor/github.com/Masterminds/semver/constraints.go b/vendor/github.com/Masterminds/semver/constraints.go new file mode 100644 index 00000000000..a41a6a7a4a8 --- /dev/null +++ b/vendor/github.com/Masterminds/semver/constraints.go @@ -0,0 +1,426 @@ +package semver + +import ( + "errors" + "fmt" + "regexp" + "strings" +) + +// Constraints is one or more constraint that a semantic version can be +// checked against. +type Constraints struct { + constraints [][]*constraint +} + +// NewConstraint returns a Constraints instance that a Version instance can +// be checked against. If there is a parse error it will be returned. +func NewConstraint(c string) (*Constraints, error) { + + // Rewrite - ranges into a comparison operation. + c = rewriteRange(c) + + ors := strings.Split(c, "||") + or := make([][]*constraint, len(ors)) + for k, v := range ors { + cs := strings.Split(v, ",") + result := make([]*constraint, len(cs)) + for i, s := range cs { + pc, err := parseConstraint(s) + if err != nil { + return nil, err + } + + result[i] = pc + } + or[k] = result + } + + o := &Constraints{constraints: or} + return o, nil +} + +// Check tests if a version satisfies the constraints. +func (cs Constraints) Check(v *Version) bool { + // loop over the ORs and check the inner ANDs + for _, o := range cs.constraints { + joy := true + for _, c := range o { + if !c.check(v) { + joy = false + break + } + } + + if joy { + return true + } + } + + return false +} + +// Validate checks if a version satisfies a constraint. If not a slice of +// reasons for the failure are returned in addition to a bool. +func (cs Constraints) Validate(v *Version) (bool, []error) { + // loop over the ORs and check the inner ANDs + var e []error + for _, o := range cs.constraints { + joy := true + for _, c := range o { + if !c.check(v) { + em := fmt.Errorf(c.msg, v, c.orig) + e = append(e, em) + joy = false + } + } + + if joy { + return true, []error{} + } + } + + return false, e +} + +var constraintOps map[string]cfunc +var constraintMsg map[string]string +var constraintRegex *regexp.Regexp + +func init() { + constraintOps = map[string]cfunc{ + "": constraintTildeOrEqual, + "=": constraintTildeOrEqual, + "!=": constraintNotEqual, + ">": constraintGreaterThan, + "<": constraintLessThan, + ">=": constraintGreaterThanEqual, + "=>": constraintGreaterThanEqual, + "<=": constraintLessThanEqual, + "=<": constraintLessThanEqual, + "~": constraintTilde, + "~>": constraintTilde, + "^": constraintCaret, + } + + constraintMsg = map[string]string{ + "": "%s is not equal to %s", + "=": "%s is not equal to %s", + "!=": "%s is equal to %s", + ">": "%s is less than or equal to %s", + "<": "%s is greater than or equal to %s", + ">=": "%s is less than %s", + "=>": "%s is less than %s", + "<=": "%s is greater than %s", + "=<": "%s is greater than %s", + "~": "%s does not have same major and minor version as %s", + "~>": "%s does not have same major and minor version as %s", + "^": "%s does not have same major version as %s", + } + + ops := make([]string, 0, len(constraintOps)) + for k := range constraintOps { + ops = append(ops, regexp.QuoteMeta(k)) + } + + constraintRegex = regexp.MustCompile(fmt.Sprintf( + `^\s*(%s)\s*(%s)\s*$`, + strings.Join(ops, "|"), + cvRegex)) + + constraintRangeRegex = regexp.MustCompile(fmt.Sprintf( + `\s*(%s)\s+-\s+(%s)\s*`, + cvRegex, cvRegex)) +} + +// An individual constraint +type constraint struct { + // The callback function for the restraint. It performs the logic for + // the constraint. + function cfunc + + msg string + + // The version used in the constraint check. For example, if a constraint + // is '<= 2.0.0' the con a version instance representing 2.0.0. + con *Version + + // The original parsed version (e.g., 4.x from != 4.x) + orig string + + // When an x is used as part of the version (e.g., 1.x) + minorDirty bool + dirty bool + patchDirty bool +} + +// Check if a version meets the constraint +func (c *constraint) check(v *Version) bool { + return c.function(v, c) +} + +type cfunc func(v *Version, c *constraint) bool + +func parseConstraint(c string) (*constraint, error) { + m := constraintRegex.FindStringSubmatch(c) + if m == nil { + return nil, fmt.Errorf("improper constraint: %s", c) + } + + ver := m[2] + orig := ver + minorDirty := false + patchDirty := false + dirty := false + if isX(m[3]) { + ver = "0.0.0" + dirty = true + } else if isX(strings.TrimPrefix(m[4], ".")) || m[4] == "" { + minorDirty = true + dirty = true + ver = fmt.Sprintf("%s.0.0%s", m[3], m[6]) + } else if isX(strings.TrimPrefix(m[5], ".")) { + dirty = true + patchDirty = true + ver = fmt.Sprintf("%s%s.0%s", m[3], m[4], m[6]) + } + + con, err := NewVersion(ver) + if err != nil { + + // The constraintRegex should catch any regex parsing errors. So, + // we should never get here. + return nil, errors.New("constraint Parser Error") + } + + cs := &constraint{ + function: constraintOps[m[1]], + msg: constraintMsg[m[1]], + con: con, + orig: orig, + minorDirty: minorDirty, + patchDirty: patchDirty, + dirty: dirty, + } + return cs, nil +} + +// Constraint functions +func constraintNotEqual(v *Version, c *constraint) bool { + if c.dirty { + + // If there is a pre-release on the version but the constraint isn't looking + // for them assume that pre-releases are not compatible. See issue 21 for + // more details. + if v.Prerelease() != "" && c.con.Prerelease() == "" { + return false + } + + if c.con.Major() != v.Major() { + return true + } + if c.con.Minor() != v.Minor() && !c.minorDirty { + return true + } else if c.minorDirty { + return false + } + + return false + } + + return !v.Equal(c.con) +} + +func constraintGreaterThan(v *Version, c *constraint) bool { + + // An edge case the constraint is 0.0.0 and the version is 0.0.0-someprerelease + // exists. This that case. + if !isNonZero(c.con) && isNonZero(v) { + return true + } + + // If there is a pre-release on the version but the constraint isn't looking + // for them assume that pre-releases are not compatible. See issue 21 for + // more details. + if v.Prerelease() != "" && c.con.Prerelease() == "" { + return false + } + + return v.Compare(c.con) == 1 +} + +func constraintLessThan(v *Version, c *constraint) bool { + // If there is a pre-release on the version but the constraint isn't looking + // for them assume that pre-releases are not compatible. See issue 21 for + // more details. + if v.Prerelease() != "" && c.con.Prerelease() == "" { + return false + } + + if !c.dirty { + return v.Compare(c.con) < 0 + } + + if v.Major() > c.con.Major() { + return false + } else if v.Minor() > c.con.Minor() && !c.minorDirty { + return false + } + + return true +} + +func constraintGreaterThanEqual(v *Version, c *constraint) bool { + // An edge case the constraint is 0.0.0 and the version is 0.0.0-someprerelease + // exists. This that case. + if !isNonZero(c.con) && isNonZero(v) { + return true + } + + // If there is a pre-release on the version but the constraint isn't looking + // for them assume that pre-releases are not compatible. See issue 21 for + // more details. + if v.Prerelease() != "" && c.con.Prerelease() == "" { + return false + } + + return v.Compare(c.con) >= 0 +} + +func constraintLessThanEqual(v *Version, c *constraint) bool { + // If there is a pre-release on the version but the constraint isn't looking + // for them assume that pre-releases are not compatible. See issue 21 for + // more details. + if v.Prerelease() != "" && c.con.Prerelease() == "" { + return false + } + + if !c.dirty { + return v.Compare(c.con) <= 0 + } + + if v.Major() > c.con.Major() { + return false + } else if v.Minor() > c.con.Minor() && !c.minorDirty { + return false + } + + return true +} + +// ~*, ~>* --> >= 0.0.0 (any) +// ~2, ~2.x, ~2.x.x, ~>2, ~>2.x ~>2.x.x --> >=2.0.0, <3.0.0 +// ~2.0, ~2.0.x, ~>2.0, ~>2.0.x --> >=2.0.0, <2.1.0 +// ~1.2, ~1.2.x, ~>1.2, ~>1.2.x --> >=1.2.0, <1.3.0 +// ~1.2.3, ~>1.2.3 --> >=1.2.3, <1.3.0 +// ~1.2.0, ~>1.2.0 --> >=1.2.0, <1.3.0 +func constraintTilde(v *Version, c *constraint) bool { + // If there is a pre-release on the version but the constraint isn't looking + // for them assume that pre-releases are not compatible. See issue 21 for + // more details. + if v.Prerelease() != "" && c.con.Prerelease() == "" { + return false + } + + if v.LessThan(c.con) { + return false + } + + // ~0.0.0 is a special case where all constraints are accepted. It's + // equivalent to >= 0.0.0. + if c.con.Major() == 0 && c.con.Minor() == 0 && c.con.Patch() == 0 && + !c.minorDirty && !c.patchDirty { + return true + } + + if v.Major() != c.con.Major() { + return false + } + + if v.Minor() != c.con.Minor() && !c.minorDirty { + return false + } + + return true +} + +// When there is a .x (dirty) status it automatically opts in to ~. Otherwise +// it's a straight = +func constraintTildeOrEqual(v *Version, c *constraint) bool { + // If there is a pre-release on the version but the constraint isn't looking + // for them assume that pre-releases are not compatible. See issue 21 for + // more details. + if v.Prerelease() != "" && c.con.Prerelease() == "" { + return false + } + + if c.dirty { + c.msg = constraintMsg["~"] + return constraintTilde(v, c) + } + + return v.Equal(c.con) +} + +// ^* --> (any) +// ^2, ^2.x, ^2.x.x --> >=2.0.0, <3.0.0 +// ^2.0, ^2.0.x --> >=2.0.0, <3.0.0 +// ^1.2, ^1.2.x --> >=1.2.0, <2.0.0 +// ^1.2.3 --> >=1.2.3, <2.0.0 +// ^1.2.0 --> >=1.2.0, <2.0.0 +func constraintCaret(v *Version, c *constraint) bool { + // If there is a pre-release on the version but the constraint isn't looking + // for them assume that pre-releases are not compatible. See issue 21 for + // more details. + if v.Prerelease() != "" && c.con.Prerelease() == "" { + return false + } + + if v.LessThan(c.con) { + return false + } + + if v.Major() != c.con.Major() { + return false + } + + return true +} + +var constraintRangeRegex *regexp.Regexp + +const cvRegex string = `v?([0-9|x|X|\*]+)(\.[0-9|x|X|\*]+)?(\.[0-9|x|X|\*]+)?` + + `(-([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?` + + `(\+([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?` + +func isX(x string) bool { + switch x { + case "x", "*", "X": + return true + default: + return false + } +} + +func rewriteRange(i string) string { + m := constraintRangeRegex.FindAllStringSubmatch(i, -1) + if m == nil { + return i + } + o := i + for _, v := range m { + t := fmt.Sprintf(">= %s, <= %s", v[1], v[11]) + o = strings.Replace(o, v[0], t, 1) + } + + return o +} + +// Detect if a version is not zero (0.0.0) +func isNonZero(v *Version) bool { + if v.Major() != 0 || v.Minor() != 0 || v.Patch() != 0 || v.Prerelease() != "" { + return true + } + + return false +} diff --git a/vendor/github.com/Masterminds/semver/doc.go b/vendor/github.com/Masterminds/semver/doc.go new file mode 100644 index 00000000000..e00f65eb73c --- /dev/null +++ b/vendor/github.com/Masterminds/semver/doc.go @@ -0,0 +1,115 @@ +/* +Package semver provides the ability to work with Semantic Versions (http://semver.org) in Go. + +Specifically it provides the ability to: + + * Parse semantic versions + * Sort semantic versions + * Check if a semantic version fits within a set of constraints + * Optionally work with a `v` prefix + +Parsing Semantic Versions + +To parse a semantic version use the `NewVersion` function. For example, + + v, err := semver.NewVersion("1.2.3-beta.1+build345") + +If there is an error the version wasn't parseable. The version object has methods +to get the parts of the version, compare it to other versions, convert the +version back into a string, and get the original string. For more details +please see the documentation at https://godoc.org/github.com/Masterminds/semver. + +Sorting Semantic Versions + +A set of versions can be sorted using the `sort` package from the standard library. +For example, + + raw := []string{"1.2.3", "1.0", "1.3", "2", "0.4.2",} + vs := make([]*semver.Version, len(raw)) + for i, r := range raw { + v, err := semver.NewVersion(r) + if err != nil { + t.Errorf("Error parsing version: %s", err) + } + + vs[i] = v + } + + sort.Sort(semver.Collection(vs)) + +Checking Version Constraints + +Checking a version against version constraints is one of the most featureful +parts of the package. + + c, err := semver.NewConstraint(">= 1.2.3") + if err != nil { + // Handle constraint not being parseable. + } + + v, _ := semver.NewVersion("1.3") + if err != nil { + // Handle version not being parseable. + } + // Check if the version meets the constraints. The a variable will be true. + a := c.Check(v) + +Basic Comparisons + +There are two elements to the comparisons. First, a comparison string is a list +of comma separated and comparisons. These are then separated by || separated or +comparisons. For example, `">= 1.2, < 3.0.0 || >= 4.2.3"` is looking for a +comparison that's greater than or equal to 1.2 and less than 3.0.0 or is +greater than or equal to 4.2.3. + +The basic comparisons are: + + * `=`: equal (aliased to no operator) + * `!=`: not equal + * `>`: greater than + * `<`: less than + * `>=`: greater than or equal to + * `<=`: less than or equal to + +Hyphen Range Comparisons + +There are multiple methods to handle ranges and the first is hyphens ranges. +These look like: + + * `1.2 - 1.4.5` which is equivalent to `>= 1.2, <= 1.4.5` + * `2.3.4 - 4.5` which is equivalent to `>= 2.3.4, <= 4.5` + +Wildcards In Comparisons + +The `x`, `X`, and `*` characters can be used as a wildcard character. This works +for all comparison operators. When used on the `=` operator it falls +back to the pack level comparison (see tilde below). For example, + + * `1.2.x` is equivalent to `>= 1.2.0, < 1.3.0` + * `>= 1.2.x` is equivalent to `>= 1.2.0` + * `<= 2.x` is equivalent to `<= 3` + * `*` is equivalent to `>= 0.0.0` + +Tilde Range Comparisons (Patch) + +The tilde (`~`) comparison operator is for patch level ranges when a minor +version is specified and major level changes when the minor number is missing. +For example, + + * `~1.2.3` is equivalent to `>= 1.2.3, < 1.3.0` + * `~1` is equivalent to `>= 1, < 2` + * `~2.3` is equivalent to `>= 2.3, < 2.4` + * `~1.2.x` is equivalent to `>= 1.2.0, < 1.3.0` + * `~1.x` is equivalent to `>= 1, < 2` + +Caret Range Comparisons (Major) + +The caret (`^`) comparison operator is for major level changes. This is useful +when comparisons of API versions as a major change is API breaking. For example, + + * `^1.2.3` is equivalent to `>= 1.2.3, < 2.0.0` + * `^1.2.x` is equivalent to `>= 1.2.0, < 2.0.0` + * `^2.3` is equivalent to `>= 2.3, < 3` + * `^2.x` is equivalent to `>= 2.0.0, < 3` +*/ +package semver diff --git a/vendor/github.com/Masterminds/semver/version.go b/vendor/github.com/Masterminds/semver/version.go new file mode 100644 index 00000000000..9d22ea6308d --- /dev/null +++ b/vendor/github.com/Masterminds/semver/version.go @@ -0,0 +1,421 @@ +package semver + +import ( + "bytes" + "encoding/json" + "errors" + "fmt" + "regexp" + "strconv" + "strings" +) + +// The compiled version of the regex created at init() is cached here so it +// only needs to be created once. +var versionRegex *regexp.Regexp +var validPrereleaseRegex *regexp.Regexp + +var ( + // ErrInvalidSemVer is returned a version is found to be invalid when + // being parsed. + ErrInvalidSemVer = errors.New("Invalid Semantic Version") + + // ErrInvalidMetadata is returned when the metadata is an invalid format + ErrInvalidMetadata = errors.New("Invalid Metadata string") + + // ErrInvalidPrerelease is returned when the pre-release is an invalid format + ErrInvalidPrerelease = errors.New("Invalid Prerelease string") +) + +// SemVerRegex is the regular expression used to parse a semantic version. +const SemVerRegex string = `v?([0-9]+)(\.[0-9]+)?(\.[0-9]+)?` + + `(-([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?` + + `(\+([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?` + +// ValidPrerelease is the regular expression which validates +// both prerelease and metadata values. +const ValidPrerelease string = `^([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*)` + +// Version represents a single semantic version. +type Version struct { + major, minor, patch int64 + pre string + metadata string + original string +} + +func init() { + versionRegex = regexp.MustCompile("^" + SemVerRegex + "$") + validPrereleaseRegex = regexp.MustCompile(ValidPrerelease) +} + +// NewVersion parses a given version and returns an instance of Version or +// an error if unable to parse the version. +func NewVersion(v string) (*Version, error) { + m := versionRegex.FindStringSubmatch(v) + if m == nil { + return nil, ErrInvalidSemVer + } + + sv := &Version{ + metadata: m[8], + pre: m[5], + original: v, + } + + var temp int64 + temp, err := strconv.ParseInt(m[1], 10, 64) + if err != nil { + return nil, fmt.Errorf("Error parsing version segment: %s", err) + } + sv.major = temp + + if m[2] != "" { + temp, err = strconv.ParseInt(strings.TrimPrefix(m[2], "."), 10, 64) + if err != nil { + return nil, fmt.Errorf("Error parsing version segment: %s", err) + } + sv.minor = temp + } else { + sv.minor = 0 + } + + if m[3] != "" { + temp, err = strconv.ParseInt(strings.TrimPrefix(m[3], "."), 10, 64) + if err != nil { + return nil, fmt.Errorf("Error parsing version segment: %s", err) + } + sv.patch = temp + } else { + sv.patch = 0 + } + + return sv, nil +} + +// MustParse parses a given version and panics on error. +func MustParse(v string) *Version { + sv, err := NewVersion(v) + if err != nil { + panic(err) + } + return sv +} + +// String converts a Version object to a string. +// Note, if the original version contained a leading v this version will not. +// See the Original() method to retrieve the original value. Semantic Versions +// don't contain a leading v per the spec. Instead it's optional on +// impelementation. +func (v *Version) String() string { + var buf bytes.Buffer + + fmt.Fprintf(&buf, "%d.%d.%d", v.major, v.minor, v.patch) + if v.pre != "" { + fmt.Fprintf(&buf, "-%s", v.pre) + } + if v.metadata != "" { + fmt.Fprintf(&buf, "+%s", v.metadata) + } + + return buf.String() +} + +// Original returns the original value passed in to be parsed. +func (v *Version) Original() string { + return v.original +} + +// Major returns the major version. +func (v *Version) Major() int64 { + return v.major +} + +// Minor returns the minor version. +func (v *Version) Minor() int64 { + return v.minor +} + +// Patch returns the patch version. +func (v *Version) Patch() int64 { + return v.patch +} + +// Prerelease returns the pre-release version. +func (v *Version) Prerelease() string { + return v.pre +} + +// Metadata returns the metadata on the version. +func (v *Version) Metadata() string { + return v.metadata +} + +// originalVPrefix returns the original 'v' prefix if any. +func (v *Version) originalVPrefix() string { + + // Note, only lowercase v is supported as a prefix by the parser. + if v.original != "" && v.original[:1] == "v" { + return v.original[:1] + } + return "" +} + +// IncPatch produces the next patch version. +// If the current version does not have prerelease/metadata information, +// it unsets metadata and prerelease values, increments patch number. +// If the current version has any of prerelease or metadata information, +// it unsets both values and keeps curent patch value +func (v Version) IncPatch() Version { + vNext := v + // according to http://semver.org/#spec-item-9 + // Pre-release versions have a lower precedence than the associated normal version. + // according to http://semver.org/#spec-item-10 + // Build metadata SHOULD be ignored when determining version precedence. + if v.pre != "" { + vNext.metadata = "" + vNext.pre = "" + } else { + vNext.metadata = "" + vNext.pre = "" + vNext.patch = v.patch + 1 + } + vNext.original = v.originalVPrefix() + "" + vNext.String() + return vNext +} + +// IncMinor produces the next minor version. +// Sets patch to 0. +// Increments minor number. +// Unsets metadata. +// Unsets prerelease status. +func (v Version) IncMinor() Version { + vNext := v + vNext.metadata = "" + vNext.pre = "" + vNext.patch = 0 + vNext.minor = v.minor + 1 + vNext.original = v.originalVPrefix() + "" + vNext.String() + return vNext +} + +// IncMajor produces the next major version. +// Sets patch to 0. +// Sets minor to 0. +// Increments major number. +// Unsets metadata. +// Unsets prerelease status. +func (v Version) IncMajor() Version { + vNext := v + vNext.metadata = "" + vNext.pre = "" + vNext.patch = 0 + vNext.minor = 0 + vNext.major = v.major + 1 + vNext.original = v.originalVPrefix() + "" + vNext.String() + return vNext +} + +// SetPrerelease defines the prerelease value. +// Value must not include the required 'hypen' prefix. +func (v Version) SetPrerelease(prerelease string) (Version, error) { + vNext := v + if len(prerelease) > 0 && !validPrereleaseRegex.MatchString(prerelease) { + return vNext, ErrInvalidPrerelease + } + vNext.pre = prerelease + vNext.original = v.originalVPrefix() + "" + vNext.String() + return vNext, nil +} + +// SetMetadata defines metadata value. +// Value must not include the required 'plus' prefix. +func (v Version) SetMetadata(metadata string) (Version, error) { + vNext := v + if len(metadata) > 0 && !validPrereleaseRegex.MatchString(metadata) { + return vNext, ErrInvalidMetadata + } + vNext.metadata = metadata + vNext.original = v.originalVPrefix() + "" + vNext.String() + return vNext, nil +} + +// LessThan tests if one version is less than another one. +func (v *Version) LessThan(o *Version) bool { + return v.Compare(o) < 0 +} + +// GreaterThan tests if one version is greater than another one. +func (v *Version) GreaterThan(o *Version) bool { + return v.Compare(o) > 0 +} + +// Equal tests if two versions are equal to each other. +// Note, versions can be equal with different metadata since metadata +// is not considered part of the comparable version. +func (v *Version) Equal(o *Version) bool { + return v.Compare(o) == 0 +} + +// Compare compares this version to another one. It returns -1, 0, or 1 if +// the version smaller, equal, or larger than the other version. +// +// Versions are compared by X.Y.Z. Build metadata is ignored. Prerelease is +// lower than the version without a prerelease. +func (v *Version) Compare(o *Version) int { + // Compare the major, minor, and patch version for differences. If a + // difference is found return the comparison. + if d := compareSegment(v.Major(), o.Major()); d != 0 { + return d + } + if d := compareSegment(v.Minor(), o.Minor()); d != 0 { + return d + } + if d := compareSegment(v.Patch(), o.Patch()); d != 0 { + return d + } + + // At this point the major, minor, and patch versions are the same. + ps := v.pre + po := o.Prerelease() + + if ps == "" && po == "" { + return 0 + } + if ps == "" { + return 1 + } + if po == "" { + return -1 + } + + return comparePrerelease(ps, po) +} + +// UnmarshalJSON implements JSON.Unmarshaler interface. +func (v *Version) UnmarshalJSON(b []byte) error { + var s string + if err := json.Unmarshal(b, &s); err != nil { + return err + } + temp, err := NewVersion(s) + if err != nil { + return err + } + v.major = temp.major + v.minor = temp.minor + v.patch = temp.patch + v.pre = temp.pre + v.metadata = temp.metadata + v.original = temp.original + temp = nil + return nil +} + +// MarshalJSON implements JSON.Marshaler interface. +func (v *Version) MarshalJSON() ([]byte, error) { + return json.Marshal(v.String()) +} + +func compareSegment(v, o int64) int { + if v < o { + return -1 + } + if v > o { + return 1 + } + + return 0 +} + +func comparePrerelease(v, o string) int { + + // split the prelease versions by their part. The separator, per the spec, + // is a . + sparts := strings.Split(v, ".") + oparts := strings.Split(o, ".") + + // Find the longer length of the parts to know how many loop iterations to + // go through. + slen := len(sparts) + olen := len(oparts) + + l := slen + if olen > slen { + l = olen + } + + // Iterate over each part of the prereleases to compare the differences. + for i := 0; i < l; i++ { + // Since the lentgh of the parts can be different we need to create + // a placeholder. This is to avoid out of bounds issues. + stemp := "" + if i < slen { + stemp = sparts[i] + } + + otemp := "" + if i < olen { + otemp = oparts[i] + } + + d := comparePrePart(stemp, otemp) + if d != 0 { + return d + } + } + + // Reaching here means two versions are of equal value but have different + // metadata (the part following a +). They are not identical in string form + // but the version comparison finds them to be equal. + return 0 +} + +func comparePrePart(s, o string) int { + // Fastpath if they are equal + if s == o { + return 0 + } + + // When s or o are empty we can use the other in an attempt to determine + // the response. + if s == "" { + if o != "" { + return -1 + } + return 1 + } + + if o == "" { + if s != "" { + return 1 + } + return -1 + } + + // When comparing strings "99" is greater than "103". To handle + // cases like this we need to detect numbers and compare them. + + oi, n1 := strconv.ParseInt(o, 10, 64) + si, n2 := strconv.ParseInt(s, 10, 64) + + // The case where both are strings compare the strings + if n1 != nil && n2 != nil { + if s > o { + return 1 + } + return -1 + } else if n1 != nil { + // o is a string and s is a number + return -1 + } else if n2 != nil { + // s is a string and o is a number + return 1 + } + // Both are numbers + if si > oi { + return 1 + } + return -1 + +} diff --git a/vendor/github.com/apex/log/.gitignore b/vendor/github.com/apex/log/.gitignore new file mode 100644 index 00000000000..7a6353d6737 --- /dev/null +++ b/vendor/github.com/apex/log/.gitignore @@ -0,0 +1 @@ +.envrc diff --git a/vendor/github.com/apex/log/History.md b/vendor/github.com/apex/log/History.md new file mode 100644 index 00000000000..c88be39eb97 --- /dev/null +++ b/vendor/github.com/apex/log/History.md @@ -0,0 +1,12 @@ + +v1.1.1 / 2019-06-24 +=================== + + * add go.mod + * add rough pass at apexlogs handler + +v1.1.0 / 2018-10-11 +=================== + + * fix: cli handler to show non-string fields appropriately + * fix: cli using fatih/color to better support windows diff --git a/vendor/github.com/apex/log/LICENSE b/vendor/github.com/apex/log/LICENSE new file mode 100644 index 00000000000..af718006842 --- /dev/null +++ b/vendor/github.com/apex/log/LICENSE @@ -0,0 +1,22 @@ +(The MIT License) + +Copyright (c) 2015 TJ Holowaychuk tj@tjholowaychuk.com + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/apex/log/Makefile b/vendor/github.com/apex/log/Makefile new file mode 100644 index 00000000000..f948e88ec12 --- /dev/null +++ b/vendor/github.com/apex/log/Makefile @@ -0,0 +1,2 @@ + +include github.com/tj/make/golang diff --git a/vendor/github.com/apex/log/Readme.md b/vendor/github.com/apex/log/Readme.md new file mode 100644 index 00000000000..4a48b6710dd --- /dev/null +++ b/vendor/github.com/apex/log/Readme.md @@ -0,0 +1,29 @@ + +![Structured logging for golang](assets/title.png) + +Package log implements a simple structured logging API inspired by Logrus, designed with centralization in mind. Read more on [Medium](https://medium.com/@tjholowaychuk/apex-log-e8d9627f4a9a#.rav8yhkud). + +## Handlers + +- __cli__ – human-friendly CLI output +- __discard__ – discards all logs +- __es__ – Elasticsearch handler +- __graylog__ – Graylog handler +- __json__ – JSON output handler +- __kinesis__ – AWS Kinesis handler +- __level__ – level filter handler +- __logfmt__ – logfmt plain-text formatter +- __memory__ – in-memory handler for tests +- __multi__ – fan-out to multiple handlers +- __papertrail__ – Papertrail handler +- __text__ – human-friendly colored output +- __delta__ – outputs the delta between log calls and spinner + +--- + +[![Build Status](https://semaphoreci.com/api/v1/projects/d8a8b1c0-45b0-4b89-b066-99d788d0b94c/642077/badge.svg)](https://semaphoreci.com/tj/log) +[![GoDoc](https://godoc.org/github.com/apex/log?status.svg)](https://godoc.org/github.com/apex/log) +![](https://img.shields.io/badge/license-MIT-blue.svg) +![](https://img.shields.io/badge/status-stable-green.svg) + + diff --git a/vendor/github.com/apex/log/default.go b/vendor/github.com/apex/log/default.go new file mode 100644 index 00000000000..22134862381 --- /dev/null +++ b/vendor/github.com/apex/log/default.go @@ -0,0 +1,45 @@ +package log + +import ( + "bytes" + "fmt" + "log" + "sort" +) + +// field used for sorting. +type field struct { + Name string + Value interface{} +} + +// by sorts fields by name. +type byName []field + +func (a byName) Len() int { return len(a) } +func (a byName) Swap(i, j int) { a[i], a[j] = a[j], a[i] } +func (a byName) Less(i, j int) bool { return a[i].Name < a[j].Name } + +// handleStdLog outpouts to the stlib log. +func handleStdLog(e *Entry) error { + level := levelNames[e.Level] + + var fields []field + + for k, v := range e.Fields { + fields = append(fields, field{k, v}) + } + + sort.Sort(byName(fields)) + + var b bytes.Buffer + fmt.Fprintf(&b, "%5s %-25s", level, e.Message) + + for _, f := range fields { + fmt.Fprintf(&b, " %s=%v", f.Name, f.Value) + } + + log.Println(b.String()) + + return nil +} diff --git a/vendor/github.com/apex/log/doc.go b/vendor/github.com/apex/log/doc.go new file mode 100644 index 00000000000..0331e8e163e --- /dev/null +++ b/vendor/github.com/apex/log/doc.go @@ -0,0 +1,10 @@ +/* +Package log implements a simple structured logging API designed with few assumptions. Designed for +centralized logging solutions such as Kinesis which require encoding and decoding before fanning-out +to handlers. + +You may use this package with inline handlers, much like Logrus, however a centralized solution +is recommended so that apps do not need to be re-deployed to add or remove logging service +providers. +*/ +package log diff --git a/vendor/github.com/apex/log/entry.go b/vendor/github.com/apex/log/entry.go new file mode 100644 index 00000000000..9f0a5e1fdaf --- /dev/null +++ b/vendor/github.com/apex/log/entry.go @@ -0,0 +1,172 @@ +package log + +import ( + "fmt" + "os" + "strings" + "time" +) + +// assert interface compliance. +var _ Interface = (*Entry)(nil) + +// Now returns the current time. +var Now = time.Now + +// Entry represents a single log entry. +type Entry struct { + Logger *Logger `json:"-"` + Fields Fields `json:"fields"` + Level Level `json:"level"` + Timestamp time.Time `json:"timestamp"` + Message string `json:"message"` + start time.Time + fields []Fields +} + +// NewEntry returns a new entry for `log`. +func NewEntry(log *Logger) *Entry { + return &Entry{ + Logger: log, + } +} + +// WithFields returns a new entry with `fields` set. +func (e *Entry) WithFields(fields Fielder) *Entry { + f := []Fields{} + f = append(f, e.fields...) + f = append(f, fields.Fields()) + return &Entry{ + Logger: e.Logger, + fields: f, + } +} + +// WithField returns a new entry with the `key` and `value` set. +func (e *Entry) WithField(key string, value interface{}) *Entry { + return e.WithFields(Fields{key: value}) +} + +// WithError returns a new entry with the "error" set to `err`. +// +// The given error may implement .Fielder, if it does the method +// will add all its `.Fields()` into the returned entry. +func (e *Entry) WithError(err error) *Entry { + ctx := e.WithField("error", err.Error()) + + if s, ok := err.(stackTracer); ok { + frame := s.StackTrace()[0] + + name := fmt.Sprintf("%n", frame) + file := fmt.Sprintf("%+s", frame) + line := fmt.Sprintf("%d", frame) + + parts := strings.Split(file, "\n\t") + if len(parts) > 1 { + file = parts[1] + } + + ctx = ctx.WithField("source", fmt.Sprintf("%s: %s:%s", name, file, line)) + } + + if f, ok := err.(Fielder); ok { + ctx = ctx.WithFields(f.Fields()) + } + + return ctx +} + +// Debug level message. +func (e *Entry) Debug(msg string) { + e.Logger.log(DebugLevel, e, msg) +} + +// Info level message. +func (e *Entry) Info(msg string) { + e.Logger.log(InfoLevel, e, msg) +} + +// Warn level message. +func (e *Entry) Warn(msg string) { + e.Logger.log(WarnLevel, e, msg) +} + +// Error level message. +func (e *Entry) Error(msg string) { + e.Logger.log(ErrorLevel, e, msg) +} + +// Fatal level message, followed by an exit. +func (e *Entry) Fatal(msg string) { + e.Logger.log(FatalLevel, e, msg) + os.Exit(1) +} + +// Debugf level formatted message. +func (e *Entry) Debugf(msg string, v ...interface{}) { + e.Debug(fmt.Sprintf(msg, v...)) +} + +// Infof level formatted message. +func (e *Entry) Infof(msg string, v ...interface{}) { + e.Info(fmt.Sprintf(msg, v...)) +} + +// Warnf level formatted message. +func (e *Entry) Warnf(msg string, v ...interface{}) { + e.Warn(fmt.Sprintf(msg, v...)) +} + +// Errorf level formatted message. +func (e *Entry) Errorf(msg string, v ...interface{}) { + e.Error(fmt.Sprintf(msg, v...)) +} + +// Fatalf level formatted message, followed by an exit. +func (e *Entry) Fatalf(msg string, v ...interface{}) { + e.Fatal(fmt.Sprintf(msg, v...)) +} + +// Trace returns a new entry with a Stop method to fire off +// a corresponding completion log, useful with defer. +func (e *Entry) Trace(msg string) *Entry { + e.Info(msg) + v := e.WithFields(e.Fields) + v.Message = msg + v.start = time.Now() + return v +} + +// Stop should be used with Trace, to fire off the completion message. When +// an `err` is passed the "error" field is set, and the log level is error. +func (e *Entry) Stop(err *error) { + if err == nil || *err == nil { + e.WithField("duration", time.Since(e.start)).Info(e.Message) + } else { + e.WithField("duration", time.Since(e.start)).WithError(*err).Error(e.Message) + } +} + +// mergedFields returns the fields list collapsed into a single map. +func (e *Entry) mergedFields() Fields { + f := Fields{} + + for _, fields := range e.fields { + for k, v := range fields { + f[k] = v + } + } + + return f +} + +// finalize returns a copy of the Entry with Fields merged. +func (e *Entry) finalize(level Level, msg string) *Entry { + return &Entry{ + Logger: e.Logger, + Fields: e.mergedFields(), + Level: level, + Message: msg, + Timestamp: Now(), + } +} diff --git a/vendor/github.com/apex/log/go.mod b/vendor/github.com/apex/log/go.mod new file mode 100644 index 00000000000..efc674b8cdf --- /dev/null +++ b/vendor/github.com/apex/log/go.mod @@ -0,0 +1,25 @@ +module github.com/apex/log + +go 1.12 + +require ( + github.com/aphistic/golf v0.0.0-20180712155816-02c07f170c5a + github.com/aphistic/sweet v0.2.0 // indirect + github.com/aws/aws-sdk-go v1.20.6 + github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59 + github.com/fatih/color v1.7.0 + github.com/go-logfmt/logfmt v0.4.0 + github.com/google/uuid v1.1.1 // indirect + github.com/jpillora/backoff v0.0.0-20180909062703-3050d21c67d7 // indirect + github.com/mattn/go-colorable v0.1.2 + github.com/pkg/errors v0.8.1 + github.com/rogpeppe/fastuuid v1.1.0 + github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9 // indirect + github.com/smartystreets/gunit v1.0.0 // indirect + github.com/stretchr/testify v1.3.0 + github.com/tj/assert v0.0.0-20171129193455-018094318fb0 + github.com/tj/go-elastic v0.0.0-20171221160941-36157cbbebc2 + github.com/tj/go-kinesis v0.0.0-20171128231115-08b17f58cb1b + github.com/tj/go-spin v1.1.0 + golang.org/x/net v0.0.0-20190620200207-3b0461eec859 // indirect +) diff --git a/vendor/github.com/apex/log/go.sum b/vendor/github.com/apex/log/go.sum new file mode 100644 index 00000000000..972a66dbcba --- /dev/null +++ b/vendor/github.com/apex/log/go.sum @@ -0,0 +1,90 @@ +github.com/aphistic/golf v0.0.0-20180712155816-02c07f170c5a h1:2KLQMJ8msqoPHIPDufkxVcoTtcmE5+1sL9950m4R9Pk= +github.com/aphistic/golf v0.0.0-20180712155816-02c07f170c5a/go.mod h1:3NqKYiepwy8kCu4PNA+aP7WUV72eXWJeP9/r3/K9aLE= +github.com/aphistic/sweet v0.2.0 h1:I4z+fAUqvKfvZV/CHi5dV0QuwbmIvYYFDjG0Ss5QpAs= +github.com/aphistic/sweet v0.2.0/go.mod h1:fWDlIh/isSE9n6EPsRmC0det+whmX6dJid3stzu0Xys= +github.com/aws/aws-sdk-go v1.20.6 h1:kmy4Gvdlyez1fV4kw5RYxZzWKVyuHZHgPWeU/YvRsV4= +github.com/aws/aws-sdk-go v1.20.6/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59 h1:WWB576BN5zNSZc/M9d/10pqEx5VHNhaQ/yOVAkmj5Yo= +github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U2H7sSsE2t6Kca0lfwTK8JdoNGS/yzM/4iH5I= +github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/go-logfmt/logfmt v0.4.0 h1:MP4Eh7ZCb31lleYCFuwm0oe4/YGak+5l1vA2NOE80nA= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jpillora/backoff v0.0.0-20180909062703-3050d21c67d7 h1:K//n/AqR5HjG3qxbrBCL4vJPW0MVFSs9CPK1OOJdRME= +github.com/jpillora/backoff v0.0.0-20180909062703-3050d21c67d7/go.mod h1:2iMrUgbbvHEiQClaW2NsSzMyGHqN+rDFqY705q49KG0= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 h1:T+h1c/A9Gawja4Y9mFVWj2vyii2bbUNDw3kt9VxK2EY= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= +github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU= +github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4= +github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= +github.com/onsi/ginkgo v1.6.0 h1:Ix8l273rp3QzYgXSR+c8d1fTG7UPgYkOSELPhiY/YGw= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo= +github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/fastuuid v1.1.0 h1:INyGLmTCMGFr6OVIb977ghJvABML2CMVjPoRfNDdYDo= +github.com/rogpeppe/fastuuid v1.1.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/smartystreets/assertions v1.0.0 h1:UVQPSSmc3qtTi+zPPkCXvZX9VvW/xT/NsRvKfwY81a8= +github.com/smartystreets/assertions v1.0.0/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM= +github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9 h1:hp2CYQUINdZMHdvTdXtPOY2ainKl4IoMcpAXEf2xj3Q= +github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9/go.mod h1:SnhjPscd9TpLiy1LpzGSKh3bXCfxxXuqd9xmQJy3slM= +github.com/smartystreets/gunit v1.0.0 h1:RyPDUFcJbvtXlhJPk7v+wnxZRY2EUokhEYl2EJOPToI= +github.com/smartystreets/gunit v1.0.0/go.mod h1:qwPWnhz6pn0NnRBP++URONOVyNkPyr4SauJk4cUOwJs= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/tj/assert v0.0.0-20171129193455-018094318fb0 h1:Rw8kxzWo1mr6FSaYXjQELRe88y2KdfynXdnK72rdjtA= +github.com/tj/assert v0.0.0-20171129193455-018094318fb0/go.mod h1:mZ9/Rh9oLWpLLDRpvE+3b7gP/C2YyLFYxNmcLnPTMe0= +github.com/tj/go-elastic v0.0.0-20171221160941-36157cbbebc2 h1:eGaGNxrtoZf/mBURsnNQKDR7u50Klgcf2eFDQEnc8Bc= +github.com/tj/go-elastic v0.0.0-20171221160941-36157cbbebc2/go.mod h1:WjeM0Oo1eNAjXGDx2yma7uG2XoyRZTq1uv3M/o7imD0= +github.com/tj/go-kinesis v0.0.0-20171128231115-08b17f58cb1b h1:m74UWYy+HBs+jMFR9mdZU6shPewugMyH5+GV6LNgW8w= +github.com/tj/go-kinesis v0.0.0-20171128231115-08b17f58cb1b/go.mod h1:/yhzCV0xPfx6jb1bBgRFjl5lytqVqZXEaeqWP8lTEao= +github.com/tj/go-spin v1.1.0 h1:lhdWZsvImxvZ3q1C5OIB7d72DuOwP4O2NdBg9PyzNds= +github.com/tj/go-spin v1.1.0/go.mod h1:Mg1mzmePZm4dva8Qz60H2lHwmJ2loum4VIrLgVnKwh4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734 h1:p/H982KKEjUnLJkM3tt/LemDnOc1GiZL5FCVlORJ5zo= +golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 h1:DH4skfRX4EBpamg7iV4ZlCpblAHI6s6TDM39bFZumv8= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/vendor/github.com/apex/log/interface.go b/vendor/github.com/apex/log/interface.go new file mode 100644 index 00000000000..c92ebea75ba --- /dev/null +++ b/vendor/github.com/apex/log/interface.go @@ -0,0 +1,19 @@ +package log + +// Interface represents the API of both Logger and Entry. +type Interface interface { + WithFields(fields Fielder) *Entry + WithField(key string, value interface{}) *Entry + WithError(err error) *Entry + Debug(msg string) + Info(msg string) + Warn(msg string) + Error(msg string) + Fatal(msg string) + Debugf(msg string, v ...interface{}) + Infof(msg string, v ...interface{}) + Warnf(msg string, v ...interface{}) + Errorf(msg string, v ...interface{}) + Fatalf(msg string, v ...interface{}) + Trace(msg string) *Entry +} diff --git a/vendor/github.com/apex/log/levels.go b/vendor/github.com/apex/log/levels.go new file mode 100644 index 00000000000..7d43a43609f --- /dev/null +++ b/vendor/github.com/apex/log/levels.go @@ -0,0 +1,81 @@ +package log + +import ( + "bytes" + "errors" + "strings" +) + +// ErrInvalidLevel is returned if the severity level is invalid. +var ErrInvalidLevel = errors.New("invalid level") + +// Level of severity. +type Level int + +// Log levels. +const ( + InvalidLevel Level = iota - 1 + DebugLevel + InfoLevel + WarnLevel + ErrorLevel + FatalLevel +) + +var levelNames = [...]string{ + DebugLevel: "debug", + InfoLevel: "info", + WarnLevel: "warn", + ErrorLevel: "error", + FatalLevel: "fatal", +} + +var levelStrings = map[string]Level{ + "debug": DebugLevel, + "info": InfoLevel, + "warn": WarnLevel, + "warning": WarnLevel, + "error": ErrorLevel, + "fatal": FatalLevel, +} + +// String implementation. +func (l Level) String() string { + return levelNames[l] +} + +// MarshalJSON implementation. +func (l Level) MarshalJSON() ([]byte, error) { + return []byte(`"` + l.String() + `"`), nil +} + +// UnmarshalJSON implementation. +func (l *Level) UnmarshalJSON(b []byte) error { + v, err := ParseLevel(string(bytes.Trim(b, `"`))) + if err != nil { + return err + } + + *l = v + return nil +} + +// ParseLevel parses level string. +func ParseLevel(s string) (Level, error) { + l, ok := levelStrings[strings.ToLower(s)] + if !ok { + return InvalidLevel, ErrInvalidLevel + } + + return l, nil +} + +// MustParseLevel parses level string or panics. +func MustParseLevel(s string) Level { + l, err := ParseLevel(s) + if err != nil { + panic("invalid log level") + } + + return l +} diff --git a/vendor/github.com/apex/log/logger.go b/vendor/github.com/apex/log/logger.go new file mode 100644 index 00000000000..1755747c912 --- /dev/null +++ b/vendor/github.com/apex/log/logger.go @@ -0,0 +1,149 @@ +package log + +import ( + stdlog "log" + "sort" +) + +// assert interface compliance. +var _ Interface = (*Logger)(nil) + +// Fielder is an interface for providing fields to custom types. +type Fielder interface { + Fields() Fields +} + +// Fields represents a map of entry level data used for structured logging. +type Fields map[string]interface{} + +// Fields implements Fielder. +func (f Fields) Fields() Fields { + return f +} + +// Get field value by name. +func (f Fields) Get(name string) interface{} { + return f[name] +} + +// Names returns field names sorted. +func (f Fields) Names() (v []string) { + for k := range f { + v = append(v, k) + } + + sort.Strings(v) + return +} + +// The HandlerFunc type is an adapter to allow the use of ordinary functions as +// log handlers. If f is a function with the appropriate signature, +// HandlerFunc(f) is a Handler object that calls f. +type HandlerFunc func(*Entry) error + +// HandleLog calls f(e). +func (f HandlerFunc) HandleLog(e *Entry) error { + return f(e) +} + +// Handler is used to handle log events, outputting them to +// stdio or sending them to remote services. See the "handlers" +// directory for implementations. +// +// It is left up to Handlers to implement thread-safety. +type Handler interface { + HandleLog(*Entry) error +} + +// Logger represents a logger with configurable Level and Handler. +type Logger struct { + Handler Handler + Level Level +} + +// WithFields returns a new entry with `fields` set. +func (l *Logger) WithFields(fields Fielder) *Entry { + return NewEntry(l).WithFields(fields.Fields()) +} + +// WithField returns a new entry with the `key` and `value` set. +// +// Note that the `key` should not have spaces in it - use camel +// case or underscores +func (l *Logger) WithField(key string, value interface{}) *Entry { + return NewEntry(l).WithField(key, value) +} + +// WithError returns a new entry with the "error" set to `err`. +func (l *Logger) WithError(err error) *Entry { + return NewEntry(l).WithError(err) +} + +// Debug level message. +func (l *Logger) Debug(msg string) { + NewEntry(l).Debug(msg) +} + +// Info level message. +func (l *Logger) Info(msg string) { + NewEntry(l).Info(msg) +} + +// Warn level message. +func (l *Logger) Warn(msg string) { + NewEntry(l).Warn(msg) +} + +// Error level message. +func (l *Logger) Error(msg string) { + NewEntry(l).Error(msg) +} + +// Fatal level message, followed by an exit. +func (l *Logger) Fatal(msg string) { + NewEntry(l).Fatal(msg) +} + +// Debugf level formatted message. +func (l *Logger) Debugf(msg string, v ...interface{}) { + NewEntry(l).Debugf(msg, v...) +} + +// Infof level formatted message. +func (l *Logger) Infof(msg string, v ...interface{}) { + NewEntry(l).Infof(msg, v...) +} + +// Warnf level formatted message. +func (l *Logger) Warnf(msg string, v ...interface{}) { + NewEntry(l).Warnf(msg, v...) +} + +// Errorf level formatted message. +func (l *Logger) Errorf(msg string, v ...interface{}) { + NewEntry(l).Errorf(msg, v...) +} + +// Fatalf level formatted message, followed by an exit. +func (l *Logger) Fatalf(msg string, v ...interface{}) { + NewEntry(l).Fatalf(msg, v...) +} + +// Trace returns a new entry with a Stop method to fire off +// a corresponding completion log, useful with defer. +func (l *Logger) Trace(msg string) *Entry { + return NewEntry(l).Trace(msg) +} + +// log the message, invoking the handler. We clone the entry here +// to bypass the overhead in Entry methods when the level is not +// met. +func (l *Logger) log(level Level, e *Entry, msg string) { + if level < l.Level { + return + } + + if err := l.Handler.HandleLog(e.finalize(level, msg)); err != nil { + stdlog.Printf("error logging: %s", err) + } +} diff --git a/vendor/github.com/apex/log/pkg.go b/vendor/github.com/apex/log/pkg.go new file mode 100644 index 00000000000..9bf51dc8e5d --- /dev/null +++ b/vendor/github.com/apex/log/pkg.go @@ -0,0 +1,100 @@ +package log + +// singletons ftw? +var Log Interface = &Logger{ + Handler: HandlerFunc(handleStdLog), + Level: InfoLevel, +} + +// SetHandler sets the handler. This is not thread-safe. +// The default handler outputs to the stdlib log. +func SetHandler(h Handler) { + if logger, ok := Log.(*Logger); ok { + logger.Handler = h + } +} + +// SetLevel sets the log level. This is not thread-safe. +func SetLevel(l Level) { + if logger, ok := Log.(*Logger); ok { + logger.Level = l + } +} + +// SetLevelFromString sets the log level from a string, panicing when invalid. This is not thread-safe. +func SetLevelFromString(s string) { + if logger, ok := Log.(*Logger); ok { + logger.Level = MustParseLevel(s) + } +} + +// WithFields returns a new entry with `fields` set. +func WithFields(fields Fielder) *Entry { + return Log.WithFields(fields) +} + +// WithField returns a new entry with the `key` and `value` set. +func WithField(key string, value interface{}) *Entry { + return Log.WithField(key, value) +} + +// WithError returns a new entry with the "error" set to `err`. +func WithError(err error) *Entry { + return Log.WithError(err) +} + +// Debug level message. +func Debug(msg string) { + Log.Debug(msg) +} + +// Info level message. +func Info(msg string) { + Log.Info(msg) +} + +// Warn level message. +func Warn(msg string) { + Log.Warn(msg) +} + +// Error level message. +func Error(msg string) { + Log.Error(msg) +} + +// Fatal level message, followed by an exit. +func Fatal(msg string) { + Log.Fatal(msg) +} + +// Debugf level formatted message. +func Debugf(msg string, v ...interface{}) { + Log.Debugf(msg, v...) +} + +// Infof level formatted message. +func Infof(msg string, v ...interface{}) { + Log.Infof(msg, v...) +} + +// Warnf level formatted message. +func Warnf(msg string, v ...interface{}) { + Log.Warnf(msg, v...) +} + +// Errorf level formatted message. +func Errorf(msg string, v ...interface{}) { + Log.Errorf(msg, v...) +} + +// Fatalf level formatted message, followed by an exit. +func Fatalf(msg string, v ...interface{}) { + Log.Fatalf(msg, v...) +} + +// Trace returns a new entry with a Stop method to fire off +// a corresponding completion log, useful with defer. +func Trace(msg string) *Entry { + return Log.Trace(msg) +} diff --git a/vendor/github.com/apex/log/stack.go b/vendor/github.com/apex/log/stack.go new file mode 100644 index 00000000000..57efe3262e1 --- /dev/null +++ b/vendor/github.com/apex/log/stack.go @@ -0,0 +1,8 @@ +package log + +import "github.com/pkg/errors" + +// stackTracer interface. +type stackTracer interface { + StackTrace() errors.StackTrace +} diff --git a/vendor/github.com/buildpacks/imgutil/.gitignore b/vendor/github.com/buildpacks/imgutil/.gitignore new file mode 100644 index 00000000000..3a30eb64468 --- /dev/null +++ b/vendor/github.com/buildpacks/imgutil/.gitignore @@ -0,0 +1,15 @@ +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, build with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# IDEs +.idea/ diff --git a/vendor/github.com/buildpacks/imgutil/.travis.yml b/vendor/github.com/buildpacks/imgutil/.travis.yml new file mode 100644 index 00000000000..8eb081b7b57 --- /dev/null +++ b/vendor/github.com/buildpacks/imgutil/.travis.yml @@ -0,0 +1,18 @@ +language: go +go: 1.12.x +dist: trusty + +env: + global: + - GO111MODULE=on + +jobs: + include: + - os: linux + script: + - docker info + - make + +branches: + only: + - master diff --git a/vendor/github.com/buildpacks/imgutil/LICENSE b/vendor/github.com/buildpacks/imgutil/LICENSE new file mode 100644 index 00000000000..261eeb9e9f8 --- /dev/null +++ b/vendor/github.com/buildpacks/imgutil/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/vendor/github.com/buildpacks/imgutil/Makefile b/vendor/github.com/buildpacks/imgutil/Makefile new file mode 100644 index 00000000000..68cf56c8bbb --- /dev/null +++ b/vendor/github.com/buildpacks/imgutil/Makefile @@ -0,0 +1,23 @@ +# Go parameters +GOCMD?=go +GOTEST=$(GOCMD) test -mod=vendor +PACKAGE_BASE=github.com/buildpacks/imgutil +PACKAGES:=$(shell $(GOCMD) list -mod=vendor ./... | grep -v /testdata/) +SRC:=$(shell find . -type f -name '*.go' -not -path "*/vendor/*") + +all: test + +install-goimports: + @echo "> Installing goimports..." + cd tools; $(GOCMD) install -mod=vendor golang.org/x/tools/cmd/goimports + +format: install-goimports + @echo "> Formating code..." + @goimports -l -w -local ${PACKAGE_BASE} ${SRC} + +vet: + @echo "> Vetting code..." + @$(GOCMD) vet -mod=vendor ${PACKAGES} + +test: format vet + $(GOTEST) -parallel=1 -count=1 -v ./... diff --git a/vendor/github.com/buildpacks/imgutil/README.md b/vendor/github.com/buildpacks/imgutil/README.md new file mode 100644 index 00000000000..2caa4b9dfc4 --- /dev/null +++ b/vendor/github.com/buildpacks/imgutil/README.md @@ -0,0 +1,19 @@ +# imgutil + +[![Build Status](https://travis-ci.org/buildpack/imgutil.svg?branch=master)](https://travis-ci.org/buildpack/imgutil) + +Helpful utilities for working with images + +## Development + +To format: + +```bash +$ make format +``` + +To run tests: + +```bash +$ make test +``` \ No newline at end of file diff --git a/vendor/github.com/buildpacks/imgutil/go.mod b/vendor/github.com/buildpacks/imgutil/go.mod new file mode 100644 index 00000000000..84d8ba92aee --- /dev/null +++ b/vendor/github.com/buildpacks/imgutil/go.mod @@ -0,0 +1,16 @@ +module github.com/buildpacks/imgutil + +require ( + github.com/docker/distribution v2.7.1+incompatible // indirect + github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7 + github.com/docker/go-connections v0.4.0 + github.com/gogo/protobuf v1.2.1 // indirect + github.com/google/go-cmp v0.2.0 + github.com/google/go-containerregistry v0.0.0-20191018211754-b77a90c667af + github.com/pkg/errors v0.8.1 + github.com/sclevine/spec v1.0.0 + golang.org/x/sync v0.0.0-20190423024810-112230192c58 + golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 // indirect +) + +go 1.13 diff --git a/vendor/github.com/buildpacks/imgutil/go.sum b/vendor/github.com/buildpacks/imgutil/go.sum new file mode 100644 index 00000000000..ae725d322dc --- /dev/null +++ b/vendor/github.com/buildpacks/imgutil/go.sum @@ -0,0 +1,166 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/Azure/azure-sdk-for-go v19.1.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8= +github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= +github.com/Azure/go-autorest v10.15.5+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/aws/aws-sdk-go v1.15.90/go.mod h1:es1KtYUFs7le0xQ3rOihkuoVD90z7D0fR2Qm4S00/gU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/containerd/containerd v1.3.0 h1:xjvXQWABwS2uiv3TWgQt5Uth60Gu86LTGZXMJkjc7rY= +github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017 h1:2HQmlpI3yI9deH18Q6xiSOIjXD4sLI55Y/gfpa8/558= +github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/distribution v2.6.0-rc.1.0.20180327202408-83389a148052+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug= +github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7 h1:Cvj7S8I4Xpx78KAl6TwTmMHuHlZ/0SM60NUneGJQ7IE= +github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker-credential-helpers v0.6.3 h1:zI2p9+1NQYdnG6sMU26EX4aVGlqbInSQxQXLvzJ4RPQ= +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-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/google/btree v0.0.0-20180124185431-e89373fe6b4a/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-containerregistry v0.0.0-20191018211754-b77a90c667af h1:gCcst+zXdvatJYFDtPd3C3VNEGcoFOOMwFydnFIfnF0= +github.com/google/go-containerregistry v0.0.0-20191018211754-b77a90c667af/go.mod h1:9kIomAeXUmwhqeYS2zoEuQ0sc2GOVmNW7t3y9aNQL1o= +github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/googleapis/gnostic v0.2.2/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= +github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/json-iterator/go v0.0.0-20180701071628-ab8a2e0c74be/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= +github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ= +github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI= +github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/sclevine/spec v1.0.0 h1:ILQ08A/CHCz8GGqivOvI54Hy1U40wwcpkf7WtB1MQfY= +github.com/sclevine/spec v1.0.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24q7p+U= +github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k= +github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +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/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191010194322-b09406accb47 h1:/XfQ9z7ib8eEJX2hdgFTZJ/ntt0swNk5oYBziWeTCvY= +golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20191017205301-920acffc3e65/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/grpc v1.24.0 h1:vb/1TCsVn3DcJlQ0Gs1yB1pKI6Do2/QNwxdKqmc/b0s= +google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= +gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +k8s.io/api v0.0.0-20180904230853-4e7be11eab3f/go.mod h1:iuAfoD4hCxJ8Onx9kaTIt30j7jUFS00AXQi6QMi99vA= +k8s.io/apimachinery v0.0.0-20180904193909-def12e63c512/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0= +k8s.io/client-go v0.0.0-20180910083459-2cefa64ff137/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s= +k8s.io/kube-openapi v0.0.0-20180731170545-e3762e86a74c/go.mod h1:BXM9ceUBTj2QnfH2MK1odQs778ajze1RxcmP6S8RVVc= +k8s.io/kubernetes v1.11.10/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= diff --git a/vendor/github.com/buildpacks/imgutil/image.go b/vendor/github.com/buildpacks/imgutil/image.go new file mode 100644 index 00000000000..84e1af6a09d --- /dev/null +++ b/vendor/github.com/buildpacks/imgutil/image.go @@ -0,0 +1,53 @@ +package imgutil + +import ( + "fmt" + "io" + "strings" + "time" +) + +type SaveDiagnostic struct { + ImageName string + Cause error +} + +type SaveError struct { + Errors []SaveDiagnostic +} + +func (e SaveError) Error() string { + var errors []string + for _, d := range e.Errors { + errors = append(errors, fmt.Sprintf("[%s: %s]", d.ImageName, d.Cause.Error())) + } + return fmt.Sprintf("failed to write image to the following tags: %s", strings.Join(errors, ",")) +} + +type Image interface { + Name() string + Rename(name string) + Label(string) (string, error) + SetLabel(string, string) error + Env(key string) (string, error) + SetEnv(string, string) error + SetEntrypoint(...string) error + SetWorkingDir(string) error + SetCmd(...string) error + Rebase(string, Image) error + AddLayer(path string) error + ReuseLayer(diffID string) error + // TopLayer returns the diff id for the top layer + TopLayer() (string, error) + // Save saves the image as `Name()` and any additional names provided to this method. + Save(additionalNames ...string) error + // Found tells whether the image exists in the repository by `Name()`. + Found() bool + // GetLayer retrieves layer by diff id. Returns a reader of the uncompressed contents of the layer. + GetLayer(diffID string) (io.ReadCloser, error) + Delete() error + CreatedAt() (time.Time, error) + Identifier() (Identifier, error) +} + +type Identifier fmt.Stringer diff --git a/vendor/github.com/buildpacks/imgutil/local/identifier.go b/vendor/github.com/buildpacks/imgutil/local/identifier.go new file mode 100644 index 00000000000..dd24fba1bb1 --- /dev/null +++ b/vendor/github.com/buildpacks/imgutil/local/identifier.go @@ -0,0 +1,9 @@ +package local + +type IDIdentifier struct { + ImageID string +} + +func (i IDIdentifier) String() string { + return i.ImageID +} diff --git a/vendor/github.com/buildpacks/imgutil/local/local.go b/vendor/github.com/buildpacks/imgutil/local/local.go new file mode 100644 index 00000000000..42b2a74287e --- /dev/null +++ b/vendor/github.com/buildpacks/imgutil/local/local.go @@ -0,0 +1,616 @@ +package local + +import ( + "archive/tar" + "context" + "crypto/sha256" + "encoding/hex" + "encoding/json" + "fmt" + "io" + "io/ioutil" + "os" + "path/filepath" + "strings" + "time" + + "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/container" + "github.com/docker/docker/client" + "github.com/google/go-containerregistry/pkg/name" + "github.com/pkg/errors" + "golang.org/x/sync/singleflight" + + "github.com/buildpacks/imgutil" +) + +type Image struct { + repoName string + docker *client.Client + inspect types.ImageInspect + layerPaths []string + currentTempImage string + requestGroup singleflight.Group + prevName string + easyAddLayers []string +} + +type FileSystemLocalImage struct { + dir string + layersMap map[string]string +} + +type ImageOption func(image *Image) (*Image, error) + +func WithPreviousImage(imageName string) ImageOption { + return func(i *Image) (*Image, error) { + if _, err := inspectOptionalImage(i.docker, imageName); err != nil { + return i, err + } + + i.prevName = imageName + + return i, nil + } +} + +func FromBaseImage(imageName string) ImageOption { + return func(i *Image) (*Image, error) { + var ( + err error + inspect types.ImageInspect + ) + + if inspect, err = inspectOptionalImage(i.docker, imageName); err != nil { + return i, err + } + + i.inspect = inspect + i.layerPaths = make([]string, len(i.inspect.RootFS.Layers)) + + return i, nil + } +} + +func NewImage(repoName string, dockerClient *client.Client, ops ...ImageOption) (imgutil.Image, error) { + inspect := defaultInspect() + + image := &Image{ + docker: dockerClient, + repoName: repoName, + inspect: inspect, + layerPaths: make([]string, len(inspect.RootFS.Layers)), + } + + var err error + for _, v := range ops { + image, err = v(image) + if err != nil { + return nil, err + } + } + + return image, nil +} + +func (i *Image) Label(key string) (string, error) { + labels := i.inspect.Config.Labels + return labels[key], nil +} + +func (i *Image) Env(key string) (string, error) { + for _, envVar := range i.inspect.Config.Env { + parts := strings.Split(envVar, "=") + if parts[0] == key { + return parts[1], nil + } + } + return "", nil +} + +func (i *Image) Rename(name string) { + i.easyAddLayers = nil + if prevInspect, _, err := i.docker.ImageInspectWithRaw(context.TODO(), name); err == nil { + if i.sameBase(prevInspect) { + i.easyAddLayers = prevInspect.RootFS.Layers[len(i.inspect.RootFS.Layers):] + } + } + + i.repoName = name +} + +func (i *Image) sameBase(prevInspect types.ImageInspect) bool { + if len(prevInspect.RootFS.Layers) < len(i.inspect.RootFS.Layers) { + return false + } + for i, baseLayer := range i.inspect.RootFS.Layers { + if baseLayer != prevInspect.RootFS.Layers[i] { + return false + } + } + return true +} + +func (i *Image) Name() string { + return i.repoName +} + +func (i *Image) Found() bool { + return i.inspect.ID != "" +} + +func (i *Image) Identifier() (imgutil.Identifier, error) { + return IDIdentifier{ + ImageID: strings.TrimPrefix(i.inspect.ID, "sha256:"), + }, nil +} + +func (i *Image) CreatedAt() (time.Time, error) { + createdAtTime := i.inspect.Created + createdTime, err := time.Parse(time.RFC3339Nano, createdAtTime) + + if err != nil { + return time.Time{}, err + } + return createdTime, nil +} + +func (i *Image) Rebase(baseTopLayer string, newBase imgutil.Image) error { + ctx := context.Background() + + // FIND TOP LAYER + keepLayers := -1 + for idx, diffID := range i.inspect.RootFS.Layers { + if diffID == baseTopLayer { + keepLayers = len(i.inspect.RootFS.Layers) - idx - 1 + break + } + } + if keepLayers == -1 { + return fmt.Errorf("'%s' not found in '%s' during rebase", baseTopLayer, i.repoName) + } + + // SWITCH BASE LAYERS + newBaseInspect, _, err := i.docker.ImageInspectWithRaw(ctx, newBase.Name()) + if err != nil { + return errors.Wrap(err, "analyze read previous image config") + } + i.inspect.RootFS.Layers = newBaseInspect.RootFS.Layers + i.layerPaths = make([]string, len(i.inspect.RootFS.Layers)) + + // DOWNLOAD IMAGE + fsImage, err := i.downloadImageOnce(i.repoName) + if err != nil { + return err + } + + // READ MANIFEST.JSON + b, err := ioutil.ReadFile(filepath.Join(fsImage.dir, "manifest.json")) + if err != nil { + return err + } + var manifest []struct{ Layers []string } + if err := json.Unmarshal(b, &manifest); err != nil { + return err + } + if len(manifest) != 1 { + return fmt.Errorf("expected 1 image received %d", len(manifest)) + } + + // ADD EXISTING LAYERS + for _, filename := range manifest[0].Layers[(len(manifest[0].Layers) - keepLayers):] { + if err := i.AddLayer(filepath.Join(fsImage.dir, filename)); err != nil { + return err + } + } + + return nil +} + +func (i *Image) SetLabel(key, val string) error { + if i.inspect.Config.Labels == nil { + i.inspect.Config.Labels = map[string]string{} + } + + i.inspect.Config.Labels[key] = val + return nil +} + +func (i *Image) SetEnv(key, val string) error { + i.inspect.Config.Env = append(i.inspect.Config.Env, fmt.Sprintf("%s=%s", key, val)) + return nil +} + +func (i *Image) SetWorkingDir(dir string) error { + i.inspect.Config.WorkingDir = dir + return nil +} + +func (i *Image) SetEntrypoint(ep ...string) error { + i.inspect.Config.Entrypoint = ep + return nil +} + +func (i *Image) SetCmd(cmd ...string) error { + i.inspect.Config.Cmd = cmd + return nil +} + +func (i *Image) TopLayer() (string, error) { + all := i.inspect.RootFS.Layers + + if len(all) == 0 { + return "", fmt.Errorf("image '%s' has no layers", i.repoName) + } + + topLayer := all[len(all)-1] + return topLayer, nil +} + +func (i *Image) GetLayer(diffID string) (io.ReadCloser, error) { + fsImage, err := i.downloadImageOnce(i.repoName) + if err != nil { + return nil, err + } + + layerID, ok := fsImage.layersMap[diffID] + if !ok { + return nil, fmt.Errorf("image '%s' does not contain layer with diff ID '%s'", i.repoName, diffID) + } + return os.Open(filepath.Join(fsImage.dir, layerID)) +} + +func (i *Image) AddLayer(path string) error { + f, err := os.Open(path) + if err != nil { + return errors.Wrapf(err, "AddLayer: open layer: %s", path) + } + defer f.Close() + hasher := sha256.New() + if _, err := io.Copy(hasher, f); err != nil { + return errors.Wrapf(err, "AddLayer: calculate checksum: %s", path) + } + sha := hex.EncodeToString(hasher.Sum(make([]byte, 0, hasher.Size()))) + + i.inspect.RootFS.Layers = append(i.inspect.RootFS.Layers, "sha256:"+sha) + i.layerPaths = append(i.layerPaths, path) + i.easyAddLayers = nil + + return nil +} + +func (i *Image) ReuseLayer(diffID string) error { + if len(i.easyAddLayers) > 0 && i.easyAddLayers[0] == diffID { + i.inspect.RootFS.Layers = append(i.inspect.RootFS.Layers, diffID) + i.layerPaths = append(i.layerPaths, "") + i.easyAddLayers = i.easyAddLayers[1:] + return nil + } + + if i.prevName == "" { + return errors.New("no previous image provided to reuse layers from") + } + + fsImage, err := i.downloadImageOnce(i.prevName) + if err != nil { + return err + } + + reuseLayer, ok := fsImage.layersMap[diffID] + if !ok { + return fmt.Errorf("SHA %s was not found in %s", diffID, i.repoName) + } + + return i.AddLayer(filepath.Join(fsImage.dir, reuseLayer)) +} + +func (i *Image) Save(additionalNames ...string) error { + inspect, err := i.doSave() + if err != nil { + saveErr := imgutil.SaveError{} + for _, n := range append([]string{i.Name()}, additionalNames...) { + saveErr.Errors = append(saveErr.Errors, imgutil.SaveDiagnostic{ImageName: n, Cause: err}) + } + return saveErr + } + i.inspect = inspect + + var errs []imgutil.SaveDiagnostic + for _, n := range append([]string{i.Name()}, additionalNames...) { + if err := i.docker.ImageTag(context.Background(), i.inspect.ID, n); err != nil { + errs = append(errs, imgutil.SaveDiagnostic{ImageName: n, Cause: err}) + } + } + + if len(errs) > 0 { + return imgutil.SaveError{Errors: errs} + } + + return nil +} + +func (i *Image) doSave() (types.ImageInspect, error) { + ctx := context.Background() + done := make(chan error) + + t, err := name.NewTag(i.repoName, name.WeakValidation) + if err != nil { + return types.ImageInspect{}, err + } + repoName := t.String() + + pr, pw := io.Pipe() + defer pw.Close() + go func() { + res, err := i.docker.ImageLoad(ctx, pr, true) + if err != nil { + done <- err + return + } + defer res.Body.Close() + io.Copy(ioutil.Discard, res.Body) + + done <- nil + }() + + tw := tar.NewWriter(pw) + defer tw.Close() + + configFile, err := i.newConfigFile() + if err != nil { + return types.ImageInspect{}, errors.Wrap(err, "generate config file") + } + + id := fmt.Sprintf("%x", sha256.Sum256(configFile)) + if err := addTextToTar(tw, id+".json", configFile); err != nil { + return types.ImageInspect{}, err + } + + var layerPaths []string + for _, path := range i.layerPaths { + if path == "" { + layerPaths = append(layerPaths, "") + continue + } + layerName := fmt.Sprintf("/%x.tar", sha256.Sum256([]byte(path))) + f, err := os.Open(path) + if err != nil { + return types.ImageInspect{}, err + } + defer f.Close() + if err := addFileToTar(tw, layerName, f); err != nil { + return types.ImageInspect{}, err + } + f.Close() + layerPaths = append(layerPaths, layerName) + + } + + manifest, err := json.Marshal([]map[string]interface{}{ + { + "Config": id + ".json", + "RepoTags": []string{repoName}, + "Layers": layerPaths, + }, + }) + if err != nil { + return types.ImageInspect{}, err + } + + if err := addTextToTar(tw, "manifest.json", manifest); err != nil { + return types.ImageInspect{}, err + } + + tw.Close() + pw.Close() + err = <-done + + i.requestGroup.Forget(i.repoName) + + inspect, _, err := i.docker.ImageInspectWithRaw(context.Background(), id) + if err != nil { + if client.IsErrNotFound(err) { + return types.ImageInspect{}, errors.Wrapf(err, "save image '%s'", i.repoName) + } + return types.ImageInspect{}, err + } + + return inspect, nil +} + +func (i *Image) newConfigFile() ([]byte, error) { + imgConfig := map[string]interface{}{ + "os": "linux", + "created": time.Now().Format(time.RFC3339), + "config": i.inspect.Config, + "rootfs": map[string][]string{ + "diff_ids": i.inspect.RootFS.Layers, + }, + "history": make([]struct{}, len(i.inspect.RootFS.Layers)), + } + return json.Marshal(imgConfig) +} + +func (i *Image) Delete() error { + if !i.Found() { + return nil + } + options := types.ImageRemoveOptions{ + Force: true, + PruneChildren: true, + } + _, err := i.docker.ImageRemove(context.Background(), i.inspect.ID, options) + return err +} + +func (i *Image) downloadImageOnce(imageName string) (*FileSystemLocalImage, error) { + v, err, _ := i.requestGroup.Do(imageName, func() (details interface{}, err error) { + return downloadImage(i.docker, imageName) + }) + + if err != nil { + return nil, err + } + + return v.(*FileSystemLocalImage), nil +} + +func downloadImage(docker *client.Client, imageName string) (*FileSystemLocalImage, error) { + ctx := context.Background() + + tarFile, err := docker.ImageSave(ctx, []string{imageName}) + if err != nil { + return nil, err + } + defer tarFile.Close() + + tmpDir, err := ioutil.TempDir("", "imgutil.local.image.") + if err != nil { + return nil, errors.Wrap(err, "local reuse-layer create temp dir") + } + + err = untar(tarFile, tmpDir) + if err != nil { + return nil, err + } + + mf, err := os.Open(filepath.Join(tmpDir, "manifest.json")) + if err != nil { + return nil, err + } + defer mf.Close() + + var manifest []struct { + Config string + Layers []string + } + if err := json.NewDecoder(mf).Decode(&manifest); err != nil { + return nil, err + } + + if len(manifest) != 1 { + return nil, fmt.Errorf("manifest.json had unexpected number of entries: %d", len(manifest)) + } + + df, err := os.Open(filepath.Join(tmpDir, manifest[0].Config)) + if err != nil { + return nil, err + } + defer df.Close() + + var details struct { + RootFS struct { + DiffIDs []string `json:"diff_ids"` + } `json:"rootfs"` + } + + if err = json.NewDecoder(df).Decode(&details); err != nil { + return nil, err + } + + if len(manifest[0].Layers) != len(details.RootFS.DiffIDs) { + return nil, fmt.Errorf("layers and diff IDs do not match, there are %d layers and %d diffIDs", len(manifest[0].Layers), len(details.RootFS.DiffIDs)) + } + + layersMap := make(map[string]string, len(manifest[0].Layers)) + for i, diffID := range details.RootFS.DiffIDs { + layerID := manifest[0].Layers[i] + layersMap[diffID] = layerID + } + + return &FileSystemLocalImage{ + dir: tmpDir, + layersMap: layersMap, + }, nil +} + +func addTextToTar(tw *tar.Writer, name string, contents []byte) error { + hdr := &tar.Header{Name: name, Mode: 0644, Size: int64(len(contents))} + if err := tw.WriteHeader(hdr); err != nil { + return err + } + _, err := tw.Write(contents) + return err +} + +func addFileToTar(tw *tar.Writer, name string, contents *os.File) error { + fi, err := contents.Stat() + if err != nil { + return err + } + hdr := &tar.Header{Name: name, Mode: 0644, Size: int64(fi.Size())} + if err := tw.WriteHeader(hdr); err != nil { + return err + } + _, err = io.Copy(tw, contents) + return err +} + +func untar(r io.Reader, dest string) error { + tr := tar.NewReader(r) + for { + hdr, err := tr.Next() + if err == io.EOF { + // end of tar archive + return nil + } + if err != nil { + return err + } + + path := filepath.Join(dest, hdr.Name) + + switch hdr.Typeflag { + case tar.TypeDir: + if err := os.MkdirAll(path, hdr.FileInfo().Mode()); err != nil { + return err + } + case tar.TypeReg, tar.TypeRegA: + _, err := os.Stat(filepath.Dir(path)) + if os.IsNotExist(err) { + if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil { + return err + } + } + + fh, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, hdr.FileInfo().Mode()) + if err != nil { + return err + } + if _, err := io.Copy(fh, tr); err != nil { + fh.Close() + return err + } + fh.Close() + case tar.TypeSymlink: + if err := os.Symlink(hdr.Linkname, path); err != nil { + return err + } + default: + return fmt.Errorf("unknown file type in tar %d", hdr.Typeflag) + } + } +} + +func inspectOptionalImage(docker *client.Client, imageName string) (types.ImageInspect, error) { + var ( + err error + inspect types.ImageInspect + ) + + if inspect, _, err = docker.ImageInspectWithRaw(context.Background(), imageName); err != nil { + if client.IsErrNotFound(err) { + return defaultInspect(), nil + } + + return types.ImageInspect{}, errors.Wrapf(err, "verifying image '%s'", imageName) + } + + return inspect, nil +} + +func defaultInspect() types.ImageInspect { + return types.ImageInspect{ + Config: &container.Config{}, + } +} diff --git a/vendor/github.com/buildpacks/imgutil/remote/identifier.go b/vendor/github.com/buildpacks/imgutil/remote/identifier.go new file mode 100644 index 00000000000..56389053577 --- /dev/null +++ b/vendor/github.com/buildpacks/imgutil/remote/identifier.go @@ -0,0 +1,13 @@ +package remote + +import ( + "github.com/google/go-containerregistry/pkg/name" +) + +type DigestIdentifier struct { + Digest name.Digest +} + +func (d DigestIdentifier) String() string { + return d.Digest.String() +} diff --git a/vendor/github.com/buildpacks/imgutil/remote/remote.go b/vendor/github.com/buildpacks/imgutil/remote/remote.go new file mode 100644 index 00000000000..6a619a92d27 --- /dev/null +++ b/vendor/github.com/buildpacks/imgutil/remote/remote.go @@ -0,0 +1,432 @@ +package remote + +import ( + "compress/gzip" + "fmt" + "io" + "net/http" + "strings" + "time" + + "github.com/google/go-containerregistry/pkg/authn" + "github.com/google/go-containerregistry/pkg/name" + v1 "github.com/google/go-containerregistry/pkg/v1" + "github.com/google/go-containerregistry/pkg/v1/mutate" + "github.com/google/go-containerregistry/pkg/v1/random" + "github.com/google/go-containerregistry/pkg/v1/remote" + "github.com/google/go-containerregistry/pkg/v1/remote/transport" + "github.com/google/go-containerregistry/pkg/v1/tarball" + "github.com/google/go-containerregistry/pkg/v1/types" + "github.com/pkg/errors" + + "github.com/buildpacks/imgutil" +) + +type Image struct { + keychain authn.Keychain + repoName string + image v1.Image + prevLayers []v1.Layer +} + +type ImageOption func(*Image) (*Image, error) + +func WithPreviousImage(imageName string) ImageOption { + return func(r *Image) (*Image, error) { + var err error + + prevImage, err := newV1Image(r.keychain, imageName) + if err != nil { + return nil, err + } + + prevLayers, err := prevImage.Layers() + if err != nil { + return nil, errors.Wrapf(err, "failed to get layers for previous image with repo name '%s'", imageName) + } + + r.prevLayers = prevLayers + return r, nil + } +} + +func FromBaseImage(imageName string) ImageOption { + return func(r *Image) (*Image, error) { + var err error + r.image, err = newV1Image(r.keychain, imageName) + if err != nil { + return nil, err + } + return r, nil + } +} + +func NewImage(repoName string, keychain authn.Keychain, ops ...ImageOption) (imgutil.Image, error) { + image, err := emptyImage() + if err != nil { + return nil, err + } + + ri := &Image{ + keychain: keychain, + repoName: repoName, + image: image, + } + + for _, op := range ops { + ri, err = op(ri) + if err != nil { + return nil, err + } + } + + return ri, nil +} + +func newV1Image(keychain authn.Keychain, repoName string) (v1.Image, error) { + ref, auth, err := referenceForRepoName(keychain, repoName) + if err != nil { + return nil, err + } + image, err := remote.Image(ref, remote.WithAuth(auth), remote.WithTransport(http.DefaultTransport)) + if err != nil { + if transportErr, ok := err.(*transport.Error); ok && len(transportErr.Errors) > 0 { + switch transportErr.Errors[0].Code { + case transport.UnauthorizedErrorCode, transport.ManifestUnknownErrorCode: + return emptyImage() + } + } + return nil, fmt.Errorf("connect to repo store '%s': %s", repoName, err.Error()) + } + return image, nil +} + +func emptyImage() (v1.Image, error) { + return random.Image(0, 0) +} + +func referenceForRepoName(keychain authn.Keychain, ref string) (name.Reference, authn.Authenticator, error) { + var auth authn.Authenticator + r, err := name.ParseReference(ref, name.WeakValidation) + if err != nil { + return nil, nil, err + } + + auth, err = keychain.Resolve(r.Context().Registry) + if err != nil { + return nil, nil, err + } + return r, auth, nil +} + +func (i *Image) Label(key string) (string, error) { + cfg, err := i.image.ConfigFile() + if err != nil || cfg == nil { + return "", fmt.Errorf("failed to get config file for image '%s'", i.repoName) + } + labels := cfg.Config.Labels + return labels[key], nil + +} + +func (i *Image) Env(key string) (string, error) { + cfg, err := i.image.ConfigFile() + if err != nil || cfg == nil { + return "", fmt.Errorf("failed to get config file for image '%s'", i.repoName) + } + for _, envVar := range cfg.Config.Env { + parts := strings.Split(envVar, "=") + if parts[0] == key { + return parts[1], nil + } + } + return "", nil +} + +func (i *Image) Rename(name string) { + i.repoName = name +} + +func (i *Image) Name() string { + return i.repoName +} + +func (i *Image) Found() bool { + ref, auth, err := referenceForRepoName(i.keychain, i.repoName) + if err != nil { + return false + } + _, err = remote.Image(ref, remote.WithAuth(auth), remote.WithTransport(http.DefaultTransport)) + if err != nil { + return false + } + return true +} + +func (i *Image) Identifier() (imgutil.Identifier, error) { + ref, err := name.ParseReference(i.repoName, name.WeakValidation) + if err != nil { + return nil, fmt.Errorf("failed to parse reference for image '%s': %s", i.repoName, err) + } + + hash, err := i.image.Digest() + if err != nil { + return nil, fmt.Errorf("failed to get digest for image '%s': %s", i.repoName, err) + } + + digestRef, err := name.NewDigest(fmt.Sprintf("%s@%s", ref.Context().Name(), hash.String()), name.WeakValidation) + if err != nil { + return nil, errors.Wrap(err, "creating digest reference") + } + + return DigestIdentifier{ + Digest: digestRef, + }, nil +} + +func (i *Image) CreatedAt() (time.Time, error) { + configFile, err := i.image.ConfigFile() + if err != nil { + return time.Time{}, fmt.Errorf("failed to get createdAt time for image '%s': %s", i.repoName, err) + } + return configFile.Created.UTC(), nil +} + +func (i *Image) Rebase(baseTopLayer string, newBase imgutil.Image) error { + newBaseRemote, ok := newBase.(*Image) + if !ok { + return errors.New("expected new base to be a remote image") + } + + newImage, err := mutate.Rebase(i.image, &subImage{img: i.image, topDiffID: baseTopLayer}, newBaseRemote.image) + if err != nil { + return errors.Wrap(err, "rebase") + } + i.image = newImage + return nil +} + +func (i *Image) SetLabel(key, val string) error { + configFile, err := i.image.ConfigFile() + if err != nil { + return err + } + config := *configFile.Config.DeepCopy() + if config.Labels == nil { + config.Labels = map[string]string{} + } + config.Labels[key] = val + i.image, err = mutate.Config(i.image, config) + return err +} + +func (i *Image) SetEnv(key, val string) error { + configFile, err := i.image.ConfigFile() + if err != nil { + return err + } + config := *configFile.Config.DeepCopy() + for idx, e := range config.Env { + parts := strings.Split(e, "=") + if parts[0] == key { + config.Env[idx] = fmt.Sprintf("%s=%s", key, val) + i.image, err = mutate.Config(i.image, config) + if err != nil { + return err + } + return nil + } + } + config.Env = append(config.Env, fmt.Sprintf("%s=%s", key, val)) + i.image, err = mutate.Config(i.image, config) + return err +} + +func (i *Image) SetWorkingDir(dir string) error { + configFile, err := i.image.ConfigFile() + if err != nil { + return err + } + config := *configFile.Config.DeepCopy() + config.WorkingDir = dir + i.image, err = mutate.Config(i.image, config) + return err +} + +func (i *Image) SetEntrypoint(ep ...string) error { + configFile, err := i.image.ConfigFile() + if err != nil { + return err + } + config := *configFile.Config.DeepCopy() + config.Entrypoint = ep + i.image, err = mutate.Config(i.image, config) + return err +} + +func (i *Image) SetCmd(cmd ...string) error { + configFile, err := i.image.ConfigFile() + if err != nil { + return err + } + config := *configFile.Config.DeepCopy() + config.Cmd = cmd + i.image, err = mutate.Config(i.image, config) + return err +} + +func (i *Image) TopLayer() (string, error) { + all, err := i.image.Layers() + if err != nil { + return "", err + } + if len(all) == 0 { + return "", fmt.Errorf("image %s has no layers", i.Name()) + } + topLayer := all[len(all)-1] + hex, err := topLayer.DiffID() + if err != nil { + return "", err + } + return hex.String(), nil +} + +func (i *Image) GetLayer(sha string) (io.ReadCloser, error) { + layers, err := i.image.Layers() + if err != nil { + return nil, err + } + + layer, err := findLayerWithSha(layers, sha) + if err != nil { + return nil, err + } + + return layer.Uncompressed() +} + +func (i *Image) AddLayer(path string) error { + layer, err := tarball.LayerFromFile(path, tarball.WithCompressionLevel(gzip.DefaultCompression)) + if err != nil { + return err + } + i.image, err = mutate.AppendLayers(i.image, layer) + if err != nil { + return errors.Wrap(err, "add layer") + } + return nil +} + +func (i *Image) ReuseLayer(sha string) error { + layer, err := findLayerWithSha(i.prevLayers, sha) + if err != nil { + return err + } + i.image, err = mutate.AppendLayers(i.image, layer) + return err +} + +func findLayerWithSha(layers []v1.Layer, diffID string) (v1.Layer, error) { + for _, layer := range layers { + dID, err := layer.DiffID() + if err != nil { + return nil, errors.Wrap(err, "get diff ID for previous image layer") + } + if diffID == dID.String() { + return layer, nil + } + } + return nil, fmt.Errorf(`previous image did not have layer with diff id '%s'`, diffID) +} + +func (i *Image) Save(additionalNames ...string) error { + var err error + + allNames := append([]string{i.repoName}, additionalNames...) + + i.image, err = mutate.CreatedAt(i.image, v1.Time{Time: time.Now()}) + if err != nil { + return errors.Wrap(err, "set creation time") + } + + cfg, err := i.image.ConfigFile() + if err != nil { + return errors.Wrap(err, "get image config") + } + + layers, err := i.image.Layers() + if err != nil { + return errors.Wrap(err, "get image layers") + } + + cfg.History = make([]v1.History, len(layers)) + i.image, err = mutate.ConfigFile(i.image, cfg) + if err != nil { + return errors.Wrap(err, "zeroing history") + } + + var diagnostics []imgutil.SaveDiagnostic + for _, n := range allNames { + if err := i.doSave(n); err != nil { + diagnostics = append(diagnostics, imgutil.SaveDiagnostic{ImageName: n, Cause: err}) + } + } + if len(diagnostics) > 0 { + return imgutil.SaveError{Errors: diagnostics} + } + + return nil +} + +func (i *Image) doSave(imageName string) error { + ref, auth, err := referenceForRepoName(i.keychain, imageName) + if err != nil { + return err + } + return remote.Write(ref, i.image, remote.WithAuth(auth)) +} + +func (i *Image) Delete() error { + id, err := i.Identifier() + if err != nil { + return err + } + ref, auth, err := referenceForRepoName(i.keychain, id.String()) + if err != nil { + return err + } + return remote.Delete(ref, remote.WithAuth(auth)) +} + +type subImage struct { + img v1.Image + topDiffID string +} + +func (si *subImage) Layers() ([]v1.Layer, error) { + all, err := si.img.Layers() + if err != nil { + return nil, err + } + for i, l := range all { + d, err := l.DiffID() + if err != nil { + return nil, err + } + if d.String() == si.topDiffID { + return all[0 : i+1], nil + } + } + return nil, errors.New("could not find base layer in image") +} +func (si *subImage) BlobSet() (map[v1.Hash]struct{}, error) { panic("Not Implemented") } +func (si *subImage) MediaType() (types.MediaType, error) { panic("Not Implemented") } +func (si *subImage) ConfigName() (v1.Hash, error) { panic("Not Implemented") } +func (si *subImage) ConfigFile() (*v1.ConfigFile, error) { panic("Not Implemented") } +func (si *subImage) RawConfigFile() ([]byte, error) { panic("Not Implemented") } +func (si *subImage) Digest() (v1.Hash, error) { panic("Not Implemented") } +func (si *subImage) Manifest() (*v1.Manifest, error) { panic("Not Implemented") } +func (si *subImage) RawManifest() ([]byte, error) { panic("Not Implemented") } +func (si *subImage) LayerByDigest(v1.Hash) (v1.Layer, error) { panic("Not Implemented") } +func (si *subImage) LayerByDiffID(v1.Hash) (v1.Layer, error) { panic("Not Implemented") } +func (si *subImage) Size() (int64, error) { panic("Not Implemented") } diff --git a/vendor/github.com/buildpacks/lifecycle/.gitignore b/vendor/github.com/buildpacks/lifecycle/.gitignore new file mode 100644 index 00000000000..1ae2ae2df48 --- /dev/null +++ b/vendor/github.com/buildpacks/lifecycle/.gitignore @@ -0,0 +1,6 @@ +.DS_Store +.idea +*.coverprofile +*.test +*~ +/out diff --git a/vendor/github.com/buildpacks/lifecycle/.travis.yml b/vendor/github.com/buildpacks/lifecycle/.travis.yml new file mode 100644 index 00000000000..3cef38717ed --- /dev/null +++ b/vendor/github.com/buildpacks/lifecycle/.travis.yml @@ -0,0 +1,8 @@ +language: go +go: +- 1.13.x +script: +- make test +branches: + only: + - master diff --git a/vendor/github.com/buildpacks/lifecycle/LICENSE b/vendor/github.com/buildpacks/lifecycle/LICENSE new file mode 100644 index 00000000000..a83b6322182 --- /dev/null +++ b/vendor/github.com/buildpacks/lifecycle/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2018 Stephen Levine + + 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. diff --git a/vendor/github.com/buildpacks/lifecycle/Makefile b/vendor/github.com/buildpacks/lifecycle/Makefile new file mode 100644 index 00000000000..6ddad5990db --- /dev/null +++ b/vendor/github.com/buildpacks/lifecycle/Makefile @@ -0,0 +1,90 @@ +GOCMD?=go +GOENV=GOARCH=amd64 CGO_ENABLED=0 +GOBUILD=$(GOCMD) build -mod=vendor -ldflags "-s -w -X 'github.com/buildpacks/lifecycle/cmd.Version=$(LIFECYCLE_VERSION)' -X 'github.com/buildpacks/lifecycle/cmd.SCMRepository=$(SCM_REPO)' -X 'github.com/buildpacks/lifecycle/cmd.SCMCommit=$(SCM_COMMIT)'" +GOTEST=$(GOCMD) test -mod=vendor +LIFECYCLE_VERSION?=0.0.0 +PLATFORM_API=0.2 +BUILDPACK_API=0.2 +SCM_REPO?= +SCM_COMMIT=$$(git rev-parse --short HEAD) +ARCHIVE_NAME=lifecycle-v$(LIFECYCLE_VERSION)+linux.x86-64 + +define LIFECYCLE_DESCRIPTOR +[api] + platform = "$(PLATFORM_API)" + buildpack = "$(BUILDPACK_API)" + +[lifecycle] + version = "$(LIFECYCLE_VERSION)" +endef + +all: test build package + +build: build-linux + +build-macos: + @echo "> Building for macos..." + mkdir -p ./out/lifecycle + GOOS=darwin $(GOENV) $(GOBUILD) -o ./out/lifecycle -a ./cmd/... + +build-linux: + @echo "> Building for linux..." + mkdir -p ./out/lifecycle + GOOS=linux $(GOENV) $(GOBUILD) -o ./out/lifecycle -a ./cmd/... + +build-windows: + @echo "> Building for windows..." + mkdir -p ./out/lifecycle + GOOS=windows $(GOENV) $(GOBUILD) -o ./out/lifecycle -a ./cmd/... + +descriptor: export LIFECYCLE_DESCRIPTOR:=$(LIFECYCLE_DESCRIPTOR) +descriptor: + @echo "> Writing descriptor file..." + mkdir -p ./out + echo "$${LIFECYCLE_DESCRIPTOR}" > ./out/lifecycle.toml + +install-goimports: + @echo "> Installing goimports..." + cd tools; $(GOCMD) install -mod=vendor golang.org/x/tools/cmd/goimports + +install-yj: + @echo "> Installing yj..." + cd tools; $(GOCMD) install -mod=vendor github.com/sclevine/yj + +install-mockgen: + @echo "> Installing mockgen..." + cd tools; $(GOCMD) install -mod=vendor github.com/golang/mock/mockgen + +install-golangci-lint: + @echo "> Installing golangci-lint..." + cd tools; $(GOCMD) install -mod=vendor github.com/golangci/golangci-lint/cmd/golangci-lint + +lint: install-golangci-lint + @echo "> Linting code..." + @golangci-lint run -c golangci.yaml + +generate: install-mockgen + @echo "> Generating..." + $(GOCMD) generate + +format: install-goimports + @echo "> Formating code..." + test -z $$(goimports -l -w -local github.com/buildpacks/lifecycle $$(find . -type f -name '*.go' -not -path "*/vendor/*")) + +test: unit acceptance + +unit: format lint install-yj + @echo "> Running unit tests..." + $(GOTEST) -v -count=1 ./... + +acceptance: format lint + @echo "> Running acceptance tests..." + $(GOTEST) -v -count=1 -tags=acceptance ./acceptance/... + +clean: + @echo "> Cleaning workspace..." + rm -rf ./out + +package: descriptor + @echo "> Packaging lifecycle..." + tar czf ./out/$(ARCHIVE_NAME).tgz -C out lifecycle.toml lifecycle diff --git a/vendor/github.com/buildpacks/lifecycle/README.md b/vendor/github.com/buildpacks/lifecycle/README.md new file mode 100644 index 00000000000..92b8fa8f5f1 --- /dev/null +++ b/vendor/github.com/buildpacks/lifecycle/README.md @@ -0,0 +1,80 @@ +# Lifecycle + +[![Build Status](https://travis-ci.org/buildpacks/lifecycle.svg?branch=master)](https://travis-ci.org/buildpack/lifecycle) +[![GoDoc](https://godoc.org/github.com/buildpacks/lifecycle?status.svg)](https://godoc.org/github.com/buildpacks/lifecycle) + +A reference implementation of [Buildpack API v3](https://github.com/buildpacks/spec). + +## Commands + +### Build + +* `detector` - chooses buildpacks (via `/bin/detect`) +* `analyzer` - restores launch layer metadata from the previous build +* `builder` - executes buildpacks (via `/bin/build`) +* `exporter` - remotely patches images with new layers (via rebase & append) +* `launcher` - invokes choice of process + +### Develop + +* `detector` - chooses buildpacks (via `/bin/detect`) +* `developer` - executes buildpacks (via `/bin/develop`) +* `launcher` - invokes choice of process + +### Cache + +* `restorer` - restores cache +* `cacher` - updates cache + +### Rebase + +* `rebaser` - remotely patches images with new base image + +## Notes + +Cache implementations (`restorer` and `cacher`) are intended to be interchangeable and platform-specific. +A platform may choose not to deduplicate cache layers. + +## Development +To test, build, and package binaries into an archive, simply run: + +```bash +$ make all +``` +This will create an archive at `out/lifecycle-+linux.x86-64.tgz`. + +By default, `LIFECYCLE_VERSION` is `0.0.0`. It can be changed by prepending `LIFECYCLE_VERSION=` to the +`make` command. For example: + +```bash +$ LIFECYCLE_VERSION=1.2.3 make all +``` + +Steps can also be run individually as shown below. + +### Test + +Formats, vets, and tests the code. + +```bash +$ make test +``` + +### Build + +Builds binaries to `out/lifecycle/`. + +```bash +$ make build +``` + +> To clean the `out/` directory, run `make clean`. + +### Package + +Creates an archive at `out/lifecycle-+linux.x86-64.tgz`, using the contents of the +`out/lifecycle/` directory, for the given (or default) `LIFECYCLE_VERSION`. + +```bash +$ make package +``` diff --git a/vendor/github.com/buildpacks/lifecycle/analyzer.go b/vendor/github.com/buildpacks/lifecycle/analyzer.go new file mode 100644 index 00000000000..5b258e6aeb7 --- /dev/null +++ b/vendor/github.com/buildpacks/lifecycle/analyzer.go @@ -0,0 +1,136 @@ +package lifecycle + +import ( + "fmt" + "os" + + "github.com/buildpacks/imgutil" + "github.com/pkg/errors" +) + +type Analyzer struct { + AnalyzedPath string + AppDir string + Buildpacks []Buildpack + GID, UID int + LayersDir string + Logger Logger + SkipLayers bool +} + +// Analyze restores metadata for launch and cache layers into the layers directory. +// If a usable cache is not provided, Analyze will not restore any cache=true layer metadata. +func (a *Analyzer) Analyze(image imgutil.Image, cache Cache) (*AnalyzedMetadata, error) { + imageID, err := a.getImageIdentifier(image) + if err != nil { + return nil, errors.Wrap(err, "retrieving image identifier") + } + + var appMeta LayersMetadata + // continue even if the label cannot be decoded + if err := DecodeLabel(image, LayerMetadataLabel, &appMeta); err != nil { + appMeta = LayersMetadata{} + } + + if a.SkipLayers { + a.Logger.Infof("Skipping buildpack layer analysis") + return &AnalyzedMetadata{ + Image: imageID, + Metadata: appMeta, + }, nil + } + + // Create empty cache metadata in case a usable cache is not provided. + var cacheMeta CacheMetadata + if cache != nil { + var err error + cacheMeta, err = cache.RetrieveMetadata() + if err != nil { + return nil, errors.Wrap(err, "retrieving cache metadata") + } + } else { + a.Logger.Debug("Usable cache not provided, using empty cache metadata.") + } + + for _, buildpack := range a.Buildpacks { + buildpackDir, err := readBuildpackLayersDir(a.LayersDir, buildpack) + if err != nil { + return nil, errors.Wrap(err, "reading buildpack layer directory") + } + + // Restore metadata for launch=true layers. + // The restorer step will restore the layer data for cache=true layers if possible or delete the layer. + appLayers := appMeta.MetadataForBuildpack(buildpack.ID).Layers + for name, layer := range appLayers { + identifier := fmt.Sprintf("%s:%s", buildpack.ID, name) + if !layer.Launch { + a.Logger.Debugf("Not restoring metadata for %q, marked as launch=false", identifier) + continue + } + if layer.Build && !layer.Cache { + a.Logger.Debugf("Not restoring metadata for %q, marked as build=true, cache=false", identifier) + continue + } + a.Logger.Infof("Restoring metadata for %q from app image", identifier) + if err := a.writeLayerMetadata(buildpackDir, name, layer); err != nil { + return nil, err + } + } + + // Restore metadata for cache=true layers. + // The restorer step will restore the layer data if possible or delete the layer. + cachedLayers := cacheMeta.MetadataForBuildpack(buildpack.ID).Layers + for name, layer := range cachedLayers { + identifier := fmt.Sprintf("%s:%s", buildpack.ID, name) + if !layer.Cache { + a.Logger.Debugf("Not restoring %q from cache, marked as cache=false", identifier) + continue + } + // If launch=true, the metadata was restored from the app image or the layer is stale. + if layer.Launch { + a.Logger.Debugf("Not restoring %q from cache, marked as launch=true", identifier) + continue + } + a.Logger.Infof("Restoring metadata for %q from cache", identifier) + if err := a.writeLayerMetadata(buildpackDir, name, layer); err != nil { + return nil, err + } + } + } + + // if analyzer is running as root it needs to fix the ownership of the layers dir + if current := os.Getuid(); current == 0 { + if err := recursiveChown(a.LayersDir, a.UID, a.GID); err != nil { + return nil, errors.Wrapf(err, "chowning layers dir to '%d/%d'", a.UID, a.GID) + } + } + + return &AnalyzedMetadata{ + Image: imageID, + Metadata: appMeta, + }, nil +} + +func (a *Analyzer) getImageIdentifier(image imgutil.Image) (*ImageIdentifier, error) { + if !image.Found() { + a.Logger.Warnf("Image %q not found", image.Name()) + return nil, nil + } + identifier, err := image.Identifier() + if err != nil { + return nil, err + } + a.Logger.Debugf("Analyzing image %q", identifier.String()) + return &ImageIdentifier{ + Reference: identifier.String(), + }, nil +} + +func (a *Analyzer) writeLayerMetadata(buildpackDir bpLayersDir, name string, metadata BuildpackLayerMetadata) error { + layer := buildpackDir.newBPLayer(name) + a.Logger.Debugf("Writing layer metadata for %q", layer.Identifier()) + if err := layer.writeMetadata(metadata); err != nil { + return err + } + return layer.writeSha(metadata.SHA) +} diff --git a/vendor/github.com/buildpacks/lifecycle/archive/tar.go b/vendor/github.com/buildpacks/lifecycle/archive/tar.go new file mode 100644 index 00000000000..452a9c7eb12 --- /dev/null +++ b/vendor/github.com/buildpacks/lifecycle/archive/tar.go @@ -0,0 +1,280 @@ +package archive + +import ( + "archive/tar" + "crypto/sha256" + "encoding/hex" + "fmt" + "io" + "os" + "path/filepath" + "time" +) + +func WriteFilesToTar(dest string, uid, gid int, files ...string) (string, map[string]struct{}, error) { + hasher := sha256.New() + f, err := os.Create(dest) + if err != nil { + return "", nil, err + } + defer f.Close() + + w := io.MultiWriter(hasher, f) + tw := tar.NewWriter(w) + + fileSet := map[string]struct{}{} + for _, file := range files { + if AddFileToArchive(tw, file, uid, gid, fileSet) != nil { + return "", nil, err + } + } + _ = tw.Close() + + sha := hex.EncodeToString(hasher.Sum(make([]byte, 0, hasher.Size()))) + return "sha256:" + sha, fileSet, nil +} + +func AddFileToArchive(tw *tar.Writer, srcDir string, uid, gid int, fileSet map[string]struct{}) error { + err := addParentDirsUnique(srcDir, tw, uid, gid, fileSet) + if err != nil { + return err + } + + return filepath.Walk(srcDir, func(file string, fi os.FileInfo, err error) error { + if _, ok := fileSet[file]; ok { + return nil + } + if err != nil { + return err + } + if fi.Mode()&os.ModeSocket != 0 { + return nil + } + var header *tar.Header + var target string + if fi.Mode()&os.ModeSymlink != 0 { + target, err = os.Readlink(file) + if err != nil { + return err + } + } + header, err = tar.FileInfoHeader(fi, target) + if err != nil { + return err + } + header.Name = file + header.ModTime = time.Date(1980, time.January, 1, 0, 0, 1, 0, time.UTC) + header.Uid = uid + header.Gid = gid + header.Uname = "" + header.Gname = "" + + if err := tw.WriteHeader(header); err != nil { + return err + } + if fi.Mode().IsRegular() { + f, err := os.Open(file) + if err != nil { + return err + } + defer f.Close() + if _, err := io.Copy(tw, f); err != nil { + return err + } + } + + fileSet[file] = struct{}{} + return nil + }) +} + +func WriteTarFile(sourceDir, dest string, uid, gid int) (string, error) { + hasher := sha256.New() + f, err := os.Create(dest) + if err != nil { + return "", err + } + defer f.Close() + w := io.MultiWriter(hasher, f) + + if err := WriteTarArchive(w, sourceDir, uid, gid); err != nil { + return "", err + } + sha := hex.EncodeToString(hasher.Sum(make([]byte, 0, hasher.Size()))) + return "sha256:" + sha, nil +} + +func WriteTarArchive(w io.Writer, srcDir string, uid, gid int) error { + tw := tar.NewWriter(w) + defer tw.Close() + + err := addParentDirs(srcDir, tw, uid, gid) + if err != nil { + return err + } + + return filepath.Walk(srcDir, func(file string, fi os.FileInfo, err error) error { + if err != nil { + return err + } + if fi.Mode()&os.ModeSocket != 0 { + return nil + } + var header *tar.Header + var target string + if fi.Mode()&os.ModeSymlink != 0 { + target, err = os.Readlink(file) + if err != nil { + return err + } + } + header, err = tar.FileInfoHeader(fi, target) + if err != nil { + return err + } + header.Name = file + header.ModTime = time.Date(1980, time.January, 1, 0, 0, 1, 0, time.UTC) + header.Uid = uid + header.Gid = gid + header.Uname = "" + header.Gname = "" + + if err := tw.WriteHeader(header); err != nil { + return err + } + if fi.Mode().IsRegular() { + f, err := os.Open(file) + if err != nil { + return err + } + defer f.Close() + if _, err := io.Copy(tw, f); err != nil { + return err + } + } + return nil + }) +} + +func addParentDirsUnique(tarDir string, tw *tar.Writer, uid, gid int, parentDirs map[string]struct{}) error { + parent := filepath.Dir(tarDir) + if parent == "." || parent == "/" { + return nil + } + + if _, ok := parentDirs[parent]; ok { + return nil + } + + if err := addParentDirsUnique(parent, tw, uid, gid, parentDirs); err != nil { + return err + } + + info, err := os.Stat(parent) + if err != nil { + return err + } + + header, err := tar.FileInfoHeader(info, parent) + if err != nil { + return err + } + header.Name = parent + header.ModTime = time.Date(1980, time.January, 1, 0, 0, 1, 0, time.UTC) + + parentDirs[parent] = struct{}{} + + return tw.WriteHeader(header) +} + +func addParentDirs(tarDir string, tw *tar.Writer, uid, gid int) error { + parent := filepath.Dir(tarDir) + if parent == "." || parent == "/" { + return nil + } + + if err := addParentDirs(parent, tw, uid, gid); err != nil { + return err + } + + info, err := os.Stat(parent) + if err != nil { + return err + } + + header, err := tar.FileInfoHeader(info, parent) + if err != nil { + return err + } + header.Name = parent + header.ModTime = time.Date(1980, time.January, 1, 0, 0, 1, 0, time.UTC) + + return tw.WriteHeader(header) +} + +type PathMode struct { + Path string + Mode os.FileMode +} + +func Untar(r io.Reader, dest string) error { + tr := tar.NewReader(r) + var pathModes []PathMode + for { + hdr, err := tr.Next() + if err == io.EOF { + for _, pathMode := range pathModes { + if err := os.Chmod(pathMode.Path, pathMode.Mode); err != nil { + return err + } + } + return nil + } + if err != nil { + return err + } + + path := filepath.Join(dest, hdr.Name) + + switch hdr.Typeflag { + case tar.TypeDir: + if _, err := os.Stat(path); os.IsNotExist(err) { + pathMode := PathMode{path, hdr.FileInfo().Mode()} + pathModes = append(pathModes, pathMode) + } + if err := os.MkdirAll(path, os.ModePerm); err != nil { + return err + } + case tar.TypeReg, tar.TypeRegA: + _, err := os.Stat(filepath.Dir(path)) + if os.IsNotExist(err) { + if err := os.MkdirAll(filepath.Dir(path), os.ModePerm); err != nil { + return err + } + } + if err := writeFile(tr, path, hdr.FileInfo().Mode()); err != nil { + return err + } + // Update permissions in case umask was applied. + if err := os.Chmod(path, hdr.FileInfo().Mode()); err != nil { + return err + } + case tar.TypeSymlink: + if err := os.Symlink(hdr.Linkname, path); err != nil { + return err + } + default: + return fmt.Errorf("unknown file type in tar %d", hdr.Typeflag) + } + } +} + +func writeFile(in io.Reader, path string, mode os.FileMode) error { + fh, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, mode) + if err != nil { + return err + } + defer fh.Close() + _, err = io.Copy(fh, in) + return err +} diff --git a/vendor/github.com/buildpacks/lifecycle/auth/env_keychain.go b/vendor/github.com/buildpacks/lifecycle/auth/env_keychain.go new file mode 100644 index 00000000000..55ac4f21e31 --- /dev/null +++ b/vendor/github.com/buildpacks/lifecycle/auth/env_keychain.go @@ -0,0 +1,161 @@ +package auth + +import ( + "encoding/base64" + "encoding/json" + "fmt" + "os" + "regexp" + + "github.com/google/go-containerregistry/pkg/authn" + "github.com/google/go-containerregistry/pkg/name" + "github.com/pkg/errors" +) + +// EnvKeychain creates a keychain augmenting the default keychain with information from an environment variable. +// +// See `ReadEnvVar`. +func EnvKeychain(envVar string) authn.Keychain { + return authn.NewMultiKeychain(&envKeychain{envVar: envVar}, authn.DefaultKeychain) +} + +type envKeychain struct { + envVar string +} + +func (k *envKeychain) Resolve(resource authn.Resource) (authn.Authenticator, error) { + authHeaders, err := ReadEnvVar(k.envVar) + if err != nil { + return nil, errors.Wrap(err, "reading auth env var") + } + + header, ok := authHeaders[resource.RegistryStr()] + if ok { + authConfig, err := authHeaderToConfig(header) + if err != nil { + return nil, errors.Wrapf(err, "parsing auth header '%s'", header) + } + + return &providedAuth{config: authConfig}, nil + } + + return authn.Anonymous, nil +} + +type providedAuth struct { + config *authn.AuthConfig +} + +func (p *providedAuth) Authorization() (*authn.AuthConfig, error) { + return p.config, nil +} + +// ReadEnvVar parses an environment variable to produce a map of 'registry url' to 'authorization header'. +// +// Complementary to `BuildEnvVar`. +// +// Example Input: +// {"gcr.io": "Bearer asdf=", "docker.io": "Basic qwerty="} +// +// Example Output: +// gcr.io -> Bearer asdf= +// docker.io -> Basic qwerty= +func ReadEnvVar(envVar string) (map[string]string, error) { + authMap := map[string]string{} + + env := os.Getenv(envVar) + if env != "" { + err := json.Unmarshal([]byte(env), &authMap) + if err != nil { + return nil, errors.Wrapf(err, "failed to parse %s value", envVar) + } + } + + return authMap, nil +} + +// BuildEnvVar creates the contents to use for authentication environment variable. +// +// Complementary to `ReadEnvVar`. +func BuildEnvVar(keychain authn.Keychain, images ...string) (string, error) { + registryAuths := map[string]string{} + + for _, image := range images { + reference, authenticator, err := ReferenceForRepoName(keychain, image) + if err != nil { + return "", nil + } + if authenticator == authn.Anonymous { + continue + } + + authConfig, err := authenticator.Authorization() + if err != nil { + return "", nil + } + + registryAuths[reference.Context().Registry.Name()], err = authConfigToHeader(authConfig) + if err != nil { + return "", nil + } + } + + authData, err := json.Marshal(registryAuths) + if err != nil { + return "", err + } + return string(authData), nil +} + +func authConfigToHeader(config *authn.AuthConfig) (string, error) { + if config.Auth != "" { + return fmt.Sprintf("Basic %s", config.Auth), nil + } + + if config.RegistryToken != "" { + return fmt.Sprintf("Bearer %s", config.RegistryToken), nil + } + + if config.Username != "" && config.Password != "" { + delimited := fmt.Sprintf("%s:%s", config.Username, config.Password) + encoded := base64.StdEncoding.EncodeToString([]byte(delimited)) + return fmt.Sprintf("Basic %s", encoded), nil + } + + return "", nil +} + +var ( + basicAuthRegExp = regexp.MustCompile("(?i)^basic (.*)$") + bearerAuthRegExp = regexp.MustCompile("(?i)^bearer (.*)$") +) + +func authHeaderToConfig(header string) (*authn.AuthConfig, error) { + if matches := basicAuthRegExp.FindAllStringSubmatch(header, -1); len(matches) != 0 { + return &authn.AuthConfig{ + Auth: matches[0][1], + }, nil + } + + if matches := bearerAuthRegExp.FindAllStringSubmatch(header, -1); len(matches) != 0 { + return &authn.AuthConfig{ + RegistryToken: matches[0][1], + }, nil + } + + return nil, errors.Errorf("unknown auth type from header: %s", header) +} + +func ReferenceForRepoName(keychain authn.Keychain, ref string) (name.Reference, authn.Authenticator, error) { + var auth authn.Authenticator + r, err := name.ParseReference(ref, name.WeakValidation) + if err != nil { + return nil, nil, err + } + + auth, err = keychain.Resolve(r.Context().Registry) + if err != nil { + return nil, nil, err + } + return r, auth, nil +} diff --git a/vendor/github.com/buildpacks/lifecycle/builder.go b/vendor/github.com/buildpacks/lifecycle/builder.go new file mode 100644 index 00000000000..8c1be5dc58e --- /dev/null +++ b/vendor/github.com/buildpacks/lifecycle/builder.go @@ -0,0 +1,232 @@ +package lifecycle + +import ( + "io/ioutil" + "log" + "os" + "os/exec" + "path/filepath" + "sort" + + "github.com/BurntSushi/toml" +) + +type Builder struct { + AppDir string + LayersDir string + PlatformDir string + BuildpacksDir string + Env BuildEnv + Group BuildpackGroup + Plan BuildPlan + Out, Err *log.Logger +} + +type BuildEnv interface { + AddRootDir(baseDir string) error + AddEnvDir(envDir string) error + WithPlatform(platformDir string) ([]string, error) + List() []string +} + +type Process struct { + Type string `toml:"type" json:"type"` + Command string `toml:"command" json:"command"` + Args []string `toml:"args" json:"args"` + Direct bool `toml:"direct" json:"direct"` +} + +type Slice struct { + Paths []string `tom:"paths"` +} + +type LaunchTOML struct { + Processes []Process `toml:"processes"` + Slices []Slice `toml:"slices"` +} + +type BOMEntry struct { + Require + Buildpack Buildpack `toml:"buildpack" json:"buildpack"` +} + +type buildpackPlan struct { + Entries []Require `toml:"entries"` +} + +func (b *Builder) Build() (*BuildMetadata, error) { + platformDir, err := filepath.Abs(b.PlatformDir) + if err != nil { + return nil, err + } + layersDir, err := filepath.Abs(b.LayersDir) + if err != nil { + return nil, err + } + appDir, err := filepath.Abs(b.AppDir) + if err != nil { + return nil, err + } + planDir, err := ioutil.TempDir("", "plan.") + if err != nil { + return nil, err + } + defer os.RemoveAll(planDir) + + procMap := processMap{} + plan := b.Plan + var bom []BOMEntry + var slices []Slice + + for _, bp := range b.Group.Group { + bpInfo, err := bp.lookup(b.BuildpacksDir) + if err != nil { + return nil, err + } + bpDirName := bp.dir() + bpLayersDir := filepath.Join(layersDir, bpDirName) + bpPlanDir := filepath.Join(planDir, bpDirName) + if err := os.MkdirAll(bpLayersDir, 0777); err != nil { + return nil, err + } + + if err := os.MkdirAll(bpPlanDir, 0777); err != nil { + return nil, err + } + bpPlanPath := filepath.Join(bpPlanDir, "plan.toml") + if err := WriteTOML(bpPlanPath, plan.find(bp)); err != nil { + return nil, err + } + cmd := exec.Command(filepath.Join(bpInfo.Path, "bin", "build"), bpLayersDir, platformDir, bpPlanPath) + cmd.Dir = appDir + cmd.Stdout = b.Out.Writer() + cmd.Stderr = b.Err.Writer() + if bpInfo.Buildpack.ClearEnv { + cmd.Env = b.Env.List() + } else { + cmd.Env, err = b.Env.WithPlatform(platformDir) + if err != nil { + return nil, err + } + } + if err := cmd.Run(); err != nil { + return nil, err + } + if err := setupEnv(b.Env, bpLayersDir); err != nil { + return nil, err + } + var bpPlanOut buildpackPlan + if _, err := toml.DecodeFile(bpPlanPath, &bpPlanOut); err != nil { + return nil, err + } + var bpBOM []BOMEntry + plan, bpBOM = plan.filter(bp, bpPlanOut) + bom = append(bom, bpBOM...) + + var launch LaunchTOML + tomlPath := filepath.Join(bpLayersDir, "launch.toml") + if _, err := toml.DecodeFile(tomlPath, &launch); os.IsNotExist(err) { + continue + } else if err != nil { + return nil, err + } + procMap.add(launch.Processes) + slices = append(slices, launch.Slices...) + } + + return &BuildMetadata{ + Processes: procMap.list(), + Buildpacks: b.Group.Group, + BOM: bom, + Slices: slices, + }, nil +} + +func (p BuildPlan) find(bp Buildpack) buildpackPlan { + var out []Require + for _, entry := range p.Entries { + for _, provider := range entry.Providers { + if provider == bp { + out = append(out, entry.Requires...) + break + } + } + } + return buildpackPlan{Entries: out} +} + +// TODO: ensure at least one claimed entry of each name is provided by the BP +func (p BuildPlan) filter(bp Buildpack, plan buildpackPlan) (BuildPlan, []BOMEntry) { + var out []BuildPlanEntry + for _, entry := range p.Entries { + if !plan.has(entry) { + out = append(out, entry) + } + } + var bom []BOMEntry + for _, entry := range plan.Entries { + bom = append(bom, BOMEntry{Require: entry, Buildpack: bp}) + } + return BuildPlan{Entries: out}, bom +} + +func (p buildpackPlan) has(entry BuildPlanEntry) bool { + for _, buildEntry := range p.Entries { + for _, req := range entry.Requires { + if req.Name == buildEntry.Name { + return true + } + } + } + return false +} + +func setupEnv(env BuildEnv, layersDir string) error { + if err := eachDir(layersDir, func(path string) error { + if !isBuild(path + ".toml") { + return nil + } + return env.AddRootDir(path) + }); err != nil { + return err + } + + return eachDir(layersDir, func(path string) error { + if !isBuild(path + ".toml") { + return nil + } + if err := env.AddEnvDir(filepath.Join(path, "env")); err != nil { + return err + } + return env.AddEnvDir(filepath.Join(path, "env.build")) + }) +} + +func isBuild(path string) bool { + var layerTOML struct { + Build bool `toml:"build"` + } + _, err := toml.DecodeFile(path, &layerTOML) + return err == nil && layerTOML.Build +} + +type processMap map[string]Process + +func (m processMap) add(l []Process) { + for _, proc := range l { + m[proc.Type] = proc + } +} + +func (m processMap) list() []Process { + var keys []string + for key := range m { + keys = append(keys, key) + } + sort.Strings(keys) + procs := []Process{} + for _, key := range keys { + procs = append(procs, m[key]) + } + return procs +} diff --git a/vendor/github.com/buildpacks/lifecycle/cmd/exit.go b/vendor/github.com/buildpacks/lifecycle/cmd/exit.go new file mode 100644 index 00000000000..d2971f69b92 --- /dev/null +++ b/vendor/github.com/buildpacks/lifecycle/cmd/exit.go @@ -0,0 +1,66 @@ +package cmd + +import ( + "fmt" + "os" + "strings" +) + +const ( + CodeFailed = 1 + // 2: reserved + CodeInvalidArgs = 3 + // 4: CodeInvalidEnv + // 5: CodeNotFound + CodeFailedDetect = 6 + CodeFailedBuild = 7 + CodeFailedLaunch = 8 + // 9: CodeFailedUpdate + CodeFailedSave = 10 +) + +type ErrorFail struct { + Err error + Code int + Action []string +} + +func (e *ErrorFail) Error() string { + message := "failed to " + strings.Join(e.Action, " ") + if e.Err == nil { + return message + } + return fmt.Sprintf("%s: %s", message, e.Err) +} + +func FailCode(code int, action ...string) *ErrorFail { + return FailErrCode(nil, code, action...) +} + +func FailErr(err error, action ...string) *ErrorFail { + code := CodeFailed + if err, ok := err.(*ErrorFail); ok { + code = err.Code + } + return FailErrCode(err, code, action...) +} + +func FailErrCode(err error, code int, action ...string) *ErrorFail { + return &ErrorFail{Err: err, Code: code, Action: action} +} + +func Exit(err error) { + if err == nil { + os.Exit(0) + } + Logger.Errorf("%s\n", err) + if err, ok := err.(*ErrorFail); ok { + os.Exit(err.Code) + } + os.Exit(CodeFailed) +} + +func ExitWithVersion() { + Logger.Infof(buildVersion()) + os.Exit(0) +} diff --git a/vendor/github.com/buildpacks/lifecycle/cmd/flags.go b/vendor/github.com/buildpacks/lifecycle/cmd/flags.go new file mode 100644 index 00000000000..e1defe2b187 --- /dev/null +++ b/vendor/github.com/buildpacks/lifecycle/cmd/flags.go @@ -0,0 +1,185 @@ +package cmd + +import ( + "flag" + "fmt" + "os" + "strconv" + + "github.com/docker/docker/client" + "github.com/pkg/errors" +) + +const ( + DefaultLayersDir = "/layers" + DefaultAppDir = "/workspace" + DefaultBuildpacksDir = "/cnb/buildpacks" + DefaultPlatformDir = "/platform" + DefaultOrderPath = "/cnb/order.toml" + DefaultGroupPath = "./group.toml" + DefaultStackPath = "/cnb/stack.toml" + DefaultAnalyzedPath = "./analyzed.toml" + DefaultPlanPath = "./plan.toml" + DefaultProcessType = "web" + DefaultLauncherPath = "/cnb/lifecycle/launcher" + DefaultLogLevel = "info" + + EnvLayersDir = "CNB_LAYERS_DIR" + EnvAppDir = "CNB_APP_DIR" + EnvBuildpacksDir = "CNB_BUILDPACKS_DIR" + EnvPlatformDir = "CNB_PLATFORM_DIR" + EnvAnalyzedPath = "CNB_ANALYZED_PATH" + EnvOrderPath = "CNB_ORDER_PATH" + EnvGroupPath = "CNB_GROUP_PATH" + EnvStackPath = "CNB_STACK_PATH" + EnvPlanPath = "CNB_PLAN_PATH" + EnvUseDaemon = "CNB_USE_DAEMON" // defaults to false + EnvUseHelpers = "CNB_USE_CRED_HELPERS" // defaults to false + EnvRunImage = "CNB_RUN_IMAGE" + EnvCacheImage = "CNB_CACHE_IMAGE" + EnvCacheDir = "CNB_CACHE_DIR" + EnvLaunchCacheDir = "CNB_LAUNCH_CACHE_DIR" + EnvUID = "CNB_USER_ID" + EnvGID = "CNB_GROUP_ID" + EnvRegistryAuth = "CNB_REGISTRY_AUTH" + EnvSkipLayers = "CNB_ANALYZE_SKIP_LAYERS" // defaults to false + EnvProcessType = "CNB_PROCESS_TYPE" + EnvProcessTypeLegacy = "PACK_PROCESS_TYPE" // deprecated + EnvLogLevel = "CNB_LOG_LEVEL" +) + +func FlagAnalyzedPath(dir *string) { + flag.StringVar(dir, "analyzed", envOrDefault(EnvAnalyzedPath, DefaultAnalyzedPath), "path to analyzed.toml") +} + +func FlagAppDir(dir *string) { + flag.StringVar(dir, "app", envOrDefault(EnvAppDir, DefaultAppDir), "path to app directory") +} + +func FlagBuildpacksDir(dir *string) { + flag.StringVar(dir, "buildpacks", envOrDefault(EnvBuildpacksDir, DefaultBuildpacksDir), "path to buildpacks directory") +} + +func FlagCacheDir(dir *string) { + flag.StringVar(dir, "cache-dir", os.Getenv(EnvCacheDir), "path to cache directory") +} + +func FlagCacheImage(image *string) { + flag.StringVar(image, "cache-image", os.Getenv(EnvCacheImage), "cache image tag name") +} + +func FlagGID(gid *int) { + flag.IntVar(gid, "gid", intEnv(EnvGID), "GID of user's group in the stack's build and run images") +} + +func FlagGroupPath(path *string) { + flag.StringVar(path, "group", envOrDefault(EnvGroupPath, DefaultGroupPath), "path to group.toml") +} + +func FlagLaunchCacheDir(dir *string) { + flag.StringVar(dir, "launch-cache", os.Getenv(EnvLaunchCacheDir), "path to launch cache directory") +} + +func FlagLauncherPath(path *string) { + flag.StringVar(path, "launcher", DefaultLauncherPath, "path to launcher binary") +} + +func FlagLayersDir(dir *string) { + flag.StringVar(dir, "layers", envOrDefault(EnvLayersDir, DefaultLayersDir), "path to layers directory") +} + +func FlagOrderPath(path *string) { + flag.StringVar(path, "order", envOrDefault(EnvOrderPath, DefaultOrderPath), "path to order.toml") +} + +func FlagPlanPath(path *string) { + flag.StringVar(path, "plan", envOrDefault(EnvPlanPath, DefaultPlanPath), "path to plan.toml") +} + +func FlagPlatformDir(dir *string) { + flag.StringVar(dir, "platform", envOrDefault(EnvPlatformDir, DefaultPlatformDir), "path to platform directory") +} + +func FlagRunImage(image *string) { + flag.StringVar(image, "image", os.Getenv(EnvRunImage), "reference to run image") +} + +func FlagStackPath(path *string) { + flag.StringVar(path, "stack", envOrDefault(EnvStackPath, DefaultStackPath), "path to stack.toml") +} + +func FlagUID(uid *int) { + flag.IntVar(uid, "uid", intEnv(EnvUID), "UID of user in the stack's build and run images") +} + +func FlagUseCredHelpers(use *bool) { + flag.BoolVar(use, "helpers", boolEnv(EnvUseHelpers), "use credential helpers") +} + +func FlagUseDaemon(use *bool) { + flag.BoolVar(use, "daemon", boolEnv(EnvUseDaemon), "export to docker daemon") +} + +func FlagSkipLayers(skip *bool) { + flag.BoolVar(skip, "skip-layers", boolEnv(EnvSkipLayers), "do not provide layer metadata to buildpacks") +} + +func FlagVersion(version *bool) { + flag.BoolVar(version, "version", false, "show version") +} + +func FlagLogLevel(level *string) { + flag.StringVar(level, "log-level", envOrDefault(EnvLogLevel, DefaultLogLevel), "logging level") +} + +var ( + // Version is the version of the lifecycle and all produced binaries. It is injected at compile time. + Version = "0.0.0" + // SCMCommit is the commit information provided by SCM. It is injected at compile time. + SCMCommit = "" + // SCMRepository is the source repository. It is injected at compile time. + SCMRepository = "" +) + +// buildVersion is a display format of the version and build metadata in compliance with semver. +func buildVersion() string { + // noinspection GoBoolExpressions + if SCMCommit == "" { + return Version + } + + return fmt.Sprintf("%s+%s", Version, SCMCommit) +} + +func intEnv(k string) int { + v := os.Getenv(k) + d, err := strconv.Atoi(v) + if err != nil { + return 0 + } + return d +} + +func boolEnv(k string) bool { + v := os.Getenv(k) + b, err := strconv.ParseBool(v) + if err != nil { + return false + } + return b +} + +func envOrDefault(key string, defaultVal string) string { + if envVal := os.Getenv(key); envVal != "" { + return envVal + } + return defaultVal +} + +func DockerClient() (*client.Client, error) { + docker, err := client.NewClientWithOpts(client.FromEnv, client.WithVersion("1.38")) + if err != nil { + return nil, errors.Wrap(err, "new docker client") + } + return docker, nil +} diff --git a/vendor/github.com/buildpacks/lifecycle/cmd/logs.go b/vendor/github.com/buildpacks/lifecycle/cmd/logs.go new file mode 100644 index 00000000000..e4b7ea0b65e --- /dev/null +++ b/vendor/github.com/buildpacks/lifecycle/cmd/logs.go @@ -0,0 +1,65 @@ +package cmd + +import ( + "io" + "os" + "sync" + + "github.com/apex/log" + "github.com/heroku/color" +) + +const ( + errorLevelText = "ERROR: " + warnLevelText = "Warning: " +) + +// Default logger +var ( + Logger = &log.Logger{ + Handler: &handler{ + writer: os.Stdout, + }, + } + warnStyle = color.New(color.FgYellow, color.Bold).SprintfFunc() + errorStyle = color.New(color.FgRed, color.Bold).SprintfFunc() +) + +func SetLogLevel(level string) *ErrorFail { + var err error + Logger.Level, err = log.ParseLevel(level) + if err != nil { + return FailErrCode(err, CodeInvalidArgs, "parse log level") + } + + return nil +} + +type handler struct { + mu sync.Mutex + writer io.Writer +} + +func (h *handler) HandleLog(entry *log.Entry) error { + h.mu.Lock() + defer h.mu.Unlock() + + var err error + switch entry.Level { + case log.WarnLevel: + _, err = h.writer.Write([]byte(warnStyle(warnLevelText) + appendMissingLineFeed(entry.Message))) + case log.ErrorLevel: + _, err = h.writer.Write([]byte(errorStyle(errorLevelText) + appendMissingLineFeed(entry.Message))) + default: + _, err = h.writer.Write([]byte(appendMissingLineFeed(entry.Message))) + } + return err +} + +func appendMissingLineFeed(msg string) string { + buff := []byte(msg) + if buff[len(buff)-1] != '\n' { + buff = append(buff, '\n') + } + return string(buff) +} diff --git a/vendor/github.com/buildpacks/lifecycle/cred_helpers.go b/vendor/github.com/buildpacks/lifecycle/cred_helpers.go new file mode 100644 index 00000000000..bf10ebc5fc6 --- /dev/null +++ b/vendor/github.com/buildpacks/lifecycle/cred_helpers.go @@ -0,0 +1,80 @@ +package lifecycle + +import ( + "encoding/json" + "errors" + "os" + "path/filepath" + "regexp" + + "github.com/google/go-containerregistry/pkg/name" +) + +func SetupCredHelpers(dockerPath string, refs ...string) error { + configPath := filepath.Join(dockerPath, "config.json") + + config := map[string]interface{}{} + if f, err := os.Open(configPath); err == nil { + err := json.NewDecoder(f).Decode(&config) + if f.Close(); err != nil { + return err + } + } else if !os.IsNotExist(err) { + return err + } + + if _, ok := config["credHelpers"]; !ok { + config["credHelpers"] = make(map[string]interface{}) + } + + credHelpers := make(map[string]string) + for _, refStr := range refs { + ref, err := name.ParseReference(refStr, name.WeakValidation) + if err != nil { + return err + } + + registry := ref.Context().RegistryStr() + for _, ch := range []struct { + domain string + helper string + }{ + {"([.]|^)gcr[.]io$", "gcr"}, + {"[.]amazonaws[.]", "ecr-login"}, + {"([.]|^)azurecr[.]io$", "acr"}, + } { + match, err := regexp.MatchString("(?i)"+ch.domain, registry) + if err != nil || !match { + continue + } + credHelpers[registry] = ch.helper + } + } + + if len(credHelpers) == 0 { + return nil + } + + ch, ok := config["credHelpers"].(map[string]interface{}) + if !ok { + return errors.New("failed to parse docker config 'credHelpers'") + } + + for k, v := range credHelpers { + if _, ok := ch[k]; !ok { + ch[k] = v + } + } + + if err := os.MkdirAll(dockerPath, 0777); err != nil { + return err + } + + f, err := os.Create(configPath) + if err != nil { + return err + } + defer f.Close() + + return json.NewEncoder(f).Encode(config) +} diff --git a/vendor/github.com/buildpacks/lifecycle/detector.go b/vendor/github.com/buildpacks/lifecycle/detector.go new file mode 100644 index 00000000000..82964bade91 --- /dev/null +++ b/vendor/github.com/buildpacks/lifecycle/detector.go @@ -0,0 +1,486 @@ +package lifecycle + +import ( + "bytes" + "fmt" + "io/ioutil" + "os" + "os/exec" + "path/filepath" + "sync" + "syscall" + + "github.com/BurntSushi/toml" + "github.com/pkg/errors" +) + +const ( + CodeDetectPass = 0 + CodeDetectFail = 100 +) + +var ErrFail = errors.New("no buildpacks participating") + +type Buildpack struct { + ID string `toml:"id" json:"id"` + Version string `toml:"version" json:"version"` + Optional bool `toml:"optional,omitempty" json:"optional,omitempty"` +} + +func (bp Buildpack) dir() string { + return escapeID(bp.ID) +} + +func (bp Buildpack) String() string { + return bp.ID + "@" + bp.Version +} + +func (bp Buildpack) noOpt() Buildpack { + bp.Optional = false + return bp +} + +type BuildPlan struct { + Entries []BuildPlanEntry `toml:"entries"` +} + +type BuildPlanEntry struct { + Providers []Buildpack `toml:"providers"` + Requires []Require `toml:"requires"` +} + +func (be BuildPlanEntry) noOpt() BuildPlanEntry { + var out []Buildpack + for _, p := range be.Providers { + out = append(out, p.noOpt()) + } + be.Providers = out + return be +} + +type Require struct { + Name string `toml:"name" json:"name"` + Version string `toml:"version" json:"version"` + Metadata map[string]interface{} `toml:"metadata" json:"metadata"` +} + +type Provide struct { + Name string `toml:"name"` +} + +type DetectConfig struct { + FullEnv []string + ClearEnv []string + AppDir string + PlatformDir string + BuildpacksDir string + Logger Logger + runs *sync.Map +} + +func (bp Buildpack) lookup(buildpacksDir string) (*buildpackTOML, error) { + bpTOML := buildpackTOML{} + bpPath, err := filepath.Abs(filepath.Join(buildpacksDir, bp.dir(), bp.Version)) + if err != nil { + return nil, err + } + tomlPath := filepath.Join(bpPath, "buildpack.toml") + if _, err := toml.DecodeFile(tomlPath, &bpTOML); err != nil { + return nil, err + } + bpTOML.Path = bpPath + return &bpTOML, nil +} + +func (c *DetectConfig) process(done []Buildpack) ([]Buildpack, []BuildPlanEntry, error) { + var runs []detectRun + for _, bp := range done { + t, ok := c.runs.Load(bp.String()) + if !ok { + return nil, nil, errors.Errorf("missing detection of '%s'", bp) + } + run := t.(detectRun) + if len(run.Output) > 0 { + c.Logger.Debugf("======== Output: %s ========", bp) + c.Logger.Debug(string(run.Output)) + } + if run.Err != nil { + c.Logger.Debugf("======== Error: %s ========", bp) + c.Logger.Debug(run.Err.Error()) + } + runs = append(runs, run) + } + + c.Logger.Debugf("======== Results ========") + + results := detectResults{} + detected := true + for i, bp := range done { + run := runs[i] + switch run.Code { + case CodeDetectPass: + c.Logger.Debugf("pass: %s", bp) + results = append(results, detectResult{bp, run}) + case CodeDetectFail: + if bp.Optional { + c.Logger.Debugf("skip: %s", bp) + } else { + c.Logger.Debugf("fail: %s", bp) + } + detected = detected && bp.Optional + case -1: + c.Logger.Debugf("err: %s", bp) + detected = detected && bp.Optional + default: + c.Logger.Debugf("err: %s (%d)", bp, run.Code) + detected = detected && bp.Optional + } + } + if !detected { + return nil, nil, ErrFail + } + + i := 0 + deps, trial, err := results.runTrials(func(trial detectTrial) (depMap, detectTrial, error) { + i++ + return c.runTrial(i, trial) + }) + if err != nil { + return nil, nil, err + } + + if len(done) != len(trial) { + c.Logger.Infof("%d of %d buildpacks participating", len(trial), len(done)) + } + + maxLength := 0 + for _, t := range trial { + l := len(t.ID) + if l > maxLength { + maxLength = l + } + } + + f := fmt.Sprintf("%%-%ds %%s", maxLength) + + for _, t := range trial { + c.Logger.Infof(f, t.ID, t.Version) + } + + var found []Buildpack + for _, r := range trial { + found = append(found, r.Buildpack.noOpt()) + } + var plan []BuildPlanEntry + for _, dep := range deps { + plan = append(plan, dep.BuildPlanEntry.noOpt()) + } + return found, plan, nil +} + +func (c *DetectConfig) runTrial(i int, trial detectTrial) (depMap, detectTrial, error) { + c.Logger.Debugf("Resolving plan... (try #%d)", i) + + var deps depMap + retry := true + for retry { + retry = false + deps = newDepMap(trial) + + if err := deps.eachUnmetRequire(func(name string, bp Buildpack) error { + retry = true + if !bp.Optional { + c.Logger.Debugf("fail: %s requires %s", bp, name) + return ErrFail + } + c.Logger.Debugf("skip: %s requires %s", bp, name) + trial = trial.remove(bp) + return nil + }); err != nil { + return nil, nil, err + } + + if err := deps.eachUnmetProvide(func(name string, bp Buildpack) error { + retry = true + if !bp.Optional { + c.Logger.Debugf("fail: %s provides unused %s", bp, name) + return ErrFail + } + c.Logger.Debugf("skip: %s provides unused %s", bp, name) + trial = trial.remove(bp) + return nil + }); err != nil { + return nil, nil, err + } + } + + if len(trial) == 0 { + c.Logger.Debugf("fail: no viable buildpacks in group") + return nil, nil, ErrFail + } + return deps, trial, nil +} + +func (bp *buildpackTOML) Detect(c *DetectConfig) detectRun { + appDir, err := filepath.Abs(c.AppDir) + if err != nil { + return detectRun{Code: -1, Err: err} + } + platformDir, err := filepath.Abs(c.PlatformDir) + if err != nil { + return detectRun{Code: -1, Err: err} + } + planDir, err := ioutil.TempDir("", "plan.") + if err != nil { + return detectRun{Code: -1, Err: err} + } + defer os.RemoveAll(planDir) + planPath := filepath.Join(planDir, "plan.toml") + if err := ioutil.WriteFile(planPath, nil, 0777); err != nil { + return detectRun{Code: -1, Err: err} + } + out := &bytes.Buffer{} + cmd := exec.Command(filepath.Join(bp.Path, "bin", "detect"), platformDir, planPath) + cmd.Dir = appDir + cmd.Stdout = out + cmd.Stderr = out + cmd.Env = c.FullEnv + if bp.Buildpack.ClearEnv { + cmd.Env = c.ClearEnv + } + + if err := cmd.Run(); err != nil { + if err, ok := err.(*exec.ExitError); ok { + if status, ok := err.Sys().(syscall.WaitStatus); ok { + return detectRun{Code: status.ExitStatus(), Output: out.Bytes()} + } + } + return detectRun{Code: -1, Err: err, Output: out.Bytes()} + } + var t detectRun + if _, err := toml.DecodeFile(planPath, &t); err != nil { + return detectRun{Code: -1, Err: err} + } + t.Output = out.Bytes() + return t +} + +type BuildpackGroup struct { + Group []Buildpack `toml:"group"` +} + +func (bg BuildpackGroup) Detect(c *DetectConfig) (BuildpackGroup, BuildPlan, error) { + if c.runs == nil { + c.runs = &sync.Map{} + } + bps, entries, err := bg.detect(nil, &sync.WaitGroup{}, c) + return BuildpackGroup{Group: bps}, BuildPlan{Entries: entries}, err +} + +func (bg BuildpackGroup) detect(done []Buildpack, wg *sync.WaitGroup, c *DetectConfig) ([]Buildpack, []BuildPlanEntry, error) { + for i, bp := range bg.Group { + key := bp.String() + if hasID(done, bp.ID) { + continue + } + info, err := bp.lookup(c.BuildpacksDir) + if err != nil { + return nil, nil, err + } + if info.Order != nil { + // TODO: double-check slice safety here + // FIXME: cyclical references lead to infinite recursion + return info.Order.detect(done, bg.Group[i+1:], bp.Optional, wg, c) + } + done = append(done, bp) + wg.Add(1) + go func() { + if _, ok := c.runs.Load(key); !ok { + c.runs.Store(key, info.Detect(c)) + } + wg.Done() + }() + } + + wg.Wait() + + return c.process(done) +} + +func (bg BuildpackGroup) append(group ...BuildpackGroup) BuildpackGroup { + for _, g := range group { + bg.Group = append(bg.Group, g.Group...) + } + return bg +} + +type BuildpackOrder []BuildpackGroup + +func (bo BuildpackOrder) Detect(c *DetectConfig) (BuildpackGroup, BuildPlan, error) { + if c.runs == nil { + c.runs = &sync.Map{} + } + bps, entries, err := bo.detect(nil, nil, false, &sync.WaitGroup{}, c) + return BuildpackGroup{Group: bps}, BuildPlan{Entries: entries}, err +} + +func (bo BuildpackOrder) detect(done, next []Buildpack, optional bool, wg *sync.WaitGroup, c *DetectConfig) ([]Buildpack, []BuildPlanEntry, error) { + ngroup := BuildpackGroup{Group: next} + for _, group := range bo { + // FIXME: double-check slice safety here + found, plan, err := group.append(ngroup).detect(done, wg, c) + if err == ErrFail { + wg = &sync.WaitGroup{} + continue + } + return found, plan, err + } + if optional { + return ngroup.detect(done, wg, c) + } + return nil, nil, ErrFail +} + +func hasID(bps []Buildpack, id string) bool { + for _, bp := range bps { + if bp.ID == id { + return true + } + } + return false +} + +type detectRun struct { + planSections + Or []planSections `toml:"or"` + Output []byte `toml:"-"` + Code int `toml:"-"` + Err error `toml:"-"` +} + +type planSections struct { + Requires []Require `toml:"requires"` + Provides []Provide `toml:"provides"` +} + +type detectResult struct { + Buildpack + detectRun +} + +func (r *detectResult) options() []detectOption { + var out []detectOption + for i, sections := range append([]planSections{r.planSections}, r.Or...) { + bp := r.Buildpack + bp.Optional = bp.Optional && i == len(r.Or) + out = append(out, detectOption{bp, sections}) + } + return out +} + +type detectResults []detectResult +type trialFunc func(detectTrial) (depMap, detectTrial, error) + +func (rs detectResults) runTrials(f trialFunc) (depMap, detectTrial, error) { + return rs.runTrialsFrom(nil, f) +} + +func (rs detectResults) runTrialsFrom(prefix detectTrial, f trialFunc) (depMap, detectTrial, error) { + if len(rs) == 0 { + deps, trial, err := f(prefix) + return deps, trial, err + } + + var lastErr error + for _, option := range rs[0].options() { + deps, trial, err := rs[1:].runTrialsFrom(append(prefix, option), f) + if err == nil { + return deps, trial, nil + } + lastErr = err + } + return nil, nil, lastErr +} + +type detectOption struct { + Buildpack + planSections +} + +type detectTrial []detectOption + +func (ts detectTrial) remove(bp Buildpack) detectTrial { + var out detectTrial + for _, t := range ts { + if t.Buildpack != bp { + out = append(out, t) + } + } + return out +} + +type depEntry struct { + BuildPlanEntry + earlyRequires []Buildpack + extraProvides []Buildpack +} + +type depMap map[string]depEntry + +func newDepMap(trial detectTrial) depMap { + m := depMap{} + for _, option := range trial { + for _, p := range option.Provides { + m.provide(option.Buildpack, p) + } + for _, r := range option.Requires { + m.require(option.Buildpack, r) + } + } + return m +} + +func (m depMap) provide(bp Buildpack, provide Provide) { + entry := m[provide.Name] + entry.extraProvides = append(entry.extraProvides, bp) + m[provide.Name] = entry +} + +func (m depMap) require(bp Buildpack, require Require) { + entry := m[require.Name] + entry.Providers = append(entry.Providers, entry.extraProvides...) + entry.extraProvides = nil + + if len(entry.Providers) == 0 { + entry.earlyRequires = append(entry.earlyRequires, bp) + } else { + entry.Requires = append(entry.Requires, require) + } + m[require.Name] = entry +} + +func (m depMap) eachUnmetProvide(f func(name string, bp Buildpack) error) error { + for name, entry := range m { + if len(entry.extraProvides) != 0 { + for _, bp := range entry.extraProvides { + if err := f(name, bp); err != nil { + return err + } + } + } + } + return nil +} + +func (m depMap) eachUnmetRequire(f func(name string, bp Buildpack) error) error { + for name, entry := range m { + if len(entry.earlyRequires) != 0 { + for _, bp := range entry.earlyRequires { + if err := f(name, bp); err != nil { + return err + } + } + } + } + return nil +} diff --git a/vendor/github.com/buildpacks/lifecycle/env.go b/vendor/github.com/buildpacks/lifecycle/env.go new file mode 100644 index 00000000000..6ca4d11ca22 --- /dev/null +++ b/vendor/github.com/buildpacks/lifecycle/env.go @@ -0,0 +1,156 @@ +package lifecycle + +import ( + "io/ioutil" + "os" + "path/filepath" + "strings" +) + +type Env struct { + LookupEnv func(key string) (string, bool) + Getenv func(key string) string + Setenv func(key, value string) error + Unsetenv func(key string) error + Environ func() []string + Map map[string][]string +} + +func (p *Env) AddRootDir(baseDir string) error { + absBaseDir, err := filepath.Abs(baseDir) + if err != nil { + return err + } + for dir, vars := range p.Map { + newDir := filepath.Join(absBaseDir, dir) + if _, err := os.Stat(newDir); os.IsNotExist(err) { + continue + } else if err != nil { + return err + } + for _, key := range vars { + value := newDir + prefix(p.Getenv(key), os.PathListSeparator) + if err := p.Setenv(key, value); err != nil { + return err + } + } + } + return nil +} + +func (p *Env) AddEnvDir(envDir string) error { + return eachEnvFile(envDir, func(k, v string) error { + parts := strings.SplitN(k, ".", 2) + name := parts[0] + var action string + if len(parts) > 1 { + action = parts[1] + } + switch action { + case "prepend": + return p.Setenv(name, v+prefix(p.Getenv(name), delim(envDir, name)...)) + case "append": + return p.Setenv(name, suffix(p.Getenv(name), delim(envDir, name)...)+v) + case "override": + return p.Setenv(name, v) + case "default": + if p.Getenv(name) != "" { + return nil + } + return p.Setenv(name, v) + case "": + return p.Setenv(name, v+prefix(p.Getenv(name), delim(envDir, name, os.PathListSeparator)...)) + default: + return nil + } + }) +} + +func (p *Env) WithPlatform(platformDir string) (out []string, err error) { + restore := map[string]*string{} + defer func() { + for k, v := range restore { + var rErr error + if v == nil { + rErr = p.Unsetenv(k) + } else { + rErr = p.Setenv(k, *v) + } + if err == nil { + err = rErr + } + } + }() + if err := eachEnvFile(filepath.Join(platformDir, "env"), func(k, v string) error { + restore[k] = nil + if old, ok := p.LookupEnv(k); ok { + restore[k] = &old + } + if p.isRootEnv(k) { + return p.Setenv(k, v+prefix(p.Getenv(k), os.PathListSeparator)) + } + return p.Setenv(k, v) + }); err != nil { + return nil, err + } + return p.List(), nil +} + +func (p *Env) List() []string { + return p.Environ() +} + +func prefix(s string, prefix ...byte) string { + if s == "" { + return "" + } + return string(prefix) + s +} + +func suffix(s string, suffix ...byte) string { + if s == "" { + return "" + } + return s + string(suffix) +} + +func delim(dir, name string, def ...byte) []byte { + value, err := ioutil.ReadFile(filepath.Join(dir, name+".delim")) + if err != nil { + return def + } + return value +} + +func eachEnvFile(dir string, fn func(k, v string) error) error { + files, err := ioutil.ReadDir(dir) + if os.IsNotExist(err) { + return nil + } else if err != nil { + return err + } + for _, f := range files { + if f.IsDir() { + continue + } + value, err := ioutil.ReadFile(filepath.Join(dir, f.Name())) + if err != nil { + return err + } + if err := fn(f.Name(), string(value)); err != nil { + return err + } + } + return nil +} + +func (p *Env) isRootEnv(name string) bool { + for _, m := range p.Map { + for _, k := range m { + if k == name { + return true + } + } + } + return false +} diff --git a/vendor/github.com/buildpacks/lifecycle/exporter.go b/vendor/github.com/buildpacks/lifecycle/exporter.go new file mode 100644 index 00000000000..ba140ccc3fa --- /dev/null +++ b/vendor/github.com/buildpacks/lifecycle/exporter.go @@ -0,0 +1,425 @@ +package lifecycle + +import ( + "encoding/json" + "fmt" + "io" + "os" + "path/filepath" + "sort" + "strings" + + "github.com/BurntSushi/toml" + "github.com/buildpacks/imgutil" + "github.com/pkg/errors" + + "github.com/buildpacks/lifecycle/archive" + "github.com/buildpacks/lifecycle/cmd" +) + +//go:generate mockgen -package testmock -destination testmock/cache.go github.com/buildpacks/lifecycle Cache +type Cache interface { + Name() string + SetMetadata(metadata CacheMetadata) error + RetrieveMetadata() (CacheMetadata, error) + AddLayerFile(sha string, tarPath string) error + ReuseLayer(sha string) error + RetrieveLayer(sha string) (io.ReadCloser, error) + Commit() error +} + +type Exporter struct { + Buildpacks []Buildpack + ArtifactsDir string + Logger Logger + UID, GID int + tarHashes map[string]string // Stores hashes of layer tarballs for reuse between the export and cache steps. +} + +type LauncherConfig struct { + Path string + Metadata LauncherMetadata +} + +type SliceLayer struct { + ID string + TarPath string + SHA string +} + +func (e *Exporter) Export( + layersDir, + appDir string, + workingImage imgutil.Image, + runImageRef string, + origMetadata LayersMetadata, + additionalNames []string, + launcherConfig LauncherConfig, + stack StackMetadata, +) error { + var err error + + meta := LayersMetadata{} + meta.RunImage.TopLayer, err = workingImage.TopLayer() + if err != nil { + return errors.Wrap(err, "get run image top layer SHA") + } + + meta.RunImage.Reference = runImageRef + meta.Stack = stack + + buildMD := &BuildMetadata{} + if _, err := toml.DecodeFile(MetadataFilePath(layersDir), buildMD); err != nil { + return errors.Wrap(err, "read build metadata") + } + + // creating app layers (slices + app dir) + appSlices, err := e.createAppSliceLayers(workingImage, &layer{path: appDir, identifier: "app"}, buildMD.Slices) + if err != nil { + return errors.Wrap(err, "creating app layers") + } + + // launcher + meta.Launcher.SHA, err = e.addOrReuseLayer(workingImage, &layer{path: launcherConfig.Path, identifier: "launcher"}, origMetadata.Launcher.SHA) + if err != nil { + return errors.Wrap(err, "exporting launcher layer") + } + + // layers + for _, bp := range e.Buildpacks { + bpDir, err := readBuildpackLayersDir(layersDir, bp) + if err != nil { + return errors.Wrapf(err, "reading layers for buildpack '%s'", bp.ID) + } + bpMD := BuildpackLayersMetadata{ + ID: bp.ID, + Version: bp.Version, + Layers: map[string]BuildpackLayerMetadata{}, + } + for _, layer := range bpDir.findLayers(launch) { + layer := layer + lmd, err := layer.read() + if err != nil { + return errors.Wrapf(err, "reading '%s' metadata", layer.Identifier()) + } + + if layer.hasLocalContents() { + origLayerMetadata := origMetadata.MetadataForBuildpack(bp.ID).Layers[layer.name()] + lmd.SHA, err = e.addOrReuseLayer(workingImage, &layer, origLayerMetadata.SHA) + if err != nil { + return err + } + } else { + if lmd.Cache { + return fmt.Errorf("layer '%s' is cache=true but has no contents", layer.Identifier()) + } + origLayerMetadata, ok := origMetadata.MetadataForBuildpack(bp.ID).Layers[layer.name()] + if !ok { + return fmt.Errorf("cannot reuse '%s', previous image has no metadata for layer '%s'", layer.Identifier(), layer.Identifier()) + } + + e.Logger.Infof("Reusing layer '%s'\n", layer.Identifier()) + e.Logger.Debugf("Layer '%s' SHA: %s\n", layer.Identifier(), origLayerMetadata.SHA) + if err := workingImage.ReuseLayer(origLayerMetadata.SHA); err != nil { + return errors.Wrapf(err, "reusing layer: '%s'", layer.Identifier()) + } + lmd.SHA = origLayerMetadata.SHA + } + bpMD.Layers[layer.name()] = lmd + } + meta.Buildpacks = append(meta.Buildpacks, bpMD) + + if malformedLayers := bpDir.findLayers(malformed); len(malformedLayers) > 0 { + ids := make([]string, 0, len(malformedLayers)) + for _, ml := range malformedLayers { + ids = append(ids, ml.Identifier()) + } + return fmt.Errorf("failed to parse metadata for layers '%s'", ids) + } + } + + // app + meta.App, err = e.addSliceLayers(workingImage, appSlices, origMetadata.App) + if err != nil { + return errors.Wrap(err, "exporting slice layers") + } + + // config + meta.Config.SHA, err = e.addOrReuseLayer(workingImage, &layer{path: filepath.Join(layersDir, "config"), identifier: "config"}, origMetadata.Config.SHA) + if err != nil { + return errors.Wrap(err, "exporting config layer") + } + + data, err := json.Marshal(meta) + if err != nil { + return errors.Wrap(err, "marshall metadata") + } + + if err = workingImage.SetLabel(LayerMetadataLabel, string(data)); err != nil { + return errors.Wrap(err, "set app image metadata label") + } + + buildMD.Launcher = launcherConfig.Metadata + buildJSON, err := json.Marshal(buildMD) + if err != nil { + return errors.Wrap(err, "parse build metadata") + } + if err := workingImage.SetLabel(BuildMetadataLabel, string(buildJSON)); err != nil { + return errors.Wrap(err, "set build image metadata label") + } + + if err = workingImage.SetEnv(cmd.EnvLayersDir, layersDir); err != nil { + return errors.Wrapf(err, "set app image env %s", cmd.EnvLayersDir) + } + + if err = workingImage.SetEnv(cmd.EnvAppDir, appDir); err != nil { + return errors.Wrapf(err, "set app image env %s", cmd.EnvAppDir) + } + + if err = workingImage.SetEntrypoint(launcherConfig.Path); err != nil { + return errors.Wrap(err, "setting entrypoint") + } + + if err = workingImage.SetCmd(); err != nil { // Note: Command intentionally empty + return errors.Wrap(err, "setting cmd") + } + + return saveImage(workingImage, additionalNames, e.Logger) +} + +func (e *Exporter) Cache(layersDir string, cacheStore Cache) error { + var err error + origMeta, err := cacheStore.RetrieveMetadata() + if err != nil { + return errors.Wrap(err, "metadata for previous cache") + } + meta := CacheMetadata{} + + for _, bp := range e.Buildpacks { + bpDir, err := readBuildpackLayersDir(layersDir, bp) + if err != nil { + return errors.Wrapf(err, "reading layers for buildpack '%s'", bp.ID) + } + + bpMD := BuildpackLayersMetadata{ + ID: bp.ID, + Version: bp.Version, + Layers: map[string]BuildpackLayerMetadata{}, + } + for _, layer := range bpDir.findLayers(cached) { + layer := layer + if !layer.hasLocalContents() { + return fmt.Errorf("failed to cache layer '%s' because it has no contents", layer.Identifier()) + } + lmd, err := layer.read() + if err != nil { + return errors.Wrapf(err, "reading %q metadata", layer.Identifier()) + } + origLayerMetadata := origMeta.MetadataForBuildpack(bp.ID).Layers[layer.name()] + if lmd.SHA, err = e.addOrReuseCacheLayer(cacheStore, &layer, origLayerMetadata.SHA); err != nil { + return err + } + bpMD.Layers[layer.name()] = lmd + } + meta.Buildpacks = append(meta.Buildpacks, bpMD) + } + + if err := cacheStore.SetMetadata(meta); err != nil { + return errors.Wrap(err, "setting cache metadata") + } + if err := cacheStore.Commit(); err != nil { + return errors.Wrap(err, "committing cache") + } + + return nil +} + +func (e *Exporter) tarLayer(layer identifiableLayer) (string, string, error) { + tarPath := filepath.Join(e.ArtifactsDir, escapeID(layer.Identifier())+".tar") + if e.tarHashes == nil { + e.tarHashes = make(map[string]string) + } + if sha, ok := e.tarHashes[tarPath]; ok { + e.Logger.Debugf("Reusing tarball for layer %q with SHA: %s\n", layer.Identifier(), sha) + return tarPath, sha, nil + } + e.Logger.Debugf("Writing tarball for layer %q\n", layer.Identifier()) + sha, err := archive.WriteTarFile(layer.Path(), tarPath, e.UID, e.GID) + if err != nil { + return "", "", err + } + e.tarHashes[tarPath] = sha + return tarPath, sha, nil +} + +func (e *Exporter) addOrReuseLayer(image imgutil.Image, layer identifiableLayer, previousSHA string) (string, error) { + tarPath, sha, err := e.tarLayer(layer) + if err != nil { + return "", errors.Wrapf(err, "tarring layer '%s'", layer.Identifier()) + } + if sha == previousSHA { + e.Logger.Infof("Reusing layer '%s'\n", layer.Identifier()) + e.Logger.Debugf("Layer '%s' SHA: %s\n", layer.Identifier(), sha) + return sha, image.ReuseLayer(previousSHA) + } + e.Logger.Infof("Adding layer '%s'\n", layer.Identifier()) + e.Logger.Debugf("Layer '%s' SHA: %s\n", layer.Identifier(), sha) + return sha, image.AddLayer(tarPath) +} + +func (e *Exporter) addOrReuseCacheLayer(cache Cache, layer identifiableLayer, previousSHA string) (string, error) { + tarPath, sha, err := e.tarLayer(layer) + if err != nil { + return "", errors.Wrapf(err, "tarring layer %q", layer.Identifier()) + } + if sha == previousSHA { + e.Logger.Infof("Reusing cache layer '%s'\n", layer.Identifier()) + e.Logger.Debugf("Layer '%s' SHA: %s\n", layer.Identifier(), sha) + return sha, cache.ReuseLayer(previousSHA) + } + e.Logger.Infof("Adding cache layer '%s'\n", layer.Identifier()) + e.Logger.Debugf("Layer '%s' SHA: %s\n", layer.Identifier(), sha) + return sha, cache.AddLayerFile(sha, tarPath) +} + +func (e *Exporter) createAppSliceLayers(image imgutil.Image, appLayer identifiableLayer, slices []Slice) ([]SliceLayer, error) { + var appSlices []SliceLayer + + for index, slice := range slices { + var allGlobMatches []string + for _, path := range slice.Paths { + globMatches, err := filepath.Glob(e.toAbs(appLayer.Path(), path)) + if err != nil { + return nil, errors.Wrap(err, "bad pattern for glob path") + } + allGlobMatches = append(allGlobMatches, globMatches...) + } + sliceLayerID := fmt.Sprintf("slice-%d", index+1) + sliceLayer, err := e.createSliceLayer(image, sliceLayerID, allGlobMatches) + if err != nil { + return nil, errors.Wrap(err, "creating slice layer") + } + appSlices = append(appSlices, sliceLayer) + } + + // finish-up by creating the actual app dir layer and place it at the end of the app slices + // ------------- + // | slice 1 | + // ------------- + // | slice 2 | + // ------------- + // | slice N | + // ------------- + // | app dir | + // ------------- + tarPath := filepath.Join(e.ArtifactsDir, escapeID(appLayer.Identifier())+".tar") + sha, err := archive.WriteTarFile(appLayer.Path(), tarPath, e.UID, e.GID) + if err != nil { + return nil, errors.Wrapf(err, "exporting layer '%s'", appLayer.Identifier()) + } + + return append(appSlices, SliceLayer{ + ID: appLayer.Identifier(), + SHA: sha, + TarPath: tarPath, + }), nil +} + +func (e *Exporter) createSliceLayer(image imgutil.Image, layerID string, files []string) (SliceLayer, error) { + tarPath := filepath.Join(e.ArtifactsDir, escapeID(layerID)+".tar") + sha, fileSet, err := archive.WriteFilesToTar(tarPath, e.UID, e.GID, files...) + if err != nil { + return SliceLayer{}, errors.Wrapf(err, "exporting slice layer '%s'", layerID) + } + + // for this first iteration, just delete the actual files then revisit + // the directories and delete if empty as a result of previous removal + var dirs []string + for file := range fileSet { + stat, _ := os.Stat(file) + if !stat.IsDir() { + err = os.Remove(file) + if err != nil { + e.Logger.Errorf("failed to delete file %v", err) + } + } else { + dirs = append(dirs, file) + } + } + // sort the dirs by their path depth (deepest -> most shallow) to avoid NOT being able to delete a high level dir + // that nested empty dirs. + sort.SliceStable(dirs, func(i, j int) bool { + return len(strings.Split(dirs[i], string(os.PathSeparator))) > len(strings.Split(dirs[j], string(os.PathSeparator))) + }) + for _, dir := range dirs { + if ok, err := isEmptyDir(dir); ok { + if err != nil { + e.Logger.Errorf("failed to check if directory is empty %v", err) + } + err = os.Remove(dir) + if err != nil { + e.Logger.Errorf("failed to delete directory %v", err) + } + } + } + + return SliceLayer{ + ID: layerID, + SHA: sha, + TarPath: tarPath, + }, nil +} + +func (e *Exporter) addSliceLayers(image imgutil.Image, sliceLayers []SliceLayer, previousAppMD []LayerMetadata) ([]LayerMetadata, error) { + var numberOfReusedLayers int + var appMD []LayerMetadata + + for _, slice := range sliceLayers { + var err error + + found := false + for _, previous := range previousAppMD { + if slice.SHA == previous.SHA { + found = true + break + } + } + if found { + err = image.ReuseLayer(slice.SHA) + numberOfReusedLayers++ + } else { + err = image.AddLayer(slice.TarPath) + } + if err != nil { + return nil, err + } + e.Logger.Debugf("Layer '%s' SHA: %s\n", slice.ID, slice.SHA) + appMD = append(appMD, LayerMetadata{SHA: slice.SHA}) + } + + delta := len(sliceLayers) - numberOfReusedLayers + if numberOfReusedLayers > 0 { + e.Logger.Infof("Reusing %d/%d app layer(s)\n", numberOfReusedLayers, len(sliceLayers)) + } + if delta != 0 { + e.Logger.Infof("Adding %d/%d app layer(s)\n", delta, len(sliceLayers)) + } + + return appMD, nil +} + +func (e *Exporter) toAbs(baseDir, path string) string { + path = filepath.Clean(path) + + // force relative path to be absolute from the base dir + if !filepath.IsAbs(path) { + path = filepath.Join(baseDir, path) + } + // force an absolute path to be absolute from base dir + if len(path) > len(baseDir) && path[:len(baseDir)] != baseDir { + path = filepath.Join(baseDir, path) + e.Logger.Warnf("found absolute path %s outside of %s", path, baseDir) + } + + return path +} diff --git a/vendor/github.com/buildpacks/lifecycle/go.mod b/vendor/github.com/buildpacks/lifecycle/go.mod new file mode 100644 index 00000000000..74555205c53 --- /dev/null +++ b/vendor/github.com/buildpacks/lifecycle/go.mod @@ -0,0 +1,22 @@ +module github.com/buildpacks/lifecycle + +require ( + github.com/BurntSushi/toml v0.3.1 + github.com/apex/log v1.1.2-0.20190827100214-baa5455d1012 + github.com/buildpacks/imgutil v0.0.0-20191212154113-dc184e0d403b + github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7 + github.com/docker/go-connections v0.4.0 + github.com/golang/mock v1.3.1 + github.com/google/go-cmp v0.3.0 + github.com/google/go-containerregistry v0.0.0-20191018211754-b77a90c667af + github.com/heroku/color v0.0.6 + github.com/mattn/go-colorable v0.1.4 // indirect + github.com/mattn/go-isatty v0.0.10 // indirect + github.com/pkg/errors v0.8.1 + github.com/sclevine/spec v1.4.0 + golang.org/x/net v0.0.0-20190724013045-ca1201d0de80 // indirect + golang.org/x/sync v0.0.0-20190423024810-112230192c58 + google.golang.org/genproto v0.0.0-20190508193815-b515fa19cec8 // indirect +) + +go 1.13 diff --git a/vendor/github.com/buildpacks/lifecycle/go.sum b/vendor/github.com/buildpacks/lifecycle/go.sum new file mode 100644 index 00000000000..eec52a8a26f --- /dev/null +++ b/vendor/github.com/buildpacks/lifecycle/go.sum @@ -0,0 +1,250 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/Azure/azure-sdk-for-go v19.1.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8= +github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= +github.com/Azure/go-autorest v10.15.5+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/Microsoft/go-winio v0.4.14 h1:+hMXMk01us9KgxGb7ftKQt2Xpf5hH/yky+TDA+qxleU= +github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= +github.com/apex/log v1.1.2-0.20190827100214-baa5455d1012 h1:r9k3B0K539tmbDOdyCIuz/6qtn8q+lp+qvEStcFUIdM= +github.com/apex/log v1.1.2-0.20190827100214-baa5455d1012/go.mod h1:Ls949n1HFtXfbDcjiTTFQqkVUrte0puoIBfO3SVgwOA= +github.com/aphistic/golf v0.0.0-20180712155816-02c07f170c5a h1:2KLQMJ8msqoPHIPDufkxVcoTtcmE5+1sL9950m4R9Pk= +github.com/aphistic/golf v0.0.0-20180712155816-02c07f170c5a/go.mod h1:3NqKYiepwy8kCu4PNA+aP7WUV72eXWJeP9/r3/K9aLE= +github.com/aphistic/sweet v0.2.0/go.mod h1:fWDlIh/isSE9n6EPsRmC0det+whmX6dJid3stzu0Xys= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/aws/aws-sdk-go v1.15.90/go.mod h1:es1KtYUFs7le0xQ3rOihkuoVD90z7D0fR2Qm4S00/gU= +github.com/aws/aws-sdk-go v1.20.6 h1:kmy4Gvdlyez1fV4kw5RYxZzWKVyuHZHgPWeU/YvRsV4= +github.com/aws/aws-sdk-go v1.20.6/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59 h1:WWB576BN5zNSZc/M9d/10pqEx5VHNhaQ/yOVAkmj5Yo= +github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U2H7sSsE2t6Kca0lfwTK8JdoNGS/yzM/4iH5I= +github.com/buildpacks/imgutil v0.0.0-20191212154113-dc184e0d403b h1:SDsB0hJtURA+5i5vIjLntzRNPEqdoz6q+0MShCWdctw= +github.com/buildpacks/imgutil v0.0.0-20191212154113-dc184e0d403b/go.mod h1:E3lXJcNXcRefJQAHW5rqboonet+jtOml4qImbJhYGAo= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/containerd/containerd v1.3.0 h1:xjvXQWABwS2uiv3TWgQt5Uth60Gu86LTGZXMJkjc7rY= +github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017 h1:2HQmlpI3yI9deH18Q6xiSOIjXD4sLI55Y/gfpa8/558= +github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/distribution v2.6.0-rc.1.0.20180327202408-83389a148052+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug= +github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7 h1:Cvj7S8I4Xpx78KAl6TwTmMHuHlZ/0SM60NUneGJQ7IE= +github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker-credential-helpers v0.6.3 h1:zI2p9+1NQYdnG6sMU26EX4aVGlqbInSQxQXLvzJ4RPQ= +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-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= +github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-logfmt/logfmt v0.4.0 h1:MP4Eh7ZCb31lleYCFuwm0oe4/YGak+5l1vA2NOE80nA= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1 h1:qGJ6qTW+x6xX/my+8YUVl4WNpX9B7+/l2tRsHGZ7f2s= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/google/btree v0.0.0-20180124185431-e89373fe6b4a/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-containerregistry v0.0.0-20191018211754-b77a90c667af h1:gCcst+zXdvatJYFDtPd3C3VNEGcoFOOMwFydnFIfnF0= +github.com/google/go-containerregistry v0.0.0-20191018211754-b77a90c667af/go.mod h1:9kIomAeXUmwhqeYS2zoEuQ0sc2GOVmNW7t3y9aNQL1o= +github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gnostic v0.2.2/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= +github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw= +github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/heroku/color v0.0.6 h1:UTFFMrmMLFcL3OweqP1lAdp8i1y/9oHqkeHjQ/b/Ny0= +github.com/heroku/color v0.0.6/go.mod h1:ZBvOcx7cTF2QKOv4LbmoBtNl5uB17qWxGuzZrsi1wLU= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jpillora/backoff v0.0.0-20180909062703-3050d21c67d7 h1:K//n/AqR5HjG3qxbrBCL4vJPW0MVFSs9CPK1OOJdRME= +github.com/jpillora/backoff v0.0.0-20180909062703-3050d21c67d7/go.mod h1:2iMrUgbbvHEiQClaW2NsSzMyGHqN+rDFqY705q49KG0= +github.com/json-iterator/go v0.0.0-20180701071628-ab8a2e0c74be/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s= +github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 h1:T+h1c/A9Gawja4Y9mFVWj2vyii2bbUNDw3kt9VxK2EY= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= +github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU= +github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.10 h1:qxFzApOv4WsAL965uUPIsXzAKCZxN2p9UqdhFS4ZW10= +github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= +github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= +github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ= +github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI= +github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= +github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/fastuuid v1.1.0 h1:INyGLmTCMGFr6OVIb977ghJvABML2CMVjPoRfNDdYDo= +github.com/rogpeppe/fastuuid v1.1.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/sclevine/spec v1.0.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24q7p+U= +github.com/sclevine/spec v1.4.0 h1:z/Q9idDcay5m5irkZ28M7PtQM4aOISzOpj4bUPkDee8= +github.com/sclevine/spec v1.4.0/go.mod h1:LvpgJaFyvQzRvc1kaDs0bulYwzC70PbiYjC4QnFHkOM= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k= +github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +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= +github.com/smartystreets/gunit v1.0.0/go.mod h1:qwPWnhz6pn0NnRBP++URONOVyNkPyr4SauJk4cUOwJs= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +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/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/tj/assert v0.0.0-20171129193455-018094318fb0/go.mod h1:mZ9/Rh9oLWpLLDRpvE+3b7gP/C2YyLFYxNmcLnPTMe0= +github.com/tj/go-elastic v0.0.0-20171221160941-36157cbbebc2 h1:eGaGNxrtoZf/mBURsnNQKDR7u50Klgcf2eFDQEnc8Bc= +github.com/tj/go-elastic v0.0.0-20171221160941-36157cbbebc2/go.mod h1:WjeM0Oo1eNAjXGDx2yma7uG2XoyRZTq1uv3M/o7imD0= +github.com/tj/go-kinesis v0.0.0-20171128231115-08b17f58cb1b h1:m74UWYy+HBs+jMFR9mdZU6shPewugMyH5+GV6LNgW8w= +github.com/tj/go-kinesis v0.0.0-20171128231115-08b17f58cb1b/go.mod h1:/yhzCV0xPfx6jb1bBgRFjl5lytqVqZXEaeqWP8lTEao= +github.com/tj/go-spin v1.1.0 h1:lhdWZsvImxvZ3q1C5OIB7d72DuOwP4O2NdBg9PyzNds= +github.com/tj/go-spin v1.1.0/go.mod h1:Mg1mzmePZm4dva8Qz60H2lHwmJ2loum4VIrLgVnKwh4= +github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80 h1:Ao/3l156eZf2AW5wK8a7/smtodRU+gha3+BeqJ69lRk= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191010194322-b09406accb47 h1:/XfQ9z7ib8eEJX2hdgFTZJ/ntt0swNk5oYBziWeTCvY= +golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20191017205301-920acffc3e65/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190508193815-b515fa19cec8 h1:x913Lq/RebkvUmRSdQ8MNb0GZKn+SR1ESfoetcQSeak= +google.golang.org/genproto v0.0.0-20190508193815-b515fa19cec8/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.24.0 h1:vb/1TCsVn3DcJlQ0Gs1yB1pKI6Do2/QNwxdKqmc/b0s= +google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= +gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +k8s.io/api v0.0.0-20180904230853-4e7be11eab3f/go.mod h1:iuAfoD4hCxJ8Onx9kaTIt30j7jUFS00AXQi6QMi99vA= +k8s.io/apimachinery v0.0.0-20180904193909-def12e63c512/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0= +k8s.io/client-go v0.0.0-20180910083459-2cefa64ff137/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s= +k8s.io/kube-openapi v0.0.0-20180731170545-e3762e86a74c/go.mod h1:BXM9ceUBTj2QnfH2MK1odQs778ajze1RxcmP6S8RVVc= +k8s.io/kubernetes v1.11.10/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= diff --git a/vendor/github.com/buildpacks/lifecycle/golangci.yaml b/vendor/github.com/buildpacks/lifecycle/golangci.yaml new file mode 100644 index 00000000000..93a050c6c62 --- /dev/null +++ b/vendor/github.com/buildpacks/lifecycle/golangci.yaml @@ -0,0 +1,33 @@ +run: + timeout: 6m + modules-download-mode: vendor + +linters: + disable-all: true + enable: + - bodyclose + - deadcode + - dogsled + - gocritic + - goimports + - golint + - gosimple + - govet + - ineffassign + - maligned + - misspell + - nakedret + - scopelint + - staticcheck + - structcheck + - stylecheck + - typecheck + - unconvert + - unused + - varcheck + - whitespace + + +linters-settings: + goimports: + local-prefixes: github.com/buildpacks/lifecycle diff --git a/vendor/github.com/buildpacks/lifecycle/launcher.go b/vendor/github.com/buildpacks/lifecycle/launcher.go new file mode 100644 index 00000000000..9964154ff20 --- /dev/null +++ b/vendor/github.com/buildpacks/lifecycle/launcher.go @@ -0,0 +1,192 @@ +package lifecycle + +import ( + "fmt" + "io/ioutil" + "os" + "os/exec" + "path/filepath" + "strings" + + "github.com/pkg/errors" +) + +type Launcher struct { + DefaultProcessType string + LayersDir string + AppDir string + Processes []Process + Buildpacks []Buildpack + Env BuildEnv + Exec func(argv0 string, argv []string, envv []string) error +} + +func (l *Launcher) Launch(self string, cmd []string) error { + if err := l.env(); err != nil { + return errors.Wrap(err, "modify env") + } + process, err := l.processFor(cmd) + if err != nil { + return errors.Wrap(err, "determine start command") + } + if err := os.Chdir(l.AppDir); err != nil { + return errors.Wrap(err, "change to app directory") + } + if process.Direct { + binary, err := exec.LookPath(process.Command) + if err != nil { + return errors.Wrap(err, "path lookup") + } + + if err := l.Exec(binary, + append([]string{process.Command}, process.Args...), + l.Env.List(), + ); err != nil { + return errors.Wrap(err, "direct exec") + } + return nil + } + launcher, err := l.profileD() + if err != nil { + return errors.Wrap(err, "determine profile") + } + if err := l.Exec("/bin/bash", append([]string{ + "bash", "-c", + launcher, self, process.Command, + }, process.Args...), l.Env.List()); err != nil { + return errors.Wrap(err, "bash exec") + } + return nil +} + +func (l *Launcher) env() error { + appInfo, err := os.Stat(l.AppDir) + if err != nil { + return errors.Wrap(err, "find app directory") + } + return l.eachBuildpack(l.LayersDir, func(path string) error { + bpInfo, err := os.Stat(path) + if err != nil { + if os.IsNotExist(err) { + return nil + } + return errors.Wrap(err, "find buildpack directory") + } + if os.SameFile(appInfo, bpInfo) { + return nil + } + if err := eachDir(path, func(path string) error { + return l.Env.AddRootDir(path) + }); err != nil { + return errors.Wrap(err, "add layer root") + } + if err := eachDir(path, func(path string) error { + if err := l.Env.AddEnvDir(filepath.Join(path, "env")); err != nil { + return err + } + return l.Env.AddEnvDir(filepath.Join(path, "env.launch")) + }); err != nil { + return errors.Wrap(err, "add layer env") + } + return nil + }) +} + +func (l *Launcher) profileD() (string, error) { + var out []string + + appendIfFile := func(path string) error { + fi, err := os.Stat(path) + if os.IsNotExist(err) { + return nil + } + if err != nil { + return err + } + if !fi.IsDir() { + out = append(out, fmt.Sprintf(`source "%s"`, path)) + } + return nil + } + layersDir, err := filepath.Abs(l.LayersDir) + if err != nil { + return "", err + } + for _, bp := range l.Buildpacks { + scripts, err := filepath.Glob(filepath.Join(layersDir, bp.dir(), "*", "profile.d", "*")) + if err != nil { + return "", err + } + for _, script := range scripts { + if err := appendIfFile(script); err != nil { + return "", err + } + } + } + + if err := appendIfFile(filepath.Join(l.AppDir, ".profile")); err != nil { + return "", err + } + + out = append(out, `exec bash -c "$@"`) + return strings.Join(out, "\n"), nil +} + +func (l *Launcher) processFor(cmd []string) (Process, error) { + if len(cmd) == 0 { + if process, ok := l.findProcessType(l.DefaultProcessType); ok { + return process, nil + } + + return Process{}, fmt.Errorf("process type %s was not found", l.DefaultProcessType) + } + + if len(cmd) == 1 { + if process, ok := l.findProcessType(cmd[0]); ok { + return process, nil + } + } + + if len(cmd) > 1 && cmd[0] == "--" { + return Process{Command: cmd[1], Args: cmd[2:], Direct: true}, nil + } + + return Process{Command: cmd[0], Args: cmd[1:]}, nil +} + +func (l *Launcher) findProcessType(kind string) (Process, bool) { + for _, p := range l.Processes { + if p.Type == kind { + return p, true + } + } + + return Process{}, false +} + +func eachDir(dir string, fn func(path string) error) error { + files, err := ioutil.ReadDir(dir) + if os.IsNotExist(err) { + return nil + } else if err != nil { + return err + } + for _, f := range files { + if !f.IsDir() { + continue + } + if err := fn(filepath.Join(dir, f.Name())); err != nil { + return err + } + } + return nil +} + +func (l *Launcher) eachBuildpack(dir string, fn func(path string) error) error { + for _, bp := range l.Buildpacks { + if err := fn(filepath.Join(l.LayersDir, bp.dir())); err != nil { + return err + } + } + return nil +} diff --git a/vendor/github.com/buildpacks/lifecycle/layers.go b/vendor/github.com/buildpacks/lifecycle/layers.go new file mode 100644 index 00000000000..a3d1a54365b --- /dev/null +++ b/vendor/github.com/buildpacks/lifecycle/layers.go @@ -0,0 +1,199 @@ +package lifecycle + +import ( + "fmt" + "io/ioutil" + "os" + "path/filepath" + "strings" + + "github.com/BurntSushi/toml" +) + +type bpLayersDir struct { + path string + layers []bpLayer + name string + buildpack Buildpack +} + +func readBuildpackLayersDir(layersDir string, buildpack Buildpack) (bpLayersDir, error) { + path := filepath.Join(layersDir, buildpack.dir()) + bpDir := bpLayersDir{ + name: buildpack.ID, + path: path, + layers: []bpLayer{}, + buildpack: buildpack, + } + + fis, err := ioutil.ReadDir(path) + if err != nil && !os.IsNotExist(err) { + return bpLayersDir{}, err + } + + names := map[string]struct{}{} + for _, fi := range fis { + if fi.IsDir() { + bpDir.layers = append(bpDir.layers, *bpDir.newBPLayer(fi.Name())) + names[fi.Name()] = struct{}{} + } + } + + tomls, err := filepath.Glob(filepath.Join(path, "*.toml")) + if err != nil { + return bpLayersDir{}, err + } + for _, toml := range tomls { + name := strings.TrimSuffix(filepath.Base(toml), ".toml") + if _, ok := names[name]; !ok { + bpDir.layers = append(bpDir.layers, *bpDir.newBPLayer(name)) + } + } + return bpDir, nil +} + +func launch(l bpLayer) bool { + md, err := l.read() + return err == nil && md.Launch +} + +func malformed(l bpLayer) bool { + _, err := l.read() + return err != nil +} + +func cached(l bpLayer) bool { + md, err := l.read() + return err == nil && md.Cache +} + +func (bd *bpLayersDir) findLayers(f func(layer bpLayer) bool) []bpLayer { + var selectedLayers []bpLayer + for _, l := range bd.layers { + if f(l) { + selectedLayers = append(selectedLayers, l) + } + } + return selectedLayers +} + +func (bd *bpLayersDir) newBPLayer(name string) *bpLayer { + return &bpLayer{ + layer{ + path: filepath.Join(bd.path, name), + identifier: fmt.Sprintf("%s:%s", bd.buildpack.ID, name), + }, + } +} + +type bpLayer struct { + layer +} + +func (bp *bpLayer) read() (BuildpackLayerMetadata, error) { + var data BuildpackLayerMetadata + tomlPath := bp.path + ".toml" + fh, err := os.Open(tomlPath) + if os.IsNotExist(err) { + return BuildpackLayerMetadata{}, nil + } else if err != nil { + return BuildpackLayerMetadata{}, err + } + defer fh.Close() + if _, err := toml.DecodeFile(tomlPath, &data); err != nil { + return BuildpackLayerMetadata{}, err + } + sha, err := ioutil.ReadFile(bp.path + ".sha") + if err != nil { + if os.IsNotExist(err) { + return data, nil + } + return BuildpackLayerMetadata{}, err + } + data.SHA = string(sha) + return data, nil +} + +func (bp *bpLayer) remove() error { + if err := os.RemoveAll(bp.path); err != nil && !os.IsNotExist(err) { + return err + } + if err := os.Remove(bp.path + ".sha"); err != nil && !os.IsNotExist(err) { + return err + } + if err := os.Remove(bp.path + ".toml"); err != nil && !os.IsNotExist(err) { + return err + } + return nil +} + +func (bp *bpLayer) writeMetadata(metadata BuildpackLayerMetadata) error { + path := filepath.Join(bp.path + ".toml") + if err := os.MkdirAll(filepath.Dir(path), 0777); err != nil { + return err + } + fh, err := os.Create(path) + if err != nil { + return err + } + defer fh.Close() + return toml.NewEncoder(fh).Encode(metadata.BuildpackLayerMetadataFile) +} + +func (bp *bpLayer) hasLocalContents() bool { + _, err := ioutil.ReadDir(bp.path) + + return !os.IsNotExist(err) +} + +func (bp *bpLayer) writeSha(sha string) error { + if err := ioutil.WriteFile(bp.path+".sha", []byte(sha), 0777); err != nil { + return err + } + return nil +} + +func (bp *bpLayer) name() string { + return filepath.Base(bp.path) +} + +type layer struct { + path string + identifier string +} + +func (l *layer) Identifier() string { + return l.identifier +} + +func (l *layer) Path() string { + return l.path +} + +type identifiableLayer interface { + Identifier() string + Path() string +} + +func recursiveChown(path string, uid, gid int) error { + fis, err := ioutil.ReadDir(path) + if err != nil { + return err + } + if err := os.Chown(path, uid, gid); err != nil { + return err + } + for _, fi := range fis { + filePath := filepath.Join(path, fi.Name()) + if fi.IsDir() { + if err := recursiveChown(filePath, uid, gid); err != nil { + return err + } + } else { + if err := os.Lchown(filePath, uid, gid); err != nil { + return err + } + } + } + return nil +} diff --git a/vendor/github.com/buildpacks/lifecycle/lifecycle.go b/vendor/github.com/buildpacks/lifecycle/lifecycle.go new file mode 100644 index 00000000000..f13158a2447 --- /dev/null +++ b/vendor/github.com/buildpacks/lifecycle/lifecycle.go @@ -0,0 +1,39 @@ +package lifecycle + +var POSIXBuildEnv = map[string][]string{ + "bin": { + "PATH", + }, + "lib": { + "LD_LIBRARY_PATH", + "LIBRARY_PATH", + }, + "include": { + "CPATH", + }, + "pkgconfig": { + "PKG_CONFIG_PATH", + }, +} + +var POSIXLaunchEnv = map[string][]string{ + "bin": {"PATH"}, + "lib": {"LD_LIBRARY_PATH"}, +} + +type buildpackTOML struct { + Buildpack buildpackInfo `toml:"buildpack"` + Order BuildpackOrder `toml:"order"` + Path string `toml:"-"` +} + +type buildpackInfo struct { + ID string `toml:"id"` + Version string `toml:"version"` + Name string `toml:"name"` + ClearEnv bool `toml:"clear-env,omitempty"` +} + +func (bp buildpackTOML) String() string { + return bp.Buildpack.Name + " " + bp.Buildpack.Version +} diff --git a/vendor/github.com/buildpacks/lifecycle/logger.go b/vendor/github.com/buildpacks/lifecycle/logger.go new file mode 100644 index 00000000000..6daaf019022 --- /dev/null +++ b/vendor/github.com/buildpacks/lifecycle/logger.go @@ -0,0 +1,15 @@ +package lifecycle + +type Logger interface { + Debug(msg string) + Debugf(fmt string, v ...interface{}) + + Info(msg string) + Infof(fmt string, v ...interface{}) + + Warn(msg string) + Warnf(fmt string, v ...interface{}) + + Error(msg string) + Errorf(fmt string, v ...interface{}) +} diff --git a/vendor/github.com/buildpacks/lifecycle/metadata.go b/vendor/github.com/buildpacks/lifecycle/metadata.go new file mode 100644 index 00000000000..0f392ff616c --- /dev/null +++ b/vendor/github.com/buildpacks/lifecycle/metadata.go @@ -0,0 +1,160 @@ +package lifecycle + +import ( + "path" + + "github.com/google/go-containerregistry/pkg/name" + "github.com/pkg/errors" +) + +const ( + BuildMetadataLabel = "io.buildpacks.build.metadata" + LayerMetadataLabel = "io.buildpacks.lifecycle.metadata" + StackIDLabel = "io.buildpacks.stack.id" +) + +type BuildMetadata struct { + Processes []Process `toml:"processes" json:"processes"` + Buildpacks []Buildpack `toml:"buildpacks" json:"buildpacks"` + BOM []BOMEntry `toml:"bom" json:"bom"` + Launcher LauncherMetadata `toml:"-" json:"launcher"` + Slices []Slice `toml:"slices" json:"-"` +} + +type LauncherMetadata struct { + Version string `json:"version"` + Source SourceMetadata `json:"source"` +} + +type SourceMetadata struct { + Git GitMetadata `json:"git"` +} + +type GitMetadata struct { + Repository string `json:"repository"` + Commit string `json:"commit"` +} + +func MetadataFilePath(layersDir string) string { + return path.Join(layersDir, "config", "metadata.toml") +} + +type CacheMetadata struct { + Buildpacks []BuildpackLayersMetadata `json:"buildpacks"` +} + +func (cm *CacheMetadata) MetadataForBuildpack(id string) BuildpackLayersMetadata { + for _, bpMd := range cm.Buildpacks { + if bpMd.ID == id { + return bpMd + } + } + return BuildpackLayersMetadata{} +} + +// NOTE: This struct MUST be kept in sync with `LayersMetadataCompat` +type LayersMetadata struct { + App []LayerMetadata `json:"app" toml:"app"` + Config LayerMetadata `json:"config" toml:"config"` + Launcher LayerMetadata `json:"launcher" toml:"launcher"` + Buildpacks []BuildpackLayersMetadata `json:"buildpacks" toml:"buildpacks"` + RunImage RunImageMetadata `json:"runImage" toml:"run-image"` + Stack StackMetadata `json:"stack" toml:"stack"` +} + +// NOTE: This struct MUST be kept in sync with `LayersMetadata`. +// It exists for situations where the `App` field type cannot be +// guaranteed, yet the original struct data must be maintained. +type LayersMetadataCompat struct { + App interface{} `json:"app" toml:"app"` + Config LayerMetadata `json:"config" toml:"config"` + Launcher LayerMetadata `json:"launcher" toml:"launcher"` + Buildpacks []BuildpackLayersMetadata `json:"buildpacks" toml:"buildpacks"` + RunImage RunImageMetadata `json:"runImage" toml:"run-image"` + Stack StackMetadata `json:"stack" toml:"stack"` +} + +type AnalyzedMetadata struct { + Image *ImageIdentifier `toml:"image"` + Metadata LayersMetadata `toml:"metadata"` +} + +// FIXME: fix key names to be accurate in the daemon case +type ImageIdentifier struct { + Reference string `toml:"reference"` +} + +type LayerMetadata struct { + SHA string `json:"sha" toml:"sha"` +} + +type BuildpackLayersMetadata struct { + ID string `json:"key" toml:"key"` + Version string `json:"version" toml:"version"` + Layers map[string]BuildpackLayerMetadata `json:"layers" toml:"layers"` +} + +type BuildpackLayerMetadata struct { + LayerMetadata + BuildpackLayerMetadataFile +} + +type BuildpackLayerMetadataFile struct { + Data interface{} `json:"data" toml:"metadata"` + Build bool `json:"build" toml:"build"` + Launch bool `json:"launch" toml:"launch"` + Cache bool `json:"cache" toml:"cache"` +} + +type RunImageMetadata struct { + TopLayer string `json:"topLayer" toml:"top-layer"` + Reference string `json:"reference" toml:"reference"` +} + +type StackMetadata struct { + RunImage StackRunImageMetadata `json:"runImage" toml:"run-image"` +} + +type StackRunImageMetadata struct { + Image string `toml:"image" json:"image"` + Mirrors []string `toml:"mirrors" json:"mirrors,omitempty"` +} + +func (sm *StackMetadata) BestRunImageMirror(registry string) (string, error) { + if sm.RunImage.Image == "" { + return "", errors.New("missing run-image metadata") + } + runImageMirrors := []string{sm.RunImage.Image} + runImageMirrors = append(runImageMirrors, sm.RunImage.Mirrors...) + runImageRef, err := byRegistry(registry, runImageMirrors) + if err != nil { + return "", errors.Wrap(err, "failed to find run-image") + } + return runImageRef, nil +} + +func (m *LayersMetadata) MetadataForBuildpack(id string) BuildpackLayersMetadata { + for _, bpMd := range m.Buildpacks { + if bpMd.ID == id { + return bpMd + } + } + return BuildpackLayersMetadata{} +} + +func byRegistry(reg string, imgs []string) (string, error) { + if len(imgs) < 1 { + return "", errors.New("no images provided to search") + } + + for _, img := range imgs { + ref, err := name.ParseReference(img, name.WeakValidation) + if err != nil { + continue + } + if reg == ref.Context().RegistryStr() { + return img, nil + } + } + return imgs[0], nil +} diff --git a/vendor/github.com/buildpacks/lifecycle/rebaser.go b/vendor/github.com/buildpacks/lifecycle/rebaser.go new file mode 100644 index 00000000000..acbb3a0d642 --- /dev/null +++ b/vendor/github.com/buildpacks/lifecycle/rebaser.go @@ -0,0 +1,73 @@ +package lifecycle + +import ( + "encoding/json" + "fmt" + + "github.com/buildpacks/imgutil" + "github.com/pkg/errors" +) + +type Rebaser struct { + Logger Logger +} + +func (r *Rebaser) Rebase( + workingImage imgutil.Image, + newBaseImage imgutil.Image, + additionalNames []string, +) error { + var origMetadata LayersMetadataCompat + if err := DecodeLabel(workingImage, LayerMetadataLabel, &origMetadata); err != nil { + return errors.Wrap(err, "get image metadata") + } + + workingStackID, err := workingImage.Label(StackIDLabel) + if err != nil { + return errors.Wrap(err, "get working image stack") + } + + newBaseStackID, err := newBaseImage.Label(StackIDLabel) + if err != nil { + return errors.Wrap(err, "get new base image stack") + } + + if workingStackID == "" { + return errors.New("stack not defined on working image") + } + + if newBaseStackID == "" { + return errors.New("stack not defined on new base image") + } + + if workingStackID != newBaseStackID { + return errors.New(fmt.Sprintf("incompatible stack: '%s' is not compatible with '%s'", newBaseStackID, workingStackID)) + } + + err = workingImage.Rebase(origMetadata.RunImage.TopLayer, newBaseImage) + if err != nil { + return errors.Wrap(err, "rebase working image") + } + + origMetadata.RunImage.TopLayer, err = newBaseImage.TopLayer() + if err != nil { + return errors.Wrap(err, "get rebase run image top layer SHA") + } + + identifier, err := newBaseImage.Identifier() + if err != nil { + return errors.Wrap(err, "get run image id or digest") + } + origMetadata.RunImage.Reference = identifier.String() + + data, err := json.Marshal(origMetadata) + if err != nil { + return errors.Wrap(err, "marshall metadata") + } + + if err := workingImage.SetLabel(LayerMetadataLabel, string(data)); err != nil { + return errors.Wrap(err, "set app image metadata label") + } + + return saveImage(workingImage, additionalNames, r.Logger) +} diff --git a/vendor/github.com/buildpacks/lifecycle/restorer.go b/vendor/github.com/buildpacks/lifecycle/restorer.go new file mode 100644 index 00000000000..c281564ea24 --- /dev/null +++ b/vendor/github.com/buildpacks/lifecycle/restorer.go @@ -0,0 +1,99 @@ +package lifecycle + +import ( + "os" + + "github.com/pkg/errors" + "golang.org/x/sync/errgroup" + + "github.com/buildpacks/lifecycle/archive" +) + +type Restorer struct { + LayersDir string + Buildpacks []Buildpack + Logger Logger + UID int + GID int +} + +// Restore attempts to restore layer data for cache=true layers, removing the layer when unsuccessful. +// If a usable cache is not provided, Restore will remove all cache=true layer metadata. +func (r *Restorer) Restore(cache Cache) error { + // Create empty cache metadata in case a usable cache is not provided. + var meta CacheMetadata + if cache != nil { + var err error + meta, err = cache.RetrieveMetadata() + if err != nil { + return errors.Wrapf(err, "retrieving cache metadata") + } + } else { + r.Logger.Debug("Usable cache not provided, using empty cache metadata.") + } + + var g errgroup.Group + for _, buildpack := range r.Buildpacks { + buildpackDir, err := readBuildpackLayersDir(r.LayersDir, buildpack) + if err != nil { + return errors.Wrapf(err, "reading buildpack layer directory") + } + + cachedLayers := meta.MetadataForBuildpack(buildpack.ID).Layers + for _, bpLayer := range buildpackDir.findLayers(cached) { + name := bpLayer.name() + cachedLayer, exists := cachedLayers[name] + if !exists { + r.Logger.Infof("Removing %q, not in cache", bpLayer.Identifier()) + if err := bpLayer.remove(); err != nil { + return errors.Wrapf(err, "removing layer") + } + continue + } + data, err := bpLayer.read() + if err != nil { + return errors.Wrapf(err, "reading layer") + } + if data.SHA != cachedLayer.SHA { + r.Logger.Infof("Removing %q, wrong sha", bpLayer.Identifier()) + r.Logger.Debugf("Layer sha: %q, cache sha: %q", data.SHA, cachedLayer.SHA) + if err := bpLayer.remove(); err != nil { + return errors.Wrapf(err, "removing layer") + } + } else { + r.Logger.Infof("Restoring data for %q from cache", bpLayer.Identifier()) + g.Go(func() error { + return r.restoreLayer(cache, cachedLayer.SHA) + }) + } + } + } + if err := g.Wait(); err != nil { + return errors.Wrap(err, "restoring data") + } + + // if restorer is running as root it needs to fix the ownership of the layers dir + if current := os.Getuid(); current == -1 { + return errors.New("cannot determine UID") + } else if current == 0 { + if err := recursiveChown(r.LayersDir, r.UID, r.GID); err != nil { + return errors.Wrapf(err, "chowning layers dir to '%d/%d'", r.UID, r.GID) + } + } + return nil +} + +func (r *Restorer) restoreLayer(cache Cache, sha string) error { + // Sanity check to prevent panic. + if cache == nil { + return errors.New("restoring layer: cache not provided") + } + r.Logger.Debugf("Retrieving data for %q", sha) + rc, err := cache.RetrieveLayer(sha) + if err != nil { + return err + } + defer rc.Close() + + return archive.Untar(rc, "/") +} diff --git a/vendor/github.com/buildpacks/lifecycle/save.go b/vendor/github.com/buildpacks/lifecycle/save.go new file mode 100644 index 00000000000..3b4702a5e50 --- /dev/null +++ b/vendor/github.com/buildpacks/lifecycle/save.go @@ -0,0 +1,73 @@ +package lifecycle + +import ( + "fmt" + + "github.com/buildpacks/imgutil" + "github.com/buildpacks/imgutil/local" + "github.com/buildpacks/imgutil/remote" + "github.com/pkg/errors" +) + +func saveImage(image imgutil.Image, additionalNames []string, logger Logger) error { + var saveErr error + if err := image.Save(additionalNames...); err != nil { + var ok bool + if saveErr, ok = err.(imgutil.SaveError); !ok { + return errors.Wrap(err, "saving image") + } + } + + id, idErr := image.Identifier() + if idErr != nil { + if saveErr != nil { + return &MultiError{Errors: []error{idErr, saveErr}} + } + return idErr + } + + refType, ref, shortRef := getReference(id) + logger.Infof("*** Images (%s):\n", shortRef) + for _, n := range append([]string{image.Name()}, additionalNames...) { + if ok, message := getSaveStatus(saveErr, n); !ok { + logger.Infof(" %s - %s\n", n, message) + } else { + logger.Infof(" %s\n", n) + } + } + + logger.Debugf("\n*** %s: %s\n", refType, ref) + return saveErr +} + +type MultiError struct { + Errors []error +} + +func (me *MultiError) Error() string { + return fmt.Sprintf("failed with multiple errors %+v", me.Errors) +} + +func getReference(identifier imgutil.Identifier) (string, string, string) { + switch v := identifier.(type) { + case local.IDIdentifier: + return "Image ID", v.String(), TruncateSha(v.String()) + case remote.DigestIdentifier: + return "Digest", v.Digest.DigestStr(), v.Digest.DigestStr() + default: + return "Reference", v.String(), v.String() + } +} + +func getSaveStatus(err error, imageName string) (bool, string) { + if err != nil { + if saveErr, ok := err.(imgutil.SaveError); ok { + for _, d := range saveErr.Errors { + if d.ImageName == imageName { + return false, d.Cause.Error() + } + } + } + } + return true, "" +} diff --git a/vendor/github.com/buildpacks/lifecycle/utils.go b/vendor/github.com/buildpacks/lifecycle/utils.go new file mode 100644 index 00000000000..243fcba1ef6 --- /dev/null +++ b/vendor/github.com/buildpacks/lifecycle/utils.go @@ -0,0 +1,76 @@ +package lifecycle + +import ( + "encoding/json" + "io/ioutil" + "os" + "path/filepath" + "strings" + + "github.com/BurntSushi/toml" + "github.com/buildpacks/imgutil" + "github.com/pkg/errors" +) + +func WriteTOML(path string, data interface{}) error { + if err := os.MkdirAll(filepath.Dir(path), 0777); err != nil { + return err + } + f, err := os.Create(path) + if err != nil { + return err + } + defer f.Close() + return toml.NewEncoder(f).Encode(data) +} + +func ReadGroup(path string) (BuildpackGroup, error) { + var group BuildpackGroup + _, err := toml.DecodeFile(path, &group) + return group, err +} + +func ReadOrder(path string) (BuildpackOrder, error) { + var order struct { + Order BuildpackOrder `toml:"order"` + } + _, err := toml.DecodeFile(path, &order) + return order.Order, err +} + +func TruncateSha(sha string) string { + rawSha := strings.TrimPrefix(sha, "sha256:") + if len(sha) > 12 { + return rawSha[0:12] + } + return rawSha +} + +func DecodeLabel(image imgutil.Image, label string, v interface{}) error { + if !image.Found() { + return nil + } + contents, err := image.Label(label) + if err != nil { + return errors.Wrapf(err, "retrieving label '%s' for image '%s'", label, image.Name()) + } + if contents == "" { + return nil + } + if err := json.Unmarshal([]byte(contents), v); err != nil { + return errors.Wrapf(err, "failed to unmarshal context of label '%s'", label) + } + return nil +} + +func escapeID(id string) string { + return strings.Replace(id, "/", "_", -1) +} + +func isEmptyDir(name string) (bool, error) { + entries, err := ioutil.ReadDir(name) + if err != nil { + return false, err + } + return len(entries) == 0, nil +} diff --git a/vendor/github.com/buildpacks/pack/.gitignore b/vendor/github.com/buildpacks/pack/.gitignore new file mode 100644 index 00000000000..c3cc6a71c46 --- /dev/null +++ b/vendor/github.com/buildpacks/pack/.gitignore @@ -0,0 +1,13 @@ +.pack/ +/pack +out/ + +# Jetbrains Goland +.idea/ + +# Build outputs +artifacts/ +.DS_Store + +# Travis unencrypted file +.travis/key.pem \ No newline at end of file diff --git a/vendor/github.com/buildpacks/pack/.travis.yml b/vendor/github.com/buildpacks/pack/.travis.yml new file mode 100644 index 00000000000..2c86f897b95 --- /dev/null +++ b/vendor/github.com/buildpacks/pack/.travis.yml @@ -0,0 +1,24 @@ +language: go +go: 1.12.x + +env: + global: + - GO111MODULE=on + +jobs: + include: + - os: linux + script: make + - os: osx + script: make + env: + - NO_DOCKER=true + - os: windows + script: go test -mod=vendor -parallel=1 -v ./... + after_success: go build -mod=vendor -o pack ./cmd/pack + env: + - NO_DOCKER=true + +branches: + only: + - master \ No newline at end of file diff --git a/vendor/github.com/buildpacks/pack/CODEOWNERS b/vendor/github.com/buildpacks/pack/CODEOWNERS new file mode 100644 index 00000000000..e9a137de3ef --- /dev/null +++ b/vendor/github.com/buildpacks/pack/CODEOWNERS @@ -0,0 +1 @@ +* @buildpack/platform-maintainers diff --git a/vendor/github.com/buildpacks/pack/CONTRIBUTING.md b/vendor/github.com/buildpacks/pack/CONTRIBUTING.md new file mode 100644 index 00000000000..9f9b7ced1ed --- /dev/null +++ b/vendor/github.com/buildpacks/pack/CONTRIBUTING.md @@ -0,0 +1,102 @@ +We're glad you are interested in contributing to this project. We hope that this +document helps you get started. + +If something is missing, incorrect, or made irrelevant please feel free to make +a PR to keep it up-to-date. + +## Prerequisites + +- [Go](https://golang.org/dl/) + - including [Git](https://git-scm.com/) +- [Docker](https://www.docker.com/) + +## Development + +### Building + +To build pack: +``` +make build +``` + +This will output the binary to the directory `out/`. + +Options: + +| ENV_VAR | Description | Default | +|--------------|------------------------------------------------------------------------|---------| +| GOCMD | Change the `go` executable. For example, [richgo][rgo] for testing. | go | +| PACK_BIN | Change the name or location of the binary relative to `out/`. | pack | +| PACK_VERSION | Tell `pack` what version to consider itself | `dev` | + +[rgo]: https://github.com/kyoh86/richgo + +_NOTE: This project uses [go modules](https://github.com/golang/go/wiki/Modules) for dependency management._ + +### Testing + +To run unit and integration tests: + +```bash +make unit +``` + +To run acceptance tests: +```bash +make acceptance +``` + +Alternately, to run all tests: +```bash +make test +``` + +### Formatting + +To format the code: + +```bash +make format +``` + +### Verification + +To verify formatting and vet: +```bash +make verify +``` + +## Pull Requests + +1. **[Fork]((https://help.github.com/en/articles/fork-a-repo)) the repo** +2. **Code, Test, Commit...** + + _Don't forget utilize the convenient make functions above._ + +3. **Preparing a Branch** + + We prefer to have PRs that are encompassed in a single commit. This might + require that you execute some of these commands: + + If you are no up-to-date with master: + ```bash + # rebase from master (applies your changes on top of master) + git pull -r origin master + ``` + + If you made more than one commit: + ```bash + # squash multiple commits, if applicable + # set the top most commit to `pick` and all subsequent to `squash` + git rebase -i origin/master + ``` + + Another requirement is that you sign your work. See [DCO](https://probot.github.io/apps/dco/) for more details. + ```bash + git commit --amend --signoff + ``` + +4. **Submit a Pull Request** + + Submitting the pull request is done in [GitHub](https://github.com/buildpacks/pack/compare/) by selecting + your branch as the `compare` branch. \ No newline at end of file diff --git a/vendor/github.com/buildpacks/pack/LICENSE b/vendor/github.com/buildpacks/pack/LICENSE new file mode 100644 index 00000000000..261eeb9e9f8 --- /dev/null +++ b/vendor/github.com/buildpacks/pack/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/vendor/github.com/buildpacks/pack/Makefile b/vendor/github.com/buildpacks/pack/Makefile new file mode 100644 index 00000000000..682137abd46 --- /dev/null +++ b/vendor/github.com/buildpacks/pack/Makefile @@ -0,0 +1,75 @@ +GOCMD?=go +GOENV=CGO_ENABLED=0 +GOFLAGS?=-mod=vendor +PACK_VERSION?=dev-$(shell date +%Y-%m-%d-%H:%M:%S) +PACK_BIN?=pack +PACKAGE_BASE=github.com/buildpacks/pack +PACKAGES:=$(shell $(GOCMD) list ./... | grep -v /testdata/) +SRC:=$(shell find . -type f -name '*.go' -not -path "*/vendor/*") +ARCHIVE_NAME=pack-$(PACK_VERSION) + +export GOFLAGS:=$(GOFLAGS) + +all: clean verify test build + +build: + @echo "> Building..." + mkdir -p ./out + $(GOENV) $(GOCMD) build -ldflags "-X 'github.com/buildpacks/pack/cmd.Version=${PACK_VERSION}'" -o ./out/$(PACK_BIN) -a ./cmd/pack + +package: + tar czf ./out/$(ARCHIVE_NAME).tgz -C out/ pack + +install-mockgen: + @echo "> Installing mockgen..." + cd tools; $(GOCMD) install github.com/golang/mock/mockgen + +install-goimports: + @echo "> Installing goimports..." + cd tools; $(GOCMD) install golang.org/x/tools/cmd/goimports + +format: install-goimports + @echo "> Formating code..." + @goimports -l -w -local ${PACKAGE_BASE} ${SRC} + +install-golangci-lint: + @echo "> Installing golangci-lint..." + cd tools; $(GOCMD) install github.com/golangci/golangci-lint/cmd/golangci-lint + +lint: install-golangci-lint + @echo "> Linting code..." + @golangci-lint run -c golangci.yaml + +test: unit acceptance + +unit: format lint + @echo "> Running unit/integration tests..." + $(GOCMD) test -v -count=1 -parallel=1 -timeout=0 ./... + +acceptance: format lint + @echo "> Running acceptance tests..." + $(GOCMD) test -v -count=1 -parallel=1 -timeout=0 -tags=acceptance ./acceptance + +acceptance-all: format lint + @echo "> Running acceptance tests..." + ACCEPTANCE_SUITE_CONFIG=$$(cat ./acceptance/testconfig/all.json) $(GOCMD) test -v -count=1 -parallel=1 -timeout=0 -tags=acceptance ./acceptance + +clean: + @echo "> Cleaning workspace..." + rm -rf ./out + +verify: verify-format lint + +generate: install-mockgen + @echo "> Generating mocks..." + $(GOCMD) generate ./... + +verify-format: install-goimports + @echo "> Verifying format..." + @test -z "$(shell goimports -l -local ${PACKAGE_BASE} ${SRC})";\ + _err=$$?;\ + [ $$_err -ne 0 ] && echo "ERROR: Format verification failed!\n" &&\ + goimports -d -local ${PACKAGE_BASE} ${SRC} && exit $$_err;\ + exit 0; + +.PHONY: clean build format imports lint test unit acceptance verify verify-format \ No newline at end of file diff --git a/vendor/github.com/buildpacks/pack/README.md b/vendor/github.com/buildpacks/pack/README.md new file mode 100644 index 00000000000..1f091ebc300 --- /dev/null +++ b/vendor/github.com/buildpacks/pack/README.md @@ -0,0 +1,33 @@ +# pack - Buildpack CLI + +[![Travis Build Status](https://travis-ci.org/buildpacks/pack.svg?branch=master)](https://travis-ci.org/buildpacks/pack/branches) +[![Go Report Card](https://goreportcard.com/badge/github.com/buildpacks/pack)](https://goreportcard.com/report/github.com/buildpacks/pack) +[![GoDoc](https://godoc.org/github.com/buildpacks/pack?status.svg)](https://godoc.org/github.com/buildpacks/pack) +[![GitHub license](https://img.shields.io/github/license/buildpacks/pack)](https://github.com/buildpacks/pack/blob/master/LICENSE) +[![Slack](https://slack.buildpacks.io/badge.svg)](https://slack.buildpacks.io/) + +`pack` makes it easy for... +- **App Developers** to use buildpacks to convert code into runnable images. +- **Buildpack Authors** to develop and package buildpacks for distribution. +- **Operators** to package buildpacks for distribution and maintain applications. + +`pack` is a CLI implementation of the [Platform Interface Specification][platform-spec] for [Cloud Native Buildpacks][buildpacks.io]. + +## Usage + +- [Installing][install-pack] +- [Getting Started][getting-started] + +## Contributing + +For information on how to contribute to this project including its development +process see [CONTRIBUTING.md](CONTRIBUTING.md). + +## Resources +- [Buildpack Specification](https://github.com/buildpacks/spec/blob/master/buildpack.md) +- [Platform Specification][platform-spec] + +[buildpacks.io]: https://buildpacks.io/ +[install-pack]: https://buildpacks.io/docs/install-pack/ +[getting-started]: https://buildpacks.io/docs/app-journey +[platform-spec]: https://github.com/buildpacks/spec/blob/master/platform.md diff --git a/vendor/github.com/buildpacks/pack/build.go b/vendor/github.com/buildpacks/pack/build.go new file mode 100644 index 00000000000..33ef755bcfc --- /dev/null +++ b/vendor/github.com/buildpacks/pack/build.go @@ -0,0 +1,441 @@ +package pack + +import ( + "context" + "fmt" + "math/rand" + "net/url" + "os" + "path/filepath" + "runtime" + "strings" + + "github.com/buildpacks/imgutil" + "github.com/docker/docker/api/types" + "github.com/google/go-containerregistry/pkg/name" + "github.com/pkg/errors" + + "github.com/buildpacks/pack/cmd" + "github.com/buildpacks/pack/internal/api" + "github.com/buildpacks/pack/internal/archive" + "github.com/buildpacks/pack/internal/build" + "github.com/buildpacks/pack/internal/builder" + "github.com/buildpacks/pack/internal/dist" + "github.com/buildpacks/pack/internal/paths" + "github.com/buildpacks/pack/internal/stack" + "github.com/buildpacks/pack/internal/stringset" + "github.com/buildpacks/pack/internal/style" +) + +type Lifecycle interface { + Execute(ctx context.Context, opts build.LifecycleOptions) error +} + +type BuildOptions struct { + Image string // required + Builder string // required + AppPath string // defaults to current working directory + RunImage string // defaults to the best mirror from the builder metadata or AdditionalMirrors + AdditionalMirrors map[string][]string // only considered if RunImage is not provided + Env map[string]string + Publish bool + NoPull bool + ClearCache bool + Buildpacks []string + ProxyConfig *ProxyConfig // defaults to environment proxy vars + ContainerConfig ContainerConfig +} + +type ProxyConfig struct { + HTTPProxy string + HTTPSProxy string + NoProxy string +} + +type ContainerConfig struct { + Network string +} + +func (c *Client) Build(ctx context.Context, opts BuildOptions) error { + imageRef, err := c.parseTagReference(opts.Image) + if err != nil { + return errors.Wrapf(err, "invalid image name '%s'", opts.Image) + } + + appPath, err := c.processAppPath(opts.AppPath) + if err != nil { + return errors.Wrapf(err, "invalid app path '%s'", opts.AppPath) + } + + proxyConfig := c.processProxyConfig(opts.ProxyConfig) + + builderRef, err := c.processBuilderName(opts.Builder) + if err != nil { + return errors.Wrapf(err, "invalid builder '%s'", opts.Builder) + } + + rawBuilderImage, err := c.imageFetcher.Fetch(ctx, builderRef.Name(), true, !opts.NoPull) + if err != nil { + return errors.Wrapf(err, "failed to fetch builder image '%s'", builderRef.Name()) + } + + bldr, err := c.getBuilder(rawBuilderImage) + if err != nil { + return errors.Wrapf(err, "invalid builder '%s'", opts.Builder) + } + + runImageName := c.resolveRunImage(opts.RunImage, imageRef.Context().RegistryStr(), bldr.Stack(), opts.AdditionalMirrors) + runImage, err := c.validateRunImage(ctx, runImageName, opts.NoPull, opts.Publish, bldr.StackID) + if err != nil { + return errors.Wrapf(err, "invalid run-image '%s'", runImageName) + } + + var runMixins []string + if _, err := dist.GetLabel(runImage, stack.MixinsLabel, &runMixins); err != nil { + return err + } + + fetchedBPs, group, err := c.processBuildpacks(ctx, opts.Buildpacks) + if err != nil { + return err + } + + if err := c.validateMixins(fetchedBPs, bldr, runImageName, runMixins); err != nil { + return errors.Wrap(err, "validating stack mixins") + } + + ephemeralBuilder, err := c.createEphemeralBuilder(rawBuilderImage, opts.Env, group, fetchedBPs) + if err != nil { + return err + } + defer c.docker.ImageRemove(context.Background(), ephemeralBuilder.Name(), types.ImageRemoveOptions{Force: true}) + + lcPlatformAPIVersion := ephemeralBuilder.LifecycleDescriptor().API.PlatformVersion + supportsPlatform := false + for _, v := range build.SupportedPlatformAPIVersions { + if api.MustParse(v).SupportsVersion(lcPlatformAPIVersion) { + supportsPlatform = true + break + } + } + if !supportsPlatform { + c.logger.Debugf("pack %s supports Platform API version(s): %s", cmd.Version, strings.Join(build.SupportedPlatformAPIVersions, ", ")) + c.logger.Debugf("Builder %s has Platform API version: %s", style.Symbol(opts.Builder), lcPlatformAPIVersion) + return errors.Errorf("Builder %s is incompatible with this version of pack", style.Symbol(opts.Builder)) + } + + return c.lifecycle.Execute(ctx, build.LifecycleOptions{ + AppPath: appPath, + Image: imageRef, + Builder: ephemeralBuilder, + RunImage: runImageName, + ClearCache: opts.ClearCache, + Publish: opts.Publish, + HTTPProxy: proxyConfig.HTTPProxy, + HTTPSProxy: proxyConfig.HTTPSProxy, + NoProxy: proxyConfig.NoProxy, + Network: opts.ContainerConfig.Network, + }) +} + +func (c *Client) processBuilderName(builderName string) (name.Reference, error) { + if builderName == "" { + return nil, errors.New("builder is a required parameter if the client has no default builder") + } + return name.ParseReference(builderName, name.WeakValidation) +} + +func (c *Client) getBuilder(img imgutil.Image) (*builder.Builder, error) { + bldr, err := builder.FromImage(img) + if err != nil { + return nil, err + } + if bldr.Stack().RunImage.Image == "" { + return nil, errors.New("builder metadata is missing runImage") + } + return bldr, nil +} + +func (c *Client) validateRunImage(context context.Context, name string, noPull bool, publish bool, expectedStack string) (imgutil.Image, error) { + if name == "" { + return nil, errors.New("run image must be specified") + } + img, err := c.imageFetcher.Fetch(context, name, !publish, !noPull) + if err != nil { + return nil, err + } + stackID, err := img.Label("io.buildpacks.stack.id") + if err != nil { + return nil, err + } + if stackID != expectedStack { + return nil, fmt.Errorf("run-image stack id '%s' does not match builder stack '%s'", stackID, expectedStack) + } + return img, nil +} + +func (c *Client) validateMixins(additionalBuildpacks []dist.Buildpack, bldr *builder.Builder, runImageName string, runMixins []string) error { + if err := stack.ValidateMixins(bldr.Image().Name(), bldr.Mixins(), runImageName, runMixins); err != nil { + return err + } + + bps, err := allBuildpacks(bldr.Image(), additionalBuildpacks) + if err != nil { + return err + } + mixins := assembleAvailableMixins(bldr.Mixins(), runMixins) + + for _, bp := range bps { + if err := bp.EnsureStackSupport(bldr.StackID, mixins, true); err != nil { + return err + } + } + return nil +} + +// assembleAvailableMixins returns the set of mixins that are common between the two provided sets, plus build-only mixins and run-only mixins. +func assembleAvailableMixins(buildMixins, runMixins []string) []string { + // NOTE: We cannot simply union the two mixin sets, as this could introduce a mixin that is only present on one stack + // image but not the other. A buildpack that happens to require the mixin would fail to run properly, even though validation + // would pass. + // + // For example: + // + // Incorrect: + // Run image mixins: [A, B] + // Build image mixins: [A] + // Merged: [A, B] + // Buildpack requires: [A, B] + // Match? Yes + // + // Correct: + // Run image mixins: [A, B] + // Build image mixins: [A] + // Merged: [A] + // Buildpack requires: [A, B] + // Match? No + + buildOnly := stack.FindStageMixins(buildMixins, "build") + runOnly := stack.FindStageMixins(runMixins, "run") + _, _, common := stringset.Compare(buildMixins, runMixins) + + return append(common, append(buildOnly, runOnly...)...) +} + +func allBuildpacks(builderImage imgutil.Image, additionalBuildpacks []dist.Buildpack) ([]dist.BuildpackDescriptor, error) { + var all []dist.BuildpackDescriptor + var bpLayers dist.BuildpackLayers + if _, err := dist.GetLabel(builderImage, dist.BuildpackLayersLabel, &bpLayers); err != nil { + return nil, err + } + for id, bps := range bpLayers { + for ver, bp := range bps { + desc := dist.BuildpackDescriptor{ + Info: dist.BuildpackInfo{ + ID: id, + Version: ver, + }, + Stacks: bp.Stacks, + Order: bp.Order, + } + all = append(all, desc) + } + } + for _, bp := range additionalBuildpacks { + all = append(all, bp.Descriptor()) + } + return all, nil +} + +func (c *Client) processAppPath(appPath string) (string, error) { + var ( + resolvedAppPath string + err error + ) + + if appPath == "" { + if appPath, err = os.Getwd(); err != nil { + return "", errors.Wrap(err, "get working dir") + } + } + + if resolvedAppPath, err = filepath.EvalSymlinks(appPath); err != nil { + return "", errors.Wrap(err, "evaluate symlink") + } + + if resolvedAppPath, err = filepath.Abs(resolvedAppPath); err != nil { + return "", errors.Wrap(err, "resolve absolute path") + } + + fi, err := os.Stat(resolvedAppPath) + if err != nil { + return "", errors.Wrap(err, "stat file") + } + + if !fi.IsDir() { + fh, err := os.Open(resolvedAppPath) + if err != nil { + return "", errors.Wrap(err, "read file") + } + defer fh.Close() + + isZip, err := archive.IsZip(fh) + if err != nil { + return "", errors.Wrap(err, "check zip") + } + + if !isZip { + return "", errors.New("app path must be a directory or zip") + } + } + + return resolvedAppPath, nil +} + +func (c *Client) processProxyConfig(config *ProxyConfig) ProxyConfig { + var ( + httpProxy, httpsProxy, noProxy string + ok bool + ) + if config != nil { + return *config + } + if httpProxy, ok = os.LookupEnv("HTTP_PROXY"); !ok { + httpProxy = os.Getenv("http_proxy") + } + if httpsProxy, ok = os.LookupEnv("HTTPS_PROXY"); !ok { + httpsProxy = os.Getenv("https_proxy") + } + if noProxy, ok = os.LookupEnv("NO_PROXY"); !ok { + noProxy = os.Getenv("no_proxy") + } + return ProxyConfig{ + HTTPProxy: httpProxy, + HTTPSProxy: httpsProxy, + NoProxy: noProxy, + } +} + +func (c *Client) processBuildpacks(ctx context.Context, buildpacks []string) ([]dist.Buildpack, dist.OrderEntry, error) { + group := dist.OrderEntry{Group: []dist.BuildpackRef{}} + var bps []dist.Buildpack + for _, bp := range buildpacks { + if isBuildpackID(bp) { + id, version := c.parseBuildpack(bp) + group.Group = append(group.Group, dist.BuildpackRef{ + BuildpackInfo: dist.BuildpackInfo{ + ID: id, + Version: version, + }, + }) + } else { + err := ensureBPSupport(bp) + if err != nil { + return nil, dist.OrderEntry{}, errors.Wrapf(err, "checking buildpack path") + } + + blob, err := c.downloader.Download(ctx, bp) + if err != nil { + return nil, dist.OrderEntry{}, errors.Wrapf(err, "downloading buildpack from %s", style.Symbol(bp)) + } + + fetchedBP, err := dist.BuildpackFromRootBlob(blob) + if err != nil { + return nil, dist.OrderEntry{}, errors.Wrapf(err, "creating buildpack from %s", style.Symbol(bp)) + } + + bps = append(bps, fetchedBP) + + group.Group = append(group.Group, dist.BuildpackRef{ + BuildpackInfo: fetchedBP.Descriptor().Info, + }) + } + } + return bps, group, nil +} + +func isBuildpackID(bp string) bool { + if !paths.IsURI(bp) { + if _, err := os.Stat(bp); err != nil { + return true + } + } + return false +} + +func ensureBPSupport(bpPath string) (err error) { + p := bpPath + if paths.IsURI(bpPath) { + var u *url.URL + u, err = url.Parse(bpPath) + if err != nil { + return err + } + + if u.Scheme == "file" { + p, err = paths.URIToFilePath(bpPath) + if err != nil { + return err + } + } + } + + if runtime.GOOS == "windows" && !paths.IsURI(p) { + isDir, err := paths.IsDir(p) + if err != nil { + return err + } + + if isDir { + return fmt.Errorf("buildpack %s: directory-based buildpacks are not currently supported on Windows", style.Symbol(bpPath)) + } + } + + return nil +} + +func (c *Client) parseBuildpack(bp string) (string, string) { + parts := strings.Split(bp, "@") + if len(parts) == 2 { + if parts[1] == "latest" { + c.logger.Warn("@latest syntax is deprecated, will not work in future releases") + return parts[0], "" + } + + return parts[0], parts[1] + } + + return parts[0], "" +} + +func (c *Client) createEphemeralBuilder(rawBuilderImage imgutil.Image, env map[string]string, group dist.OrderEntry, buildpacks []dist.Buildpack) (*builder.Builder, error) { + origBuilderName := rawBuilderImage.Name() + bldr, err := builder.New(rawBuilderImage, fmt.Sprintf("pack.local/builder/%x:latest", randString(10))) + if err != nil { + return nil, errors.Wrapf(err, "invalid builder %s", style.Symbol(origBuilderName)) + } + + bldr.SetEnv(env) + for _, bp := range buildpacks { + bpInfo := bp.Descriptor().Info + c.logger.Debugf("Adding buildpack %s version %s to builder", style.Symbol(bpInfo.ID), style.Symbol(bpInfo.Version)) + bldr.AddBuildpack(bp) + } + if len(group.Group) > 0 { + c.logger.Debug("Setting custom order") + bldr.SetOrder([]dist.OrderEntry{group}) + } + + if err := bldr.Save(c.logger); err != nil { + return nil, err + } + return bldr, nil +} + +func randString(n int) string { + b := make([]byte, n) + for i := range b { + b[i] = 'a' + byte(rand.Intn(26)) + } + return string(b) +} diff --git a/vendor/github.com/buildpacks/pack/builder/config.go b/vendor/github.com/buildpacks/pack/builder/config.go new file mode 100644 index 00000000000..387e3a61199 --- /dev/null +++ b/vendor/github.com/buildpacks/pack/builder/config.go @@ -0,0 +1,136 @@ +package builder + +import ( + "fmt" + "io" + "os" + "path/filepath" + + "github.com/BurntSushi/toml" + "github.com/pkg/errors" + + "github.com/buildpacks/pack/internal/dist" + "github.com/buildpacks/pack/internal/paths" + "github.com/buildpacks/pack/internal/style" +) + +type Config struct { + Description string `toml:"description"` + Buildpacks []BuildpackConfig `toml:"buildpacks"` + Packages []PackageConfig `toml:"packages"` + Order dist.Order `toml:"order"` + Stack StackConfig `toml:"stack"` + Lifecycle LifecycleConfig `toml:"lifecycle"` +} + +type BuildpackConfig struct { + dist.BuildpackInfo + URI string `toml:"uri"` +} + +type PackageConfig struct { + Image string `toml:"image"` +} + +type StackConfig struct { + ID string `toml:"id"` + BuildImage string `toml:"build-image"` + RunImage string `toml:"run-image"` + RunImageMirrors []string `toml:"run-image-mirrors,omitempty"` +} + +type LifecycleConfig struct { + URI string `toml:"uri"` + Version string `toml:"version"` +} + +// ReadConfig reads a builder configuration from the file path provided and returns the +// configuration along with any warnings encountered while parsing +func ReadConfig(path string) (config Config, warnings []string, err error) { + builderDir, err := filepath.Abs(filepath.Dir(path)) + if err != nil { + return Config{}, nil, err + } + + file, err := os.Open(path) + if err != nil { + return Config{}, nil, errors.Wrap(err, "opening config file") + } + defer file.Close() + + warnings, err = getWarningsForObsoleteFields(file) + if err != nil { + return Config{}, nil, errors.Wrapf(err, "check warnings for file '%s'", path) + } + if _, err := file.Seek(0, io.SeekStart); err != nil { + return Config{}, nil, errors.Wrap(err, "reset config file pointer") + } + + config, err = parseConfig(file, builderDir) + if err != nil { + return Config{}, nil, errors.Wrapf(err, "parse contents of '%s'", path) + } + + if len(config.Order) == 0 { + warnings = append(warnings, fmt.Sprintf("empty %s definition", style.Symbol("order"))) + } + + return config, warnings, nil +} + +func getWarningsForObsoleteFields(reader io.Reader) ([]string, error) { + var warnings []string + + var obsoleteConfig = struct { + Buildpacks []struct { + Latest bool + } + Groups []interface{} + }{} + + if _, err := toml.DecodeReader(reader, &obsoleteConfig); err != nil { + return nil, err + } + + latestUsed := false + + for _, bp := range obsoleteConfig.Buildpacks { + latestUsed = bp.Latest + } + + if latestUsed { + warnings = append(warnings, fmt.Sprintf("%s field on a buildpack is obsolete and will be ignored", style.Symbol("latest"))) + } + + if len(obsoleteConfig.Groups) > 0 { + warnings = append(warnings, fmt.Sprintf("%s field is obsolete in favor of %s", style.Symbol("groups"), style.Symbol("order"))) + } + + return warnings, nil +} + +// parseConfig reads a builder configuration from reader and resolves relative buildpack paths using `relativeToDir` +func parseConfig(reader io.Reader, relativeToDir string) (Config, error) { + var builderConfig Config + if _, err := toml.DecodeReader(reader, &builderConfig); err != nil { + return Config{}, errors.Wrap(err, "decoding toml contents") + } + + for i, bp := range builderConfig.Buildpacks { + uri, err := paths.ToAbsolute(bp.URI, relativeToDir) + if err != nil { + return Config{}, errors.Wrap(err, "transforming buildpack URI") + } + builderConfig.Buildpacks[i].URI = uri + } + + if builderConfig.Lifecycle.URI != "" { + uri, err := paths.ToAbsolute(builderConfig.Lifecycle.URI, relativeToDir) + if err != nil { + return Config{}, errors.Wrap(err, "transforming lifecycle URI") + } + builderConfig.Lifecycle.URI = uri + } + + return builderConfig, nil +} diff --git a/vendor/github.com/buildpacks/pack/client.go b/vendor/github.com/buildpacks/pack/client.go new file mode 100644 index 00000000000..ad5ee068d4e --- /dev/null +++ b/vendor/github.com/buildpacks/pack/client.go @@ -0,0 +1,131 @@ +package pack + +import ( + "context" + "os" + "path/filepath" + + "github.com/buildpacks/imgutil" + dockerClient "github.com/docker/docker/client" + "github.com/google/go-containerregistry/pkg/authn" + "github.com/pkg/errors" + + "github.com/buildpacks/pack/internal/blob" + "github.com/buildpacks/pack/internal/build" + "github.com/buildpacks/pack/internal/config" + "github.com/buildpacks/pack/internal/image" + "github.com/buildpacks/pack/logging" +) + +//go:generate mockgen -package testmocks -destination testmocks/mock_image_fetcher.go github.com/buildpacks/pack ImageFetcher +type ImageFetcher interface { + // Fetch fetches an image by resolving it both remotely and locally depending on provided parameters. + // If daemon is true, it will look return a `local.Image`. Pull, applicable only when daemon is true, will + // attempt to pull a remote image first. + Fetch(ctx context.Context, name string, daemon, pull bool) (imgutil.Image, error) +} + +//go:generate mockgen -package testmocks -destination testmocks/mock_downloader.go github.com/buildpacks/pack Downloader +type Downloader interface { + Download(ctx context.Context, pathOrURI string) (blob.Blob, error) +} + +//go:generate mockgen -package testmocks -destination testmocks/mock_image_factory.go github.com/buildpacks/pack ImageFactory +type ImageFactory interface { + NewImage(repoName string, local bool) (imgutil.Image, error) +} + +type Client struct { + logger logging.Logger + imageFetcher ImageFetcher + downloader Downloader + lifecycle Lifecycle + docker *dockerClient.Client + imageFactory ImageFactory +} + +type ClientOption func(c *Client) + +// WithLogger supply your own logger. +func WithLogger(l logging.Logger) ClientOption { + return func(c *Client) { + c.logger = l + } +} + +// WithImageFactory supply your own image factory. +func WithImageFactory(f ImageFactory) ClientOption { + return func(c *Client) { + c.imageFactory = f + } +} + +// WithFetcher supply your own fetcher. +func WithFetcher(f ImageFetcher) ClientOption { + return func(c *Client) { + c.imageFetcher = f + } +} + +// WithDownloader supply your own downloader. +func WithDownloader(d Downloader) ClientOption { + return func(c *Client) { + c.downloader = d + } +} + +// WithCacheDir supply your own cache directory. +// +// Deprecated: use WithDownloader instead. +func WithCacheDir(path string) ClientOption { + return func(c *Client) { + c.downloader = blob.NewDownloader(c.logger, path) + } +} + +// WithDockerClient supply your own docker client. +func WithDockerClient(docker *dockerClient.Client) ClientOption { + return func(c *Client) { + c.docker = docker + } +} + +func NewClient(opts ...ClientOption) (*Client, error) { + var client Client + + for _, opt := range opts { + opt(&client) + } + + if client.logger == nil { + client.logger = logging.New(os.Stderr) + } + + if client.docker == nil { + var err error + client.docker, err = dockerClient.NewClientWithOpts(dockerClient.FromEnv, dockerClient.WithVersion("1.38")) + if err != nil { + return nil, err + } + } + + if client.downloader == nil { + packHome, err := config.PackHome() + if err != nil { + return nil, errors.Wrap(err, "getting pack home") + } + client.downloader = blob.NewDownloader(client.logger, filepath.Join(packHome, "download-cache")) + } + + if client.imageFetcher == nil { + client.imageFetcher = image.NewFetcher(client.logger, client.docker) + } + + if client.imageFactory == nil { + client.imageFactory = image.NewFactory(client.docker, authn.DefaultKeychain) + } + + client.lifecycle = build.NewLifecycle(client.docker, client.logger) + + return &client, nil +} diff --git a/vendor/github.com/buildpacks/pack/cmd/cmd.go b/vendor/github.com/buildpacks/pack/cmd/cmd.go new file mode 100644 index 00000000000..3a347a3cf9f --- /dev/null +++ b/vendor/github.com/buildpacks/pack/cmd/cmd.go @@ -0,0 +1,6 @@ +package cmd + +var ( + // Version is the version of `pack`. It is injected at compile time. + Version = "0.0.0" +) diff --git a/vendor/github.com/buildpacks/pack/common.go b/vendor/github.com/buildpacks/pack/common.go new file mode 100644 index 00000000000..8a477d2a67e --- /dev/null +++ b/vendor/github.com/buildpacks/pack/common.go @@ -0,0 +1,77 @@ +package pack + +import ( + "errors" + "fmt" + + "github.com/google/go-containerregistry/pkg/name" + + "github.com/buildpacks/pack/internal/builder" + "github.com/buildpacks/pack/internal/style" +) + +func (c *Client) parseTagReference(imageName string) (name.Reference, error) { + if imageName == "" { + return nil, errors.New("image is a required parameter") + } + if _, err := name.ParseReference(imageName, name.WeakValidation); err != nil { + return nil, err + } + ref, err := name.NewTag(imageName, name.WeakValidation) + if err != nil { + return nil, fmt.Errorf("'%s' is not a tag reference", imageName) + } + + return ref, nil +} + +func (c *Client) resolveRunImage(runImage, targetRegistry string, stackInfo builder.StackMetadata, additionalMirrors map[string][]string) string { + if runImage != "" { + c.logger.Debugf("Using provided run-image %s", style.Symbol(runImage)) + return runImage + } + runImageName := getBestRunMirror( + targetRegistry, + stackInfo.RunImage.Image, + stackInfo.RunImage.Mirrors, + additionalMirrors[stackInfo.RunImage.Image], + ) + + switch { + case runImageName == stackInfo.RunImage.Image: + c.logger.Debugf("Selected run image %s", style.Symbol(runImageName)) + case contains(stackInfo.RunImage.Mirrors, runImageName): + c.logger.Debugf("Selected run image mirror %s", style.Symbol(runImageName)) + default: + c.logger.Debugf("Selected run image mirror %s from local config", style.Symbol(runImageName)) + } + return runImageName +} + +func contains(slc []string, v string) bool { + for _, s := range slc { + if s == v { + return true + } + } + return false +} + +func getBestRunMirror(registry string, runImage string, mirrors []string, preferredMirrors []string) string { + runImageList := append(preferredMirrors, append([]string{runImage}, mirrors...)...) + for _, img := range runImageList { + ref, err := name.ParseReference(img, name.WeakValidation) + if err != nil { + continue + } + if ref.Context().RegistryStr() == registry { + return img + } + } + + if len(preferredMirrors) > 0 { + return preferredMirrors[0] + } + + return runImage +} diff --git a/vendor/github.com/buildpacks/pack/create_builder.go b/vendor/github.com/buildpacks/pack/create_builder.go new file mode 100644 index 00000000000..41b2e3458ad --- /dev/null +++ b/vendor/github.com/buildpacks/pack/create_builder.go @@ -0,0 +1,226 @@ +package pack + +import ( + "context" + "fmt" + + "github.com/Masterminds/semver" + "github.com/buildpacks/imgutil" + "github.com/pkg/errors" + + pubbldr "github.com/buildpacks/pack/builder" + "github.com/buildpacks/pack/internal/builder" + "github.com/buildpacks/pack/internal/dist" + "github.com/buildpacks/pack/internal/image" + "github.com/buildpacks/pack/internal/style" +) + +type CreateBuilderOptions struct { + BuilderName string + Config pubbldr.Config + Publish bool + NoPull bool +} + +func (c *Client) CreateBuilder(ctx context.Context, opts CreateBuilderOptions) error { + if err := validateBuilderConfig(opts.Config); err != nil { + return errors.Wrap(err, "invalid builder config") + } + + if err := c.validateRunImageConfig(ctx, opts); err != nil { + return err + } + + baseImage, err := c.imageFetcher.Fetch(ctx, opts.Config.Stack.BuildImage, !opts.Publish, !opts.NoPull) + if err != nil { + return errors.Wrap(err, "fetch build image") + } + + c.logger.Debugf("Creating builder %s from build-image %s", style.Symbol(opts.BuilderName), style.Symbol(baseImage.Name())) + bldr, err := builder.New(baseImage, opts.BuilderName) + if err != nil { + return errors.Wrap(err, "invalid build-image") + } + + bldr.SetDescription(opts.Config.Description) + + if bldr.StackID != opts.Config.Stack.ID { + return fmt.Errorf( + "stack %s from builder config is incompatible with stack %s from build image", + style.Symbol(opts.Config.Stack.ID), + style.Symbol(bldr.StackID), + ) + } + + lifecycle, err := c.fetchLifecycle(ctx, opts.Config.Lifecycle) + if err != nil { + return errors.Wrap(err, "fetch lifecycle") + } + + if err := bldr.SetLifecycle(lifecycle); err != nil { + return errors.Wrap(err, "setting lifecycle") + } + + for _, b := range opts.Config.Buildpacks { + err := ensureBPSupport(b.URI) + if err != nil { + return err + } + + blob, err := c.downloader.Download(ctx, b.URI) + if err != nil { + return errors.Wrapf(err, "downloading buildpack from %s", style.Symbol(b.URI)) + } + + fetchedBp, err := dist.BuildpackFromRootBlob(blob) + if err != nil { + return errors.Wrapf(err, "creating buildpack from %s", style.Symbol(b.URI)) + } + + err = validateBuildpack(fetchedBp, b.URI, b.ID, b.Version) + if err != nil { + return errors.Wrap(err, "invalid buildpack") + } + + bldr.AddBuildpack(fetchedBp) + } + + for _, pkg := range opts.Config.Packages { + bps, err := extractPackagedBuildpacks(ctx, pkg.Image, c.imageFetcher, opts.Publish, opts.NoPull) + if err != nil { + return err + } + + for _, bp := range bps { + bldr.AddBuildpack(bp) + } + } + + bldr.SetOrder(opts.Config.Order) + bldr.SetStack(opts.Config.Stack) + + return bldr.Save(c.logger) +} + +func validateBuildpack(bp dist.Buildpack, source, expectedID, expectedBPVersion string) error { + if expectedID != "" && bp.Descriptor().Info.ID != expectedID { + return fmt.Errorf( + "buildpack from URI %s has ID %s which does not match ID %s from builder config", + style.Symbol(source), + style.Symbol(bp.Descriptor().Info.ID), + style.Symbol(expectedID), + ) + } + + if expectedBPVersion != "" && bp.Descriptor().Info.Version != expectedBPVersion { + return fmt.Errorf( + "buildpack from URI %s has version %s which does not match version %s from builder config", + style.Symbol(source), + style.Symbol(bp.Descriptor().Info.Version), + style.Symbol(expectedBPVersion), + ) + } + + return nil +} + +func (c *Client) fetchLifecycle(ctx context.Context, config pubbldr.LifecycleConfig) (builder.Lifecycle, error) { + if config.Version != "" && config.URI != "" { + return nil, errors.Errorf( + "%s can only declare %s or %s, not both", + style.Symbol("lifecycle"), style.Symbol("version"), style.Symbol("uri"), + ) + } + + var uri string + switch { + case config.Version != "": + v, err := semver.NewVersion(config.Version) + if err != nil { + return nil, errors.Wrapf(err, "%s must be a valid semver", style.Symbol("lifecycle.version")) + } + + uri = uriFromLifecycleVersion(*v) + case config.URI != "": + uri = config.URI + default: + uri = uriFromLifecycleVersion(*semver.MustParse(builder.DefaultLifecycleVersion)) + } + + b, err := c.downloader.Download(ctx, uri) + if err != nil { + return nil, errors.Wrap(err, "downloading lifecycle") + } + + lifecycle, err := builder.NewLifecycle(b) + if err != nil { + return nil, errors.Wrap(err, "invalid lifecycle") + } + + return lifecycle, nil +} + +func uriFromLifecycleVersion(version semver.Version) string { + return fmt.Sprintf("https://github.com/buildpacks/lifecycle/releases/download/v%s/lifecycle-v%s+linux.x86-64.tgz", version.String(), version.String()) +} + +func validateBuilderConfig(conf pubbldr.Config) error { + if conf.Stack.ID == "" { + return errors.New("stack.id is required") + } + + if conf.Stack.BuildImage == "" { + return errors.New("stack.build-image is required") + } + + if conf.Stack.RunImage == "" { + return errors.New("stack.run-image is required") + } + + return nil +} + +func (c *Client) validateRunImageConfig(ctx context.Context, opts CreateBuilderOptions) error { + var runImages []imgutil.Image + for _, i := range append([]string{opts.Config.Stack.RunImage}, opts.Config.Stack.RunImageMirrors...) { + if !opts.Publish { + img, err := c.imageFetcher.Fetch(ctx, i, true, false) + if err != nil { + if errors.Cause(err) != image.ErrNotFound { + return err + } + } else { + runImages = append(runImages, img) + continue + } + } + + img, err := c.imageFetcher.Fetch(ctx, i, false, false) + if err != nil { + if errors.Cause(err) != image.ErrNotFound { + return err + } + c.logger.Warnf("run image %s is not accessible", style.Symbol(i)) + } else { + runImages = append(runImages, img) + } + } + + for _, img := range runImages { + stackID, err := img.Label("io.buildpacks.stack.id") + if err != nil { + return err + } + + if stackID != opts.Config.Stack.ID { + return fmt.Errorf( + "stack %s from builder config is incompatible with stack %s from run image %s", + style.Symbol(opts.Config.Stack.ID), + style.Symbol(stackID), + style.Symbol(img.Name()), + ) + } + } + + return nil +} diff --git a/vendor/github.com/buildpacks/pack/create_buildpackage.go b/vendor/github.com/buildpacks/pack/create_buildpackage.go new file mode 100644 index 00000000000..d16c24fb97e --- /dev/null +++ b/vendor/github.com/buildpacks/pack/create_buildpackage.go @@ -0,0 +1,71 @@ +package pack + +import ( + "context" + + "github.com/pkg/errors" + + "github.com/buildpacks/pack/internal/buildpackage" + "github.com/buildpacks/pack/internal/dist" + "github.com/buildpacks/pack/internal/style" +) + +type CreatePackageOptions struct { + Name string + Config buildpackage.Config + Publish bool + NoPull bool +} + +func (c *Client) CreatePackage(ctx context.Context, opts CreatePackageOptions) error { + packageBuilder := buildpackage.NewBuilder(c.imageFactory) + + bpURI := opts.Config.Buildpack.URI + if bpURI == "" { + return errors.New("buildpack URI must be provided") + } + + blob, err := c.downloader.Download(ctx, bpURI) + if err != nil { + return errors.Wrapf(err, "downloading buildpack from %s", style.Symbol(bpURI)) + } + + bp, err := dist.BuildpackFromRootBlob(blob) + if err != nil { + return errors.Wrapf(err, "creating buildpack from %s", style.Symbol(bpURI)) + } + + packageBuilder.SetBuildpack(bp) + + for _, dep := range opts.Config.Dependencies { + if dep.URI != "" { + blob, err := c.downloader.Download(ctx, dep.URI) + if err != nil { + return errors.Wrapf(err, "downloading buildpack from %s", style.Symbol(dep.URI)) + } + + depBP, err := dist.BuildpackFromRootBlob(blob) + if err != nil { + return errors.Wrapf(err, "creating buildpack from %s", style.Symbol(dep.URI)) + } + + packageBuilder.AddDependency(depBP) + } else if dep.ImageName != "" { + bps, err := extractPackagedBuildpacks(ctx, dep.ImageName, c.imageFetcher, opts.Publish, opts.NoPull) + if err != nil { + return err + } + + for _, depBP := range bps { + packageBuilder.AddDependency(depBP) + } + } + } + + _, err = packageBuilder.Save(opts.Name, opts.Publish) + if err != nil { + return errors.Wrapf(err, "saving image") + } + + return err +} diff --git a/vendor/github.com/buildpacks/pack/go.mod b/vendor/github.com/buildpacks/pack/go.mod new file mode 100644 index 00000000000..ea14c860339 --- /dev/null +++ b/vendor/github.com/buildpacks/pack/go.mod @@ -0,0 +1,23 @@ +module github.com/buildpacks/pack + +require ( + github.com/BurntSushi/toml v0.3.1 + github.com/Masterminds/semver v1.4.2 + github.com/apex/log v1.1.2-0.20190827100214-baa5455d1012 + github.com/buildpacks/imgutil v0.0.0-20191212154113-dc184e0d403b + github.com/buildpacks/lifecycle v0.5.1-0.20191217221752-3b74c943b7b3 + github.com/dgodd/dockerdial v1.0.1 + github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7 + github.com/docker/go-connections v0.4.0 + github.com/golang/mock v1.3.1 + github.com/google/go-cmp v0.3.0 + github.com/google/go-containerregistry v0.0.0-20191018211754-b77a90c667af + github.com/heroku/color v0.0.6 + github.com/mitchellh/ioprogress v0.0.0-20180201004757-6a23b12fa88e + github.com/onsi/gomega v1.7.0 + github.com/pkg/errors v0.8.1 + github.com/sclevine/spec v1.4.0 + github.com/spf13/cobra v0.0.5 +) + +go 1.13 diff --git a/vendor/github.com/buildpacks/pack/go.sum b/vendor/github.com/buildpacks/pack/go.sum new file mode 100644 index 00000000000..4b745f3203d --- /dev/null +++ b/vendor/github.com/buildpacks/pack/go.sum @@ -0,0 +1,273 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/Azure/azure-sdk-for-go v19.1.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8= +github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= +github.com/Azure/go-autorest v10.15.5+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/Masterminds/semver v1.4.2 h1:WBLTQ37jOCzSLtXNdoo8bNM8876KhNqOKvrlGITgsTc= +github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= +github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= +github.com/Microsoft/go-winio v0.4.14 h1:+hMXMk01us9KgxGb7ftKQt2Xpf5hH/yky+TDA+qxleU= +github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= +github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= +github.com/apex/log v1.1.2-0.20190827100214-baa5455d1012 h1:r9k3B0K539tmbDOdyCIuz/6qtn8q+lp+qvEStcFUIdM= +github.com/apex/log v1.1.2-0.20190827100214-baa5455d1012/go.mod h1:Ls949n1HFtXfbDcjiTTFQqkVUrte0puoIBfO3SVgwOA= +github.com/aphistic/golf v0.0.0-20180712155816-02c07f170c5a/go.mod h1:3NqKYiepwy8kCu4PNA+aP7WUV72eXWJeP9/r3/K9aLE= +github.com/aphistic/sweet v0.2.0/go.mod h1:fWDlIh/isSE9n6EPsRmC0det+whmX6dJid3stzu0Xys= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/aws/aws-sdk-go v1.15.90/go.mod h1:es1KtYUFs7le0xQ3rOihkuoVD90z7D0fR2Qm4S00/gU= +github.com/aws/aws-sdk-go v1.20.6/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U2H7sSsE2t6Kca0lfwTK8JdoNGS/yzM/4iH5I= +github.com/buildpacks/imgutil v0.0.0-20191212154113-dc184e0d403b h1:SDsB0hJtURA+5i5vIjLntzRNPEqdoz6q+0MShCWdctw= +github.com/buildpacks/imgutil v0.0.0-20191212154113-dc184e0d403b/go.mod h1:E3lXJcNXcRefJQAHW5rqboonet+jtOml4qImbJhYGAo= +github.com/buildpacks/lifecycle v0.5.1-0.20191217221752-3b74c943b7b3 h1:15zYyFmNbrtx5MmyVEKVgY2/eearqEqGJXLCjmvUo58= +github.com/buildpacks/lifecycle v0.5.1-0.20191217221752-3b74c943b7b3/go.mod h1:ZIuIs9B6tjAW4dthhltKVyEUlhRfFWWix9eqoInMGX4= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/containerd/containerd v1.3.0 h1:xjvXQWABwS2uiv3TWgQt5Uth60Gu86LTGZXMJkjc7rY= +github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgodd/dockerdial v1.0.1 h1:6XixGQxeytsIdVsbI4y+EHuv8QcxxH6ySJZLkm3jk5o= +github.com/dgodd/dockerdial v1.0.1/go.mod h1:MJmK56eTylC3KU7DR6bc3k9jmbpURO8rDOsGbfj+c6o= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017 h1:2HQmlpI3yI9deH18Q6xiSOIjXD4sLI55Y/gfpa8/558= +github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/distribution v0.0.0-20180327202408-83389a148052/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/distribution v2.6.0-rc.1.0.20180327202408-83389a148052+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug= +github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/docker v0.7.3-0.20181027010111-b8e87cfdad8d/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7 h1:Cvj7S8I4Xpx78KAl6TwTmMHuHlZ/0SM60NUneGJQ7IE= +github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker-credential-helpers v0.6.3 h1:zI2p9+1NQYdnG6sMU26EX4aVGlqbInSQxQXLvzJ4RPQ= +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-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= +github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +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= +github.com/golang/mock v1.3.1 h1:qGJ6qTW+x6xX/my+8YUVl4WNpX9B7+/l2tRsHGZ7f2s= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/google/btree v0.0.0-20180124185431-e89373fe6b4a/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-containerregistry v0.0.0-20191018211754-b77a90c667af h1:gCcst+zXdvatJYFDtPd3C3VNEGcoFOOMwFydnFIfnF0= +github.com/google/go-containerregistry v0.0.0-20191018211754-b77a90c667af/go.mod h1:9kIomAeXUmwhqeYS2zoEuQ0sc2GOVmNW7t3y9aNQL1o= +github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gnostic v0.2.2/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= +github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= +github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw= +github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d h1:kJCB4vdITiW1eC1vq2e6IsrXKrZit1bv/TDYFGMp4BQ= +github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= +github.com/heroku/color v0.0.6 h1:UTFFMrmMLFcL3OweqP1lAdp8i1y/9oHqkeHjQ/b/Ny0= +github.com/heroku/color v0.0.6/go.mod h1:ZBvOcx7cTF2QKOv4LbmoBtNl5uB17qWxGuzZrsi1wLU= +github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jpillora/backoff v0.0.0-20180909062703-3050d21c67d7/go.mod h1:2iMrUgbbvHEiQClaW2NsSzMyGHqN+rDFqY705q49KG0= +github.com/json-iterator/go v0.0.0-20180701071628-ab8a2e0c74be/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/konsorten/go-windows-terminal-sequences v0.0.0-20180402223658-b729f2633dfe/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s= +github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= +github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.10 h1:qxFzApOv4WsAL965uUPIsXzAKCZxN2p9UqdhFS4ZW10= +github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= +github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/ioprogress v0.0.0-20180201004757-6a23b12fa88e h1:Qa6dnn8DlasdXRnacluu8HzPts0S1I9zvvUPDbBnXFI= +github.com/mitchellh/ioprogress v0.0.0-20180201004757-6a23b12fa88e/go.mod h1:waEya8ee1Ro/lgxpVhkJI4BVASzkm3UZqkx/cFJiYHM= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= +github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.1 h1:q/mM8GF/n0shIN8SaAZ0V+jnLPzen6WIVZdiwrRlMlo= +github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME= +github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ= +github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI= +github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/fastuuid v1.1.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/sclevine/spec v1.0.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24q7p+U= +github.com/sclevine/spec v1.4.0 h1:z/Q9idDcay5m5irkZ28M7PtQM4aOISzOpj4bUPkDee8= +github.com/sclevine/spec v1.4.0/go.mod h1:LvpgJaFyvQzRvc1kaDs0bulYwzC70PbiYjC4QnFHkOM= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/sirupsen/logrus v1.1.1/go.mod h1:zrgwTnHtNr00buQ1vSptGe8m1f/BbgsPukg8qsT7A+A= +github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +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= +github.com/smartystreets/gunit v1.0.0/go.mod h1:qwPWnhz6pn0NnRBP++URONOVyNkPyr4SauJk4cUOwJs= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v0.0.5 h1:f0B+LkLX6DtmRH1isoNA9VTtNUK9K8xYd28JNNfOv/s= +github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +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/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/tj/assert v0.0.0-20171129193455-018094318fb0/go.mod h1:mZ9/Rh9oLWpLLDRpvE+3b7gP/C2YyLFYxNmcLnPTMe0= +github.com/tj/go-elastic v0.0.0-20171221160941-36157cbbebc2/go.mod h1:WjeM0Oo1eNAjXGDx2yma7uG2XoyRZTq1uv3M/o7imD0= +github.com/tj/go-kinesis v0.0.0-20171128231115-08b17f58cb1b/go.mod h1:/yhzCV0xPfx6jb1bBgRFjl5lytqVqZXEaeqWP8lTEao= +github.com/tj/go-spin v1.1.0/go.mod h1:Mg1mzmePZm4dva8Qz60H2lHwmJ2loum4VIrLgVnKwh4= +github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80 h1:Ao/3l156eZf2AW5wK8a7/smtodRU+gha3+BeqJ69lRk= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181025063200-d989b31c8746/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191010194322-b09406accb47 h1:/XfQ9z7ib8eEJX2hdgFTZJ/ntt0swNk5oYBziWeTCvY= +golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +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 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20191017205301-920acffc3e65/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190508193815-b515fa19cec8 h1:x913Lq/RebkvUmRSdQ8MNb0GZKn+SR1ESfoetcQSeak= +google.golang.org/genproto v0.0.0-20190508193815-b515fa19cec8/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.24.0 h1:vb/1TCsVn3DcJlQ0Gs1yB1pKI6Do2/QNwxdKqmc/b0s= +google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gotest.tools v2.1.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= +gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= +gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= +honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +k8s.io/api v0.0.0-20180904230853-4e7be11eab3f/go.mod h1:iuAfoD4hCxJ8Onx9kaTIt30j7jUFS00AXQi6QMi99vA= +k8s.io/apimachinery v0.0.0-20180904193909-def12e63c512/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0= +k8s.io/client-go v0.0.0-20180910083459-2cefa64ff137/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s= +k8s.io/kube-openapi v0.0.0-20180731170545-e3762e86a74c/go.mod h1:BXM9ceUBTj2QnfH2MK1odQs778ajze1RxcmP6S8RVVc= +k8s.io/kubernetes v1.11.10/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= diff --git a/vendor/github.com/buildpacks/pack/golangci.yaml b/vendor/github.com/buildpacks/pack/golangci.yaml new file mode 100644 index 00000000000..22e69ce5df6 --- /dev/null +++ b/vendor/github.com/buildpacks/pack/golangci.yaml @@ -0,0 +1,32 @@ +run: + timeout: 6m + modules-download-mode: vendor + +linters: + disable-all: true + enable: + - bodyclose + - deadcode + - dogsled + - gocritic + - goimports + - golint + - gosimple + - govet + - ineffassign + - maligned + - misspell + - nakedret + - scopelint + - staticcheck + - structcheck + - stylecheck + - typecheck + - unconvert + - unused + - varcheck + - whitespace + +linters-settings: + goimports: + local-prefixes: github.com/buildpacks/pack \ No newline at end of file diff --git a/vendor/github.com/buildpacks/pack/inspect_builder.go b/vendor/github.com/buildpacks/pack/inspect_builder.go new file mode 100644 index 00000000000..ba228e2064c --- /dev/null +++ b/vendor/github.com/buildpacks/pack/inspect_builder.go @@ -0,0 +1,67 @@ +package pack + +import ( + "context" + "strings" + + "github.com/pkg/errors" + + "github.com/buildpacks/pack/internal/builder" + "github.com/buildpacks/pack/internal/dist" + "github.com/buildpacks/pack/internal/image" + "github.com/buildpacks/pack/internal/style" +) + +type BuilderInfo struct { + Description string + Stack string + Mixins []string + RunImage string + RunImageMirrors []string + Buildpacks []builder.BuildpackMetadata + Order dist.Order + Lifecycle builder.LifecycleDescriptor + CreatedBy builder.CreatorMetadata +} + +type BuildpackInfo struct { + ID string + Version string +} + +func (c *Client) InspectBuilder(name string, daemon bool) (*BuilderInfo, error) { + img, err := c.imageFetcher.Fetch(context.Background(), name, daemon, false) + if err != nil { + if errors.Cause(err) == image.ErrNotFound { + return nil, nil + } + return nil, err + } + + bldr, err := builder.FromImage(img) + if err != nil { + return nil, errors.Wrapf(err, "invalid builder %s", style.Symbol(name)) + } + + var commonMixins, buildMixins []string + commonMixins = []string{} + for _, mixin := range bldr.Mixins() { + if strings.HasPrefix(mixin, "build:") { + buildMixins = append(buildMixins, mixin) + } else { + commonMixins = append(commonMixins, mixin) + } + } + + return &BuilderInfo{ + Description: bldr.Description(), + Stack: bldr.StackID, + Mixins: append(commonMixins, buildMixins...), + RunImage: bldr.Stack().RunImage.Image, + RunImageMirrors: bldr.Stack().RunImage.Mirrors, + Buildpacks: bldr.Buildpacks(), + Order: bldr.Order(), + Lifecycle: bldr.LifecycleDescriptor(), + CreatedBy: bldr.CreatedBy(), + }, nil +} diff --git a/vendor/github.com/buildpacks/pack/inspect_image.go b/vendor/github.com/buildpacks/pack/inspect_image.go new file mode 100644 index 00000000000..20db4d1f064 --- /dev/null +++ b/vendor/github.com/buildpacks/pack/inspect_image.go @@ -0,0 +1,88 @@ +package pack + +import ( + "context" + + "github.com/Masterminds/semver" + "github.com/buildpacks/lifecycle" + "github.com/pkg/errors" + + "github.com/buildpacks/pack/internal/dist" + "github.com/buildpacks/pack/internal/image" +) + +type ImageInfo struct { + StackID string + Buildpacks []lifecycle.Buildpack + Base lifecycle.RunImageMetadata + BOM []lifecycle.BOMEntry + Stack lifecycle.StackMetadata + Processes ProcessDetails +} + +type ProcessDetails struct { + DefaultProcess *lifecycle.Process + OtherProcesses []lifecycle.Process +} + +// Deserialize just the subset of fields we need to avoid breaking changes +type layersMetadata struct { + RunImage lifecycle.RunImageMetadata `json:"runImage" toml:"run-image"` + Stack lifecycle.StackMetadata `json:"stack" toml:"stack"` +} + +func (c *Client) InspectImage(name string, daemon bool) (*ImageInfo, error) { + img, err := c.imageFetcher.Fetch(context.Background(), name, daemon, false) + if err != nil { + if errors.Cause(err) == image.ErrNotFound { + return nil, nil + } + return nil, err + } + + var layersMd layersMetadata + if _, err := dist.GetLabel(img, lifecycle.LayerMetadataLabel, &layersMd); err != nil { + return nil, err + } + + var buildMD lifecycle.BuildMetadata + if _, err := dist.GetLabel(img, lifecycle.BuildMetadataLabel, &buildMD); err != nil { + return nil, err + } + + minimumBaseImageReferenceVersion := semver.MustParse("0.5.0") + actualLauncherVersion, err := semver.NewVersion(buildMD.Launcher.Version) + + if err == nil && actualLauncherVersion.LessThan(minimumBaseImageReferenceVersion) { + layersMd.RunImage.Reference = "" + } + + stackID, err := img.Label(lifecycle.StackIDLabel) + if err != nil { + return nil, err + } + + defaultProcessType, err := img.Env("CNB_PROCESS_TYPE") + if err != nil || defaultProcessType == "" { + defaultProcessType = "web" + } + + var processDetails ProcessDetails + for _, proc := range buildMD.Processes { + proc := proc + if proc.Type == defaultProcessType { + processDetails.DefaultProcess = &proc + continue + } + processDetails.OtherProcesses = append(processDetails.OtherProcesses, proc) + } + + return &ImageInfo{ + StackID: stackID, + Stack: layersMd.Stack, + Base: layersMd.RunImage, + BOM: buildMD.BOM, + Buildpacks: buildMD.Buildpacks, + Processes: processDetails, + }, nil +} diff --git a/vendor/github.com/buildpacks/pack/internal/api/version.go b/vendor/github.com/buildpacks/pack/internal/api/version.go new file mode 100644 index 00000000000..eaafafa9e79 --- /dev/null +++ b/vendor/github.com/buildpacks/pack/internal/api/version.go @@ -0,0 +1,121 @@ +package api + +import ( + "fmt" + "regexp" + "strconv" + + "github.com/pkg/errors" + + "github.com/buildpacks/pack/internal/style" +) + +var regex = regexp.MustCompile(`^v?(\d+)\.(\d*)$`) + +type Version struct { + major, + minor uint64 +} + +func MustParse(v string) *Version { + version, err := NewVersion(v) + if err != nil { + panic(err) + } + + return version +} + +func NewVersion(v string) (*Version, error) { + matches := regex.FindAllStringSubmatch(v, -1) + if len(matches) == 0 { + return nil, errors.Errorf("could not parse %s as version", style.Symbol(v)) + } + + var ( + major, minor uint64 + err error + ) + if len(matches[0]) == 3 { + major, err = strconv.ParseUint(matches[0][1], 10, 64) + if err != nil { + return nil, errors.Wrapf(err, "parsing major %s", style.Symbol(matches[0][1])) + } + + minor, err = strconv.ParseUint(matches[0][2], 10, 64) + if err != nil { + return nil, errors.Wrapf(err, "parsing minor %s", style.Symbol(matches[0][2])) + } + } else { + return nil, errors.Errorf("could not parse version %s", style.Symbol(v)) + } + + return &Version{major: major, minor: minor}, nil +} + +func (v *Version) String() string { + return fmt.Sprintf("%d.%d", v.major, v.minor) +} + +// MarshalText makes Version satisfy the encoding.TextMarshaler interface. +func (v *Version) MarshalText() ([]byte, error) { + return []byte(v.String()), nil +} + +// UnmarshalText makes Version satisfy the encoding.TextUnmarshaler interface. +func (v *Version) UnmarshalText(text []byte) error { + s := string(text) + + parsedVersion, err := NewVersion(s) + if err != nil { + return errors.Wrapf(err, "invalid api version %s", s) + } + + v.major = parsedVersion.major + v.minor = parsedVersion.minor + + return nil +} + +// SupportsVersion determines whether this version supports a given version. If comparing two pre-stable (major == 0) +// versions, minors must match exactly. Otherwise, this minor must be greater than or equal to the given minor. Majors +// must always match. +func (v *Version) SupportsVersion(o *Version) bool { + if v.Equal(o) { + return true + } + + if v.major != 0 { + return v.major == o.major && v.minor >= o.minor + } + + return false +} + +func (v *Version) Equal(o *Version) bool { + return v.Compare(o) == 0 +} + +func (v *Version) Compare(o *Version) int { + if v.major != o.major { + if v.major < o.major { + return -1 + } + + if v.major > o.major { + return 1 + } + } + + if v.minor != o.minor { + if v.minor < o.minor { + return -1 + } + + if v.minor > o.minor { + return 1 + } + } + + return 0 +} diff --git a/vendor/github.com/buildpacks/pack/internal/app/image.go b/vendor/github.com/buildpacks/pack/internal/app/image.go new file mode 100644 index 00000000000..787beeac086 --- /dev/null +++ b/vendor/github.com/buildpacks/pack/internal/app/image.go @@ -0,0 +1,8 @@ +package app + +import "github.com/buildpacks/pack/logging" + +type Image struct { + RepoName string + Logger logging.Logger +} diff --git a/vendor/github.com/buildpacks/pack/internal/app/run.go b/vendor/github.com/buildpacks/pack/internal/app/run.go new file mode 100644 index 00000000000..03b4453cf45 --- /dev/null +++ b/vendor/github.com/buildpacks/pack/internal/app/run.go @@ -0,0 +1,104 @@ +package app + +import ( + "context" + "fmt" + "strconv" + "strings" + + "github.com/docker/docker/api/types" + dcontainer "github.com/docker/docker/api/types/container" + "github.com/docker/docker/client" + "github.com/docker/go-connections/nat" + "github.com/pkg/errors" + + "github.com/buildpacks/pack/internal/container" + "github.com/buildpacks/pack/logging" +) + +func (i *Image) Run(ctx context.Context, docker *client.Client, ports []string) error { + if ports == nil { + var err error + ports, err = exposedPorts(ctx, docker, i.RepoName) + if err != nil { + return err + } + } + + parsedPorts, portBindings, err := parsePorts(ports) + if err != nil { + return err + } + + ctr, err := docker.ContainerCreate(ctx, &dcontainer.Config{ + Image: i.RepoName, + AttachStdout: true, + AttachStderr: true, + ExposedPorts: parsedPorts, + Labels: map[string]string{"author": "pack"}, + }, &dcontainer.HostConfig{ + AutoRemove: true, + PortBindings: portBindings, + }, nil, "") + if err != nil { + return err + } + defer docker.ContainerRemove(context.Background(), ctr.ID, types.ContainerRemoveOptions{Force: true}) + + logContainerListening(i.Logger, portBindings) + if err = container.Run( + ctx, + docker, + ctr.ID, + logging.GetInfoWriter(i.Logger), + logging.GetInfoErrorWriter(i.Logger), + ); err != nil { + return errors.Wrap(err, "run container") + } + + return nil +} + +func exposedPorts(ctx context.Context, docker *client.Client, imageID string) ([]string, error) { + i, _, err := docker.ImageInspectWithRaw(ctx, imageID) + if err != nil { + return nil, err + } + var ports []string + for port := range i.Config.ExposedPorts { + ports = append(ports, port.Port()) + } + return ports, nil +} + +func parsePorts(ports []string) (nat.PortSet, nat.PortMap, error) { + for i, p := range ports { + p = strings.TrimSpace(p) + if _, err := strconv.Atoi(p); err == nil { + // default simple port to localhost and inside the container + p = fmt.Sprintf("127.0.0.1:%s:%s/tcp", p, p) + } + ports[i] = p + } + + return nat.ParsePortSpecs(ports) +} + +func logContainerListening(logger logging.Logger, portBindings nat.PortMap) { + // TODO handle case with multiple ports, for now when there is more than + // one port we assume you know what you're doing and don't need guidance + if len(portBindings) == 1 { + for _, bindings := range portBindings { + if len(bindings) == 1 { + binding := bindings[0] + host := binding.HostIP + port := binding.HostPort + if host == "127.0.0.1" { + host = "localhost" + } + // TODO the service may not be http based + logger.Infof("Starting container listening at http://%s:%s/\n", host, port) + } + } + } +} diff --git a/vendor/github.com/buildpacks/pack/internal/archive/archive.go b/vendor/github.com/buildpacks/pack/internal/archive/archive.go new file mode 100644 index 00000000000..c040590fedf --- /dev/null +++ b/vendor/github.com/buildpacks/pack/internal/archive/archive.go @@ -0,0 +1,311 @@ +package archive + +import ( + "archive/tar" + "archive/zip" + "bytes" + "io" + "io/ioutil" + "os" + "path" + "path/filepath" + "time" + + "github.com/docker/docker/pkg/ioutils" + "github.com/pkg/errors" +) + +var NormalizedDateTime time.Time + +func init() { + NormalizedDateTime = time.Date(1980, time.January, 1, 0, 0, 1, 0, time.UTC) +} + +func ReadDirAsTar(srcDir, basePath string, uid, gid int, mode int64) io.ReadCloser { + return GenerateTar(func(tw *tar.Writer) error { + return WriteDirToTar(tw, srcDir, basePath, uid, gid, mode) + }) +} + +func ReadZipAsTar(srcPath, basePath string, uid, gid int, mode int64) io.ReadCloser { + return GenerateTar(func(tw *tar.Writer) error { + return WriteZipToTar(tw, srcPath, basePath, uid, gid, mode) + }) +} + +// GenerateTar returns a reader to a tar from a generator function. Note that the +// generator will not fully execute until the reader is fully read from. Any errors +// returned by the generator will be returned when reading the reader. +func GenerateTar(gen func(*tar.Writer) error) io.ReadCloser { + errChan := make(chan error) + pr, pw := io.Pipe() + + go func() { + tw := tar.NewWriter(pw) + defer func() { + if r := recover(); r != nil { + tw.Close() + pw.CloseWithError(errors.Errorf("panic: %v", r)) + } + }() + + err := gen(tw) + + closeErr := tw.Close() + closeErr = aggregateError(closeErr, pw.CloseWithError(err)) + + errChan <- closeErr + }() + + return ioutils.NewReadCloserWrapper(pr, func() error { + var completeErr error + + // closing the reader ensures that if anything attempts + // further reading it doesn't block waiting for content + if err := pr.Close(); err != nil { + completeErr = aggregateError(completeErr, err) + } + + // wait until everything closes properly + if err := <-errChan; err != nil { + completeErr = aggregateError(completeErr, err) + } + + return completeErr + }) +} + +func aggregateError(base, addition error) error { + if addition == nil { + return base + } + + if base == nil { + return addition + } + + return errors.Wrap(addition, base.Error()) +} + +func CreateSingleFileTarReader(path, txt string) (io.Reader, error) { + var buf bytes.Buffer + tarBuilder := TarBuilder{} + tarBuilder.AddFile(path, 0644, NormalizedDateTime, []byte(txt)) + _, err := tarBuilder.WriteTo(&buf) + if err != nil { + return nil, err + } + + return bytes.NewReader(buf.Bytes()), nil +} + +func CreateSingleFileTar(tarFile, path, txt string) error { + tarBuilder := TarBuilder{} + tarBuilder.AddFile(path, 0644, NormalizedDateTime, []byte(txt)) + return tarBuilder.WriteToPath(tarFile) +} + +func AddFileToTar(tw *tar.Writer, path string, txt string) error { + if err := tw.WriteHeader(&tar.Header{ + Name: path, + Size: int64(len(txt)), + Mode: 0644, + ModTime: NormalizedDateTime, + }); err != nil { + return err + } + if _, err := tw.Write([]byte(txt)); err != nil { + return err + } + return nil +} + +var ErrEntryNotExist = errors.New("not exist") + +func ReadTarEntry(rc io.Reader, entryPath string) (*tar.Header, []byte, error) { + tr := tar.NewReader(rc) + for { + header, err := tr.Next() + if err == io.EOF { + break + } + if err != nil { + return nil, nil, errors.Wrap(err, "failed to get next tar entry") + } + + if path.Clean(header.Name) == entryPath { + buf, err := ioutil.ReadAll(tr) + if err != nil { + return nil, nil, errors.Wrapf(err, "failed to read contents of '%s'", entryPath) + } + + return header, buf, nil + } + } + + return nil, nil, errors.Wrapf(ErrEntryNotExist, "could not find entry path '%s'", entryPath) +} + +func WriteDirToTar(tw *tar.Writer, srcDir, basePath string, uid, gid int, mode int64) error { + return filepath.Walk(srcDir, func(file string, fi os.FileInfo, err error) error { + if err != nil { + return err + } + + if fi.Mode()&os.ModeSocket != 0 { + return nil + } + + var header *tar.Header + if fi.Mode()&os.ModeSymlink != 0 { + target, err := os.Readlink(file) + if err != nil { + return err + } + + header, err = tar.FileInfoHeader(fi, target) + if err != nil { + return err + } + } else { + header, err = tar.FileInfoHeader(fi, fi.Name()) + if err != nil { + return err + } + } + + relPath, err := filepath.Rel(srcDir, file) + if err != nil { + return err + } else if relPath == "." { + return nil + } + + header.Name = filepath.ToSlash(filepath.Join(basePath, relPath)) + finalizeHeader(header, uid, gid, mode) + + if err := tw.WriteHeader(header); err != nil { + return err + } + + if fi.Mode().IsRegular() { + f, err := os.Open(file) + if err != nil { + return err + } + defer f.Close() + + if _, err := io.Copy(tw, f); err != nil { + return err + } + } + + return nil + }) +} + +func WriteZipToTar(tw *tar.Writer, srcZip, basePath string, uid, gid int, mode int64) error { + zipReader, err := zip.OpenReader(srcZip) + if err != nil { + return err + } + defer zipReader.Close() + + for _, f := range zipReader.File { + var header *tar.Header + if f.Mode()&os.ModeSymlink != 0 { + target, err := func() (string, error) { + r, err := f.Open() + if err != nil { + return "", nil + } + defer r.Close() + + // contents is the target of the symlink + target, err := ioutil.ReadAll(r) + if err != nil { + return "", err + } + + return string(target), nil + }() + + if err != nil { + return err + } + + header, err = tar.FileInfoHeader(f.FileInfo(), target) + if err != nil { + return err + } + } else { + header, err = tar.FileInfoHeader(f.FileInfo(), f.Name) + if err != nil { + return err + } + } + + header.Name = filepath.ToSlash(filepath.Join(basePath, f.Name)) + finalizeHeader(header, uid, gid, mode) + + if err := tw.WriteHeader(header); err != nil { + return err + } + + if f.Mode().IsRegular() { + err := func() error { + fi, err := f.Open() + if err != nil { + return err + } + defer fi.Close() + + _, err = io.Copy(tw, fi) + return err + }() + + if err != nil { + return err + } + } + } + + return nil +} + +func finalizeHeader(header *tar.Header, uid, gid int, mode int64) { + NormalizeHeader(header) + if mode != -1 { + header.Mode = mode + } + header.Uid = uid + header.Gid = gid +} + +// NormalizeHeader normalizes a tar.Header +// +// Normalizes the following: +// - ModTime +// - GID +// - UID +// - User Name +// - Group Name +func NormalizeHeader(header *tar.Header) { + header.ModTime = NormalizedDateTime + header.Uid = 0 + header.Gid = 0 + header.Uname = "" + header.Gname = "" +} + +func IsZip(file io.Reader) (bool, error) { + b := make([]byte, 4) + _, err := file.Read(b) + if err != nil && err != io.EOF { + return false, err + } else if err == io.EOF { + return false, nil + } + + return bytes.Equal(b, []byte("\x50\x4B\x03\x04")), nil +} diff --git a/vendor/github.com/buildpacks/pack/internal/archive/tar_builder.go b/vendor/github.com/buildpacks/pack/internal/archive/tar_builder.go new file mode 100644 index 00000000000..a2bfd96237e --- /dev/null +++ b/vendor/github.com/buildpacks/pack/internal/archive/tar_builder.go @@ -0,0 +1,94 @@ +package archive + +import ( + "archive/tar" + "io" + "os" + "time" + + "github.com/pkg/errors" + + "github.com/buildpacks/pack/internal/style" +) + +type TarBuilder struct { + files []fileEntry +} + +type fileEntry struct { + typeFlag byte + path string + mode int64 + modTime time.Time + contents []byte +} + +func (t *TarBuilder) AddFile(path string, mode int64, modTime time.Time, contents []byte) { + t.files = append(t.files, fileEntry{ + typeFlag: tar.TypeReg, + path: path, + mode: mode, + modTime: modTime, + contents: contents, + }) +} + +func (t *TarBuilder) AddDir(path string, mode int64, modTime time.Time) { + t.files = append(t.files, fileEntry{ + typeFlag: tar.TypeDir, + path: path, + mode: mode, + modTime: modTime, + }) +} + +func (t *TarBuilder) Reader() io.ReadCloser { + pr, pw := io.Pipe() + go func() { + var err error + defer func() { + pw.CloseWithError(err) + }() + _, err = t.WriteTo(pw) + }() + + return pr +} + +func (t *TarBuilder) WriteToPath(path string) error { + fh, err := os.Create(path) + if err != nil { + return errors.Wrapf(err, "create file for tar: %s", style.Symbol(path)) + } + defer fh.Close() + + _, err = t.WriteTo(fh) + return err +} + +func (t *TarBuilder) WriteTo(writer io.Writer) (int64, error) { + tw := tar.NewWriter(writer) + defer tw.Close() + + var written int64 + for _, f := range t.files { + if err := tw.WriteHeader(&tar.Header{ + Typeflag: f.typeFlag, + Name: f.path, + Size: int64(len(f.contents)), + Mode: f.mode, + ModTime: f.modTime, + }); err != nil { + return written, err + } + + n, err := tw.Write(f.contents) + if err != nil { + return written, err + } + + written += int64(n) + } + + return written, nil +} diff --git a/vendor/github.com/buildpacks/pack/internal/blob/blob.go b/vendor/github.com/buildpacks/pack/internal/blob/blob.go new file mode 100644 index 00000000000..80c407ecae2 --- /dev/null +++ b/vendor/github.com/buildpacks/pack/internal/blob/blob.go @@ -0,0 +1,80 @@ +package blob + +import ( + "bytes" + "compress/gzip" + "io" + "os" + + "github.com/docker/docker/pkg/ioutils" + "github.com/pkg/errors" + + "github.com/buildpacks/pack/internal/archive" +) + +type Blob interface { + Open() (io.ReadCloser, error) +} + +type blob struct { + path string +} + +func NewBlob(path string) Blob { + return &blob{path: path} +} + +// Open returns an io.ReadCloser whose contents are in tar archive format +func (b blob) Open() (r io.ReadCloser, err error) { + fi, err := os.Stat(b.path) + if err != nil { + return nil, errors.Wrapf(err, "read blob at path '%s'", b.path) + } + if fi.IsDir() { + return archive.ReadDirAsTar(b.path, ".", 0, 0, -1), nil + } + + fh, err := os.Open(b.path) + if err != nil { + return nil, errors.Wrap(err, "open buildpack archive") + } + defer func() { + if err != nil { + fh.Close() + } + }() + + if ok, err := isGZip(fh); err != nil { + return nil, errors.Wrap(err, "check header") + } else if !ok { + return fh, nil + } + gzr, err := gzip.NewReader(fh) + if err != nil { + return nil, errors.Wrap(err, "create gzip reader") + } + + rc := ioutils.NewReadCloserWrapper(gzr, func() error { + defer fh.Close() + return gzr.Close() + }) + + return rc, nil +} + +func isGZip(file io.ReadSeeker) (bool, error) { + b := make([]byte, 3) + if _, err := file.Seek(0, 0); err != nil { + return false, err + } + _, err := file.Read(b) + if err != nil && err != io.EOF { + return false, err + } else if err == io.EOF { + return false, nil + } + if _, err := file.Seek(0, 0); err != nil { + return false, err + } + return bytes.Equal(b, []byte("\x1f\x8b\x08")), nil +} diff --git a/vendor/github.com/buildpacks/pack/internal/blob/downloader.go b/vendor/github.com/buildpacks/pack/internal/blob/downloader.go new file mode 100644 index 00000000000..30b97724943 --- /dev/null +++ b/vendor/github.com/buildpacks/pack/internal/blob/downloader.go @@ -0,0 +1,187 @@ +package blob + +import ( + "context" + "crypto/sha256" + "fmt" + "io" + "io/ioutil" + "net/http" + "net/url" + "os" + "path/filepath" + + "github.com/mitchellh/ioprogress" + "github.com/pkg/errors" + + "github.com/buildpacks/pack/internal/paths" + "github.com/buildpacks/pack/internal/style" + "github.com/buildpacks/pack/logging" +) + +const ( + cacheDirPrefix = "c" + cacheVersion = "2" +) + +type downloader struct { + logger logging.Logger + baseCacheDir string +} + +func NewDownloader(logger logging.Logger, baseCacheDir string) *downloader { //nolint:golint,gosimple + return &downloader{ + logger: logger, + baseCacheDir: baseCacheDir, + } +} + +func (d *downloader) Download(ctx context.Context, pathOrURI string) (Blob, error) { + if paths.IsURI(pathOrURI) { + parsedURL, err := url.Parse(pathOrURI) + if err != nil { + return nil, errors.Wrapf(err, "parsing path/uri %s", style.Symbol(pathOrURI)) + } + + var path string + switch parsedURL.Scheme { + case "file": + path, err = paths.URIToFilePath(pathOrURI) + case "http", "https": + path, err = d.handleHTTP(ctx, pathOrURI) + default: + err = fmt.Errorf("unsupported protocol %s in URI %s", style.Symbol(parsedURL.Scheme), style.Symbol(pathOrURI)) + } + if err != nil { + return nil, err + } + + return &blob{path: path}, nil + } + + path := d.handleFile(pathOrURI) + + return &blob{path: path}, nil +} + +func (d *downloader) handleFile(path string) string { + path, err := filepath.Abs(path) + if err != nil { + return "" + } + + return path +} + +func (d *downloader) handleHTTP(ctx context.Context, uri string) (string, error) { + cacheDir := d.versionedCacheDir() + + if err := os.MkdirAll(cacheDir, 0755); err != nil { + return "", err + } + + cachePath := filepath.Join(cacheDir, fmt.Sprintf("%x", sha256.Sum256([]byte(uri)))) + + etagFile := cachePath + ".etag" + etagExists, err := fileExists(etagFile) + if err != nil { + return "", err + } + + etag := "" + if etagExists { + bytes, err := ioutil.ReadFile(etagFile) + if err != nil { + return "", err + } + etag = string(bytes) + } + + reader, etag, err := d.downloadAsStream(ctx, uri, etag) + if err != nil { + return "", err + } else if reader == nil { + return cachePath, nil + } + defer reader.Close() + + fh, err := os.Create(cachePath) + if err != nil { + return "", errors.Wrapf(err, "create cache path %s", style.Symbol(cachePath)) + } + defer fh.Close() + + _, err = io.Copy(fh, reader) + if err != nil { + return "", errors.Wrap(err, "writing cache") + } + + if err = ioutil.WriteFile(etagFile, []byte(etag), 0744); err != nil { + return "", errors.Wrap(err, "writing etag") + } + + return cachePath, nil +} + +func (d *downloader) downloadAsStream(ctx context.Context, uri string, etag string) (io.ReadCloser, string, error) { + req, err := http.NewRequest("GET", uri, nil) + if err != nil { + return nil, "", err + } + req = req.WithContext(ctx) + + if etag != "" { + req.Header.Set("If-None-Match", etag) + } + + resp, err := (&http.Client{}).Do(req) //nolint:bodyclose + if err != nil { + return nil, "", err + } + + if resp.StatusCode >= 200 && resp.StatusCode < 300 { + d.logger.Infof("Downloading from %s", style.Symbol(uri)) + return withProgress(logging.GetInfoWriter(d.logger), resp.Body, resp.ContentLength), resp.Header.Get("Etag"), nil + } + + if resp.StatusCode == 304 { + d.logger.Debugf("Using cached version of %s", style.Symbol(uri)) + return nil, etag, nil + } + + return nil, "", fmt.Errorf( + "could not download from %s, code http status %s", + style.Symbol(uri), style.Symbol("%d", resp.StatusCode), + ) +} + +func withProgress(writer io.Writer, rc io.ReadCloser, length int64) io.ReadCloser { + return &progressReader{ + Closer: rc, + Reader: &ioprogress.Reader{ + Reader: rc, + Size: length, + DrawFunc: ioprogress.DrawTerminalf(writer, ioprogress.DrawTextFormatBytes), + }, + } +} + +type progressReader struct { + *ioprogress.Reader + io.Closer +} + +func (d *downloader) versionedCacheDir() string { + return filepath.Join(d.baseCacheDir, cacheDirPrefix+cacheVersion) +} + +func fileExists(file string) (bool, error) { + _, err := os.Stat(file) + if err != nil { + if os.IsNotExist(err) { + return false, nil + } + return false, err + } + return true, nil +} diff --git a/vendor/github.com/buildpacks/pack/internal/build/build.go b/vendor/github.com/buildpacks/pack/internal/build/build.go new file mode 100644 index 00000000000..713b0c8f559 --- /dev/null +++ b/vendor/github.com/buildpacks/pack/internal/build/build.go @@ -0,0 +1,167 @@ +package build + +import ( + "context" + "math/rand" + "sync" + "time" + + "github.com/docker/docker/client" + "github.com/google/go-containerregistry/pkg/name" + "github.com/pkg/errors" + + "github.com/buildpacks/pack/internal/api" + "github.com/buildpacks/pack/internal/builder" + "github.com/buildpacks/pack/internal/cache" + "github.com/buildpacks/pack/internal/style" + "github.com/buildpacks/pack/logging" +) + +var ( + // SupportedPlatformAPIVersions lists the Platform API versions pack supports. + SupportedPlatformAPIVersions = []string{"0.1", "0.2"} +) + +type Lifecycle struct { + builder *builder.Builder + logger logging.Logger + docker *client.Client + appPath string + appOnce *sync.Once + httpProxy string + httpsProxy string + noProxy string + version string + platformAPIVersion string + LayersVolume string + AppVolume string +} + +type Cache interface { + Name() string + Clear(context.Context) error +} + +func init() { + rand.Seed(time.Now().UTC().UnixNano()) +} + +func NewLifecycle(docker *client.Client, logger logging.Logger) *Lifecycle { + return &Lifecycle{logger: logger, docker: docker} +} + +type LifecycleOptions struct { + AppPath string + Image name.Reference + Builder *builder.Builder + RunImage string + ClearCache bool + Publish bool + HTTPProxy string + HTTPSProxy string + NoProxy string + Network string +} + +// CombinedExporterCacher returns true if the lifecycle contains combined exporter/cacher phases and reversed analyzer/restorer phases. +func (l *Lifecycle) CombinedExporterCacher() bool { + return api.MustParse(l.platformAPIVersion).Compare(api.MustParse("0.2")) >= 0 +} + +func (l *Lifecycle) Execute(ctx context.Context, opts LifecycleOptions) error { + l.Setup(opts) + defer l.Cleanup() + + buildCache := cache.NewVolumeCache(opts.Image, "build", l.docker) + launchCache := cache.NewVolumeCache(opts.Image, "launch", l.docker) + l.logger.Debugf("Using build cache volume %s", style.Symbol(buildCache.Name())) + + if opts.ClearCache { + if err := buildCache.Clear(ctx); err != nil { + return errors.Wrap(err, "clearing build cache") + } + l.logger.Debugf("Build cache %s cleared", style.Symbol(buildCache.Name())) + } + + l.logger.Info(style.Step("DETECTING")) + if err := l.Detect(ctx, opts.Network); err != nil { + return err + } + + if l.CombinedExporterCacher() { + l.logger.Info(style.Step("ANALYZING")) + if err := l.Analyze(ctx, opts.Image.Name(), buildCache.Name(), opts.Publish, opts.ClearCache); err != nil { + return err + } + + l.logger.Info(style.Step("RESTORING")) + if opts.ClearCache { + l.logger.Info("Skipping 'restore' due to clearing cache") + } else if err := l.Restore(ctx, buildCache.Name()); err != nil { + return err + } + } else { + l.logger.Info(style.Step("RESTORING")) + if opts.ClearCache { + l.logger.Info("Skipping 'restore' due to clearing cache") + } else if err := l.Restore(ctx, buildCache.Name()); err != nil { + return err + } + + l.logger.Info(style.Step("ANALYZING")) + if err := l.Analyze(ctx, opts.Image.Name(), buildCache.Name(), opts.Publish, opts.ClearCache); err != nil { + return err + } + } + + l.logger.Info(style.Step("BUILDING")) + if err := l.Build(ctx, opts.Network); err != nil { + return err + } + + l.logger.Info(style.Step("EXPORTING")) + if err := l.Export(ctx, opts.Image.Name(), opts.RunImage, opts.Publish, launchCache.Name(), buildCache.Name()); err != nil { + return err + } + + if !l.CombinedExporterCacher() { + l.logger.Info(style.Step("CACHING")) + if err := l.Cache(ctx, buildCache.Name()); err != nil { + return err + } + } + + return nil +} + +func (l *Lifecycle) Setup(opts LifecycleOptions) { + l.LayersVolume = "pack-layers-" + randString(10) + l.AppVolume = "pack-app-" + randString(10) + l.appPath = opts.AppPath + l.appOnce = &sync.Once{} + l.builder = opts.Builder + l.httpProxy = opts.HTTPProxy + l.httpsProxy = opts.HTTPSProxy + l.noProxy = opts.NoProxy + l.version = opts.Builder.LifecycleDescriptor().Info.Version.String() + l.platformAPIVersion = opts.Builder.LifecycleDescriptor().API.PlatformVersion.String() +} + +func (l *Lifecycle) Cleanup() error { + var reterr error + if err := l.docker.VolumeRemove(context.Background(), l.LayersVolume, true); err != nil { + reterr = errors.Wrapf(err, "failed to clean up layers volume %s", l.LayersVolume) + } + if err := l.docker.VolumeRemove(context.Background(), l.AppVolume, true); err != nil { + reterr = errors.Wrapf(err, "failed to clean up app volume %s", l.AppVolume) + } + return reterr +} + +func randString(n int) string { + b := make([]byte, n) + for i := range b { + b[i] = 'a' + byte(rand.Intn(26)) + } + return string(b) +} diff --git a/vendor/github.com/buildpacks/pack/internal/build/phase.go b/vendor/github.com/buildpacks/pack/internal/build/phase.go new file mode 100644 index 00000000000..54b22d55783 --- /dev/null +++ b/vendor/github.com/buildpacks/pack/internal/build/phase.go @@ -0,0 +1,200 @@ +package build + +import ( + "context" + "fmt" + "io" + "os" + "runtime" + "sync" + + "github.com/buildpacks/lifecycle/auth" + "github.com/docker/docker/api/types" + dcontainer "github.com/docker/docker/api/types/container" + "github.com/docker/docker/client" + "github.com/google/go-containerregistry/pkg/authn" + "github.com/pkg/errors" + + "github.com/buildpacks/pack/internal/archive" + "github.com/buildpacks/pack/internal/container" + "github.com/buildpacks/pack/logging" +) + +type Phase struct { + name string + logger logging.Logger + docker *client.Client + ctrConf *dcontainer.Config + hostConf *dcontainer.HostConfig + ctr dcontainer.ContainerCreateCreatedBody + uid, gid int + appPath string + appOnce *sync.Once +} + +func (l *Lifecycle) NewPhase(name string, ops ...func(*Phase) (*Phase, error)) (*Phase, error) { + ctrConf := &dcontainer.Config{ + Image: l.builder.Name(), + Labels: map[string]string{"author": "pack"}, + } + hostConf := &dcontainer.HostConfig{ + Binds: []string{ + fmt.Sprintf("%s:%s", l.LayersVolume, layersDir), + fmt.Sprintf("%s:%s", l.AppVolume, appDir), + }, + } + ctrConf.Cmd = []string{"/lifecycle/" + name} + phase := &Phase{ + ctrConf: ctrConf, + hostConf: hostConf, + name: name, + docker: l.docker, + logger: l.logger, + uid: l.builder.UID, + gid: l.builder.GID, + appPath: l.appPath, + appOnce: l.appOnce, + } + + if l.httpProxy != "" { + phase.ctrConf.Env = append(phase.ctrConf.Env, "HTTP_PROXY="+l.httpProxy) + phase.ctrConf.Env = append(phase.ctrConf.Env, "http_proxy="+l.httpProxy) + } + if l.httpsProxy != "" { + phase.ctrConf.Env = append(phase.ctrConf.Env, "HTTPS_PROXY="+l.httpsProxy) + phase.ctrConf.Env = append(phase.ctrConf.Env, "https_proxy="+l.httpsProxy) + } + if l.noProxy != "" { + phase.ctrConf.Env = append(phase.ctrConf.Env, "NO_PROXY="+l.noProxy) + phase.ctrConf.Env = append(phase.ctrConf.Env, "no_proxy="+l.noProxy) + } + + var err error + for _, op := range ops { + phase, err = op(phase) + if err != nil { + return nil, errors.Wrapf(err, "create %s phase", name) + } + } + return phase, nil +} + +func WithArgs(args ...string) func(*Phase) (*Phase, error) { + return func(phase *Phase) (*Phase, error) { + phase.ctrConf.Cmd = append(phase.ctrConf.Cmd, args...) + return phase, nil + } +} + +func WithDaemonAccess() func(*Phase) (*Phase, error) { + return func(phase *Phase) (*Phase, error) { + phase.ctrConf.User = "root" + phase.hostConf.Binds = append(phase.hostConf.Binds, "/var/run/docker.sock:/var/run/docker.sock") + return phase, nil + } +} + +func WithRoot() func(*Phase) (*Phase, error) { + return func(phase *Phase) (*Phase, error) { + phase.ctrConf.User = "root" + return phase, nil + } +} + +func WithBinds(binds ...string) func(*Phase) (*Phase, error) { + return func(phase *Phase) (*Phase, error) { + phase.hostConf.Binds = append(phase.hostConf.Binds, binds...) + return phase, nil + } +} + +func WithRegistryAccess(repos ...string) func(*Phase) (*Phase, error) { + return func(phase *Phase) (*Phase, error) { + authConfig, err := auth.BuildEnvVar(authn.DefaultKeychain, repos...) + if err != nil { + return nil, err + } + phase.ctrConf.Env = append(phase.ctrConf.Env, fmt.Sprintf(`CNB_REGISTRY_AUTH=%s`, authConfig)) + phase.hostConf.NetworkMode = "host" + return phase, nil + } +} + +func WithNetwork(networkMode string) func(*Phase) (*Phase, error) { + return func(phase *Phase) (*Phase, error) { + phase.hostConf.NetworkMode = dcontainer.NetworkMode(networkMode) + return phase, nil + } +} + +func (p *Phase) Run(ctx context.Context) error { + var err error + + p.ctr, err = p.docker.ContainerCreate(ctx, p.ctrConf, p.hostConf, nil, "") + if err != nil { + return errors.Wrapf(err, "failed to create '%s' container", p.name) + } + + p.appOnce.Do(func() { + var ( + appReader io.ReadCloser + clientErr error + ) + appReader, err = p.createAppReader() + if err != nil { + err = errors.Wrapf(err, "create tar archive from '%s'", p.appPath) + return + } + defer appReader.Close() + + doneChan := make(chan interface{}) + pr, pw := io.Pipe() + go func() { + clientErr = p.docker.CopyToContainer(ctx, p.ctr.ID, "/", pr, types.CopyToContainerOptions{}) + close(doneChan) + }() + func() { + defer pw.Close() + _, err = io.Copy(pw, appReader) + }() + + <-doneChan + if err == nil { + err = clientErr + } + }) + + if err != nil { + return errors.Wrapf(err, "failed to copy files to '%s' container", p.name) + } + + return container.Run( + ctx, + p.docker, + p.ctr.ID, + logging.NewPrefixWriter(logging.GetInfoWriter(p.logger), p.name), + logging.NewPrefixWriter(logging.GetInfoErrorWriter(p.logger), p.name), + ) +} + +func (p *Phase) Cleanup() error { + return p.docker.ContainerRemove(context.Background(), p.ctr.ID, types.ContainerRemoveOptions{Force: true}) +} + +func (p *Phase) createAppReader() (io.ReadCloser, error) { + fi, err := os.Stat(p.appPath) + if err != nil { + return nil, err + } + + if fi.IsDir() { + var mode int64 = -1 + if runtime.GOOS == "windows" { + mode = 0777 + } + + return archive.ReadDirAsTar(p.appPath, appDir, p.uid, p.gid, mode), nil + } + + return archive.ReadZipAsTar(p.appPath, appDir, p.uid, p.gid, -1), nil +} diff --git a/vendor/github.com/buildpacks/pack/internal/build/phases.go b/vendor/github.com/buildpacks/pack/internal/build/phases.go new file mode 100644 index 00000000000..41936caa211 --- /dev/null +++ b/vendor/github.com/buildpacks/pack/internal/build/phases.go @@ -0,0 +1,201 @@ +package build + +import ( + "context" + "fmt" + + "github.com/Masterminds/semver" +) + +const ( + layersDir = "/layers" + appDir = "/workspace" + cacheDir = "/cache" + launchCacheDir = "/launch-cache" + platformDir = "/platform" +) + +func (l *Lifecycle) Detect(ctx context.Context, networkMode string) error { + detect, err := l.NewPhase( + "detector", + WithArgs( + l.withLogLevel( + "-app", appDir, + "-platform", platformDir, + )..., + ), + WithNetwork(networkMode), + ) + if err != nil { + return err + } + defer detect.Cleanup() + return detect.Run(ctx) +} + +func (l *Lifecycle) Restore(ctx context.Context, cacheName string) error { + cacheFlag := "-path" + if l.CombinedExporterCacher() { + cacheFlag = "-cache-dir" + } + + restore, err := l.NewPhase( + "restorer", + WithDaemonAccess(), + WithArgs( + l.withLogLevel( + cacheFlag, cacheDir, + "-layers", layersDir, + )..., + ), + WithBinds(fmt.Sprintf("%s:%s", cacheName, cacheDir)), + ) + if err != nil { + return err + } + defer restore.Cleanup() + return restore.Run(ctx) +} + +func (l *Lifecycle) Analyze(ctx context.Context, repoName, cacheName string, publish, clearCache bool) error { + analyze, err := l.newAnalyze(repoName, cacheName, publish, clearCache) + if err != nil { + return err + } + defer analyze.Cleanup() + return analyze.Run(ctx) +} + +func (l *Lifecycle) newAnalyze(repoName, cacheName string, publish, clearCache bool) (*Phase, error) { + args := []string{ + "-layers", layersDir, + repoName, + } + if clearCache { + args = prependArg("-skip-layers", args) + } else if l.CombinedExporterCacher() { + args = append([]string{"-cache-dir", cacheDir}, args...) + } + + if publish { + return l.NewPhase( + "analyzer", + WithRegistryAccess(repoName), + WithRoot(), + WithArgs(args...), + WithBinds(fmt.Sprintf("%s:%s", cacheName, cacheDir)), + ) + } + return l.NewPhase( + "analyzer", + WithDaemonAccess(), + WithArgs( + l.withLogLevel( + prependArg( + "-daemon", + args, + )..., + )..., + ), + WithBinds(fmt.Sprintf("%s:%s", cacheName, cacheDir)), + ) +} + +func prependArg(arg string, args []string) []string { + return append([]string{arg}, args...) +} + +func (l *Lifecycle) Build(ctx context.Context, networkMode string) error { + build, err := l.NewPhase( + "builder", + WithArgs( + "-layers", layersDir, + "-app", appDir, + "-platform", platformDir, + ), + WithNetwork(networkMode), + ) + if err != nil { + return err + } + defer build.Cleanup() + return build.Run(ctx) +} + +func (l *Lifecycle) Export(ctx context.Context, repoName string, runImage string, publish bool, launchCacheName, cacheName string) error { + export, err := l.newExport(repoName, runImage, publish, launchCacheName, cacheName) + if err != nil { + return err + } + defer export.Cleanup() + return export.Run(ctx) +} + +func (l *Lifecycle) newExport(repoName, runImage string, publish bool, launchCacheName, cacheName string) (*Phase, error) { + if publish { + return l.NewPhase( + "exporter", + WithRegistryAccess(repoName, runImage), + WithArgs( + l.withLogLevel( + "-image", runImage, + "-layers", layersDir, + "-app", appDir, + repoName, + )..., + ), + ) + } + + args := []string{ + "-image", runImage, + "-layers", layersDir, + "-app", appDir, + "-daemon", + "-launch-cache", launchCacheDir, + repoName, + } + if l.CombinedExporterCacher() { + args = append([]string{"-cache-dir", cacheDir}, args...) + } + + return l.NewPhase( + "exporter", + WithDaemonAccess(), + WithArgs( + l.withLogLevel(args...)..., + ), + WithBinds(fmt.Sprintf("%s:%s", launchCacheName, launchCacheDir)), + WithBinds(fmt.Sprintf("%s:%s", cacheName, cacheDir)), + ) +} + +// The cache phase is obsolete with Platform API 0.2 and will be removed in the future. +func (l *Lifecycle) Cache(ctx context.Context, cacheName string) error { + cache, err := l.NewPhase( + "cacher", + WithDaemonAccess(), + WithArgs( + l.withLogLevel( + "-path", cacheDir, + "-layers", layersDir, + )..., + ), + WithBinds(fmt.Sprintf("%s:%s", cacheName, cacheDir)), + ) + if err != nil { + return err + } + defer cache.Cleanup() + return cache.Run(ctx) +} + +func (l *Lifecycle) withLogLevel(args ...string) []string { + version := semver.MustParse(l.version) + if semver.MustParse("0.4.0").LessThan(version) { + if l.logger.IsVerbose() { + return append([]string{"-log-level", "debug"}, args...) + } + } + return args +} diff --git a/vendor/github.com/buildpacks/pack/internal/builder/builder.go b/vendor/github.com/buildpacks/pack/internal/builder/builder.go new file mode 100644 index 00000000000..34168c437de --- /dev/null +++ b/vendor/github.com/buildpacks/pack/internal/builder/builder.go @@ -0,0 +1,676 @@ +package builder + +import ( + "archive/tar" + "bytes" + "fmt" + "io" + "io/ioutil" + "os" + "path" + "path/filepath" + "regexp" + "strconv" + "time" + + "github.com/BurntSushi/toml" + "github.com/buildpacks/imgutil" + "github.com/pkg/errors" + + "github.com/buildpacks/pack/builder" + "github.com/buildpacks/pack/cmd" + "github.com/buildpacks/pack/internal/api" + "github.com/buildpacks/pack/internal/archive" + "github.com/buildpacks/pack/internal/dist" + "github.com/buildpacks/pack/internal/stack" + "github.com/buildpacks/pack/internal/style" + "github.com/buildpacks/pack/logging" +) + +const ( + packName = "Pack CLI" + + cnbDir = "/cnb" + + orderPath = "/cnb/order.toml" + stackPath = "/cnb/stack.toml" + platformDir = "/platform" + lifecycleDir = "/cnb/lifecycle" + workspaceDir = "/workspace" + layersDir = "/layers" + + metadataLabel = "io.buildpacks.builder.metadata" + stackLabel = "io.buildpacks.stack.id" + + envUID = "CNB_USER_ID" + envGID = "CNB_GROUP_ID" +) + +type Builder struct { + baseImageName string + image imgutil.Image + lifecycle Lifecycle + lifecycleDescriptor LifecycleDescriptor + additionalBuildpacks []dist.Buildpack + metadata Metadata + mixins []string + env map[string]string + UID, GID int + StackID string + replaceOrder bool + order dist.Order +} + +type orderTOML struct { + Order dist.Order `toml:"order"` +} + +// FromImage constructs a builder from a builder image +func FromImage(img imgutil.Image) (*Builder, error) { + var metadata Metadata + if ok, err := dist.GetLabel(img, metadataLabel, &metadata); err != nil { + return nil, err + } else if !ok { + return nil, fmt.Errorf("builder %s missing label %s -- try recreating builder", style.Symbol(img.Name()), style.Symbol(metadataLabel)) + } + return constructBuilder(img, "", metadata) +} + +// New constructs a new builder from base image +func New(baseImage imgutil.Image, name string) (*Builder, error) { + var metadata Metadata + if _, err := dist.GetLabel(baseImage, metadataLabel, &metadata); err != nil { + return nil, err + } + return constructBuilder(baseImage, name, metadata) +} + +func constructBuilder(img imgutil.Image, newName string, metadata Metadata) (*Builder, error) { + uid, gid, err := userAndGroupIDs(img) + if err != nil { + return nil, err + } + + stackID, err := img.Label(stackLabel) + if err != nil { + return nil, errors.Wrapf(err, "get label %s from image %s", style.Symbol(stackLabel), style.Symbol(img.Name())) + } + if stackID == "" { + return nil, fmt.Errorf("image %s missing label %s", style.Symbol(img.Name()), style.Symbol(stackLabel)) + } + + var mixins []string + if _, err := dist.GetLabel(img, stack.MixinsLabel, &mixins); err != nil { + return nil, err + } + + baseName := img.Name() + if newName != "" && baseName != newName { + img.Rename(newName) + } + + lifecycleVersion := VersionMustParse(AssumedLifecycleVersion) + if metadata.Lifecycle.Version != nil { + lifecycleVersion = metadata.Lifecycle.Version + } + + buildpackAPIVersion := api.MustParse(dist.AssumedBuildpackAPIVersion) + if metadata.Lifecycle.API.BuildpackVersion != nil { + buildpackAPIVersion = metadata.Lifecycle.API.BuildpackVersion + } + + platformAPIVersion := api.MustParse(AssumedPlatformAPIVersion) + if metadata.Lifecycle.API.PlatformVersion != nil { + platformAPIVersion = metadata.Lifecycle.API.PlatformVersion + } + + var order dist.Order + if ok, err := dist.GetLabel(img, OrderLabel, &order); err != nil { + return nil, err + } else if !ok { + order = metadata.Groups.ToOrder() + } + + return &Builder{ + baseImageName: baseName, + image: img, + metadata: metadata, + mixins: mixins, + order: order, + UID: uid, + GID: gid, + StackID: stackID, + lifecycleDescriptor: LifecycleDescriptor{ + Info: LifecycleInfo{ + Version: lifecycleVersion, + }, + API: LifecycleAPI{ + PlatformVersion: platformAPIVersion, + BuildpackVersion: buildpackAPIVersion, + }, + }, + env: map[string]string{}, + }, nil +} + +func (b *Builder) Description() string { + return b.metadata.Description +} + +func (b *Builder) LifecycleDescriptor() LifecycleDescriptor { + return b.lifecycleDescriptor +} + +func (b *Builder) Buildpacks() []BuildpackMetadata { + return b.metadata.Buildpacks +} + +func (b *Builder) CreatedBy() CreatorMetadata { + return b.metadata.CreatedBy +} + +func (b *Builder) Order() dist.Order { + return b.order +} + +func (b *Builder) Name() string { + return b.image.Name() +} + +func (b *Builder) Image() imgutil.Image { + return b.image +} + +func (b *Builder) Stack() StackMetadata { + return b.metadata.Stack +} +func (b *Builder) Mixins() []string { + return b.mixins +} + +func (b *Builder) AddBuildpack(bp dist.Buildpack) { + b.additionalBuildpacks = append(b.additionalBuildpacks, bp) + b.metadata.Buildpacks = append(b.metadata.Buildpacks, BuildpackMetadata{ + BuildpackInfo: bp.Descriptor().Info, + }) +} + +func (b *Builder) SetLifecycle(lifecycle Lifecycle) error { + b.lifecycle = lifecycle + b.lifecycleDescriptor = lifecycle.Descriptor() + return nil +} + +func (b *Builder) SetEnv(env map[string]string) { + b.env = env +} + +func (b *Builder) SetOrder(order dist.Order) { + b.order = order + b.replaceOrder = true +} + +func (b *Builder) SetDescription(description string) { + b.metadata.Description = description +} + +func (b *Builder) SetStack(stackConfig builder.StackConfig) { + b.metadata.Stack = StackMetadata{ + RunImage: RunImageMetadata{ + Image: stackConfig.RunImage, + Mirrors: stackConfig.RunImageMirrors, + }, + } +} + +func (b *Builder) Save(logger logging.Logger) error { + resolvedOrder, err := processOrder(b.metadata.Buildpacks, b.order) + if err != nil { + return errors.Wrap(err, "processing order") + } + + b.metadata.Groups = orderToV1Order(resolvedOrder) + processMetadata(&b.metadata) + + tmpDir, err := ioutil.TempDir("", "create-builder-scratch") + if err != nil { + return err + } + defer os.RemoveAll(tmpDir) + + dirsTar, err := b.defaultDirsLayer(tmpDir) + if err != nil { + return err + } + if err := b.image.AddLayer(dirsTar); err != nil { + return errors.Wrap(err, "adding default dirs layer") + } + + if b.lifecycle != nil { + b.metadata.Lifecycle.LifecycleInfo = b.lifecycle.Descriptor().Info + b.metadata.Lifecycle.API = b.lifecycle.Descriptor().API + lifecycleTar, err := b.lifecycleLayer(tmpDir) + if err != nil { + return err + } + if err := b.image.AddLayer(lifecycleTar); err != nil { + return errors.Wrap(err, "adding lifecycle layer") + } + } + + if err := validateBuildpacks(b.StackID, b.Mixins(), b.LifecycleDescriptor(), b.additionalBuildpacks); err != nil { + return errors.Wrap(err, "validating buildpacks") + } + + bpLayers := dist.BuildpackLayers{} + if _, err := dist.GetLabel(b.image, dist.BuildpackLayersLabel, &bpLayers); err != nil { + return err + } + + for _, bp := range b.additionalBuildpacks { + bpLayerTar, err := dist.BuildpackToLayerTar(tmpDir, bp) + if err != nil { + return err + } + + if err := b.image.AddLayer(bpLayerTar); err != nil { + return errors.Wrapf(err, + "adding layer tar for buildpack %s", + style.Symbol(bp.Descriptor().Info.FullName()), + ) + } + + diffID, err := dist.LayerDiffID(bpLayerTar) + if err != nil { + return errors.Wrapf(err, + "getting content hashes for buildpack %s", + style.Symbol(bp.Descriptor().Info.FullName()), + ) + } + + bpInfo := bp.Descriptor().Info + if _, ok := bpLayers[bpInfo.ID][bpInfo.Version]; ok { + logger.Warnf( + "buildpack %s already exists on builder and will be overwritten", + style.Symbol(bpInfo.FullName()), + ) + } + + dist.AddBuildpackToLayersMD(bpLayers, bp.Descriptor(), diffID.String()) + } + + if err := dist.SetLabel(b.image, dist.BuildpackLayersLabel, bpLayers); err != nil { + return err + } + + if b.replaceOrder { + orderTar, err := b.orderLayer(resolvedOrder, tmpDir) + if err != nil { + return err + } + if err := b.image.AddLayer(orderTar); err != nil { + return errors.Wrap(err, "adding order.tar layer") + } + + if err := dist.SetLabel(b.image, OrderLabel, b.order); err != nil { + return err + } + } + + stackTar, err := b.stackLayer(tmpDir) + if err != nil { + return err + } + if err := b.image.AddLayer(stackTar); err != nil { + return errors.Wrap(err, "adding stack.tar layer") + } + + compatTar, err := b.compatLayer(resolvedOrder, tmpDir) + if err != nil { + return err + } + + if err := b.image.AddLayer(compatTar); err != nil { + return errors.Wrap(err, "adding compat.tar layer") + } + + envTar, err := b.envLayer(tmpDir, b.env) + if err != nil { + return err + } + if err := b.image.AddLayer(envTar); err != nil { + return errors.Wrap(err, "adding env layer") + } + + b.metadata.CreatedBy = CreatorMetadata{ + Name: packName, + Version: cmd.Version, + } + + if err := dist.SetLabel(b.image, metadataLabel, b.metadata); err != nil { + return err + } + + if err := dist.SetLabel(b.image, stack.MixinsLabel, b.mixins); err != nil { + return err + } + + if err := b.image.SetWorkingDir(layersDir); err != nil { + return errors.Wrap(err, "failed to set working dir") + } + + return b.image.Save() +} + +func processOrder(buildpacks []BuildpackMetadata, order dist.Order) (dist.Order, error) { + resolvedOrder := dist.Order{} + + for gi, g := range order { + resolvedOrder = append(resolvedOrder, dist.OrderEntry{}) + + for _, bpRef := range g.Group { + var matchingBps []dist.BuildpackInfo + for _, bp := range buildpacks { + if bpRef.ID == bp.ID { + matchingBps = append(matchingBps, bp.BuildpackInfo) + } + } + + if len(matchingBps) == 0 { + return dist.Order{}, fmt.Errorf("no versions of buildpack %s were found on the builder", style.Symbol(bpRef.ID)) + } + + if bpRef.Version == "" { + if len(matchingBps) > 1 { + return dist.Order{}, fmt.Errorf("unable to resolve version: multiple versions of %s - must specify an explicit version", style.Symbol(bpRef.ID)) + } + + bpRef.Version = matchingBps[0].Version + } + + if !hasBuildpackWithVersion(matchingBps, bpRef.Version) { + return dist.Order{}, fmt.Errorf("buildpack %s with version %s was not found on the builder", style.Symbol(bpRef.ID), style.Symbol(bpRef.Version)) + } + + resolvedOrder[gi].Group = append(resolvedOrder[gi].Group, bpRef) + } + } + + return resolvedOrder, nil +} + +func hasBuildpackWithVersion(bps []dist.BuildpackInfo, version string) bool { + for _, bp := range bps { + if bp.Version == version { + return true + } + } + return false +} + +func validateBuildpacks(stackID string, mixins []string, lifecycleDescriptor LifecycleDescriptor, bps []dist.Buildpack) error { + bpLookup := map[string]interface{}{} + + for _, bp := range bps { + bpLookup[bp.Descriptor().Info.FullName()] = nil + } + + for _, bp := range bps { + bpd := bp.Descriptor() + + if !bpd.API.SupportsVersion(lifecycleDescriptor.API.BuildpackVersion) { + return fmt.Errorf( + "buildpack %s (Buildpack API version %s) is incompatible with lifecycle %s (Buildpack API version %s)", + style.Symbol(bpd.Info.FullName()), + bpd.API.String(), + style.Symbol(lifecycleDescriptor.Info.Version.String()), + lifecycleDescriptor.API.BuildpackVersion.String(), + ) + } + + if len(bpd.Stacks) >= 1 { // standard buildpack + if err := bpd.EnsureStackSupport(stackID, mixins, false); err != nil { + return err + } + } else { // order buildpack + for _, g := range bpd.Order { + for _, r := range g.Group { + if _, ok := bpLookup[r.FullName()]; !ok { + return fmt.Errorf( + "buildpack %s not found on the builder", + style.Symbol(r.FullName()), + ) + } + } + } + } + } + + return nil +} + +func userAndGroupIDs(img imgutil.Image) (int, int, error) { + sUID, err := img.Env(envUID) + if err != nil { + return 0, 0, errors.Wrap(err, "reading builder env variables") + } else if sUID == "" { + return 0, 0, fmt.Errorf("image %s missing required env var %s", style.Symbol(img.Name()), style.Symbol(envUID)) + } + + sGID, err := img.Env(envGID) + if err != nil { + return 0, 0, errors.Wrap(err, "reading builder env variables") + } else if sGID == "" { + return 0, 0, fmt.Errorf("image %s missing required env var %s", style.Symbol(img.Name()), style.Symbol(envGID)) + } + + var uid, gid int + uid, err = strconv.Atoi(sUID) + if err != nil { + return 0, 0, fmt.Errorf("failed to parse %s, value %s should be an integer", style.Symbol(envUID), style.Symbol(sUID)) + } + + gid, err = strconv.Atoi(sGID) + if err != nil { + return 0, 0, fmt.Errorf("failed to parse %s, value %s should be an integer", style.Symbol(envGID), style.Symbol(sGID)) + } + + return uid, gid, nil +} + +func (b *Builder) defaultDirsLayer(dest string) (string, error) { + fh, err := os.Create(filepath.Join(dest, "dirs.tar")) + if err != nil { + return "", err + } + defer fh.Close() + + tw := tar.NewWriter(fh) + defer tw.Close() + + ts := archive.NormalizedDateTime + + if err := tw.WriteHeader(b.packOwnedDir(workspaceDir, ts)); err != nil { + return "", errors.Wrapf(err, "creating %s dir in layer", style.Symbol(workspaceDir)) + } + + if err := tw.WriteHeader(b.packOwnedDir(layersDir, ts)); err != nil { + return "", errors.Wrapf(err, "creating %s dir in layer", style.Symbol(layersDir)) + } + + if err := tw.WriteHeader(b.rootOwnedDir(cnbDir, ts)); err != nil { + return "", errors.Wrapf(err, "creating %s dir in layer", style.Symbol(cnbDir)) + } + + if err := tw.WriteHeader(b.rootOwnedDir(dist.BuildpacksDir, ts)); err != nil { + return "", errors.Wrapf(err, "creating %s dir in layer", style.Symbol(dist.BuildpacksDir)) + } + + if err := tw.WriteHeader(b.rootOwnedDir(platformDir, ts)); err != nil { + return "", errors.Wrapf(err, "creating %s dir in layer", style.Symbol(platformDir)) + } + + if err := tw.WriteHeader(b.rootOwnedDir(platformDir+"/env", ts)); err != nil { + return "", errors.Wrapf(err, "creating %s dir in layer", style.Symbol(platformDir+"/env")) + } + + return fh.Name(), nil +} + +func (b *Builder) packOwnedDir(path string, time time.Time) *tar.Header { + return &tar.Header{ + Typeflag: tar.TypeDir, + Name: path, + Mode: 0755, + ModTime: time, + Uid: b.UID, + Gid: b.GID, + } +} + +func (b *Builder) rootOwnedDir(path string, time time.Time) *tar.Header { + return &tar.Header{ + Typeflag: tar.TypeDir, + Name: path, + Mode: 0755, + ModTime: time, + } +} + +func (b *Builder) orderLayer(order dist.Order, dest string) (string, error) { + contents, err := orderFileContents(order) + if err != nil { + return "", err + } + + layerTar := filepath.Join(dest, "order.tar") + err = archive.CreateSingleFileTar(layerTar, orderPath, contents) + if err != nil { + return "", errors.Wrapf(err, "failed to create order.toml layer tar") + } + + return layerTar, nil +} + +func orderFileContents(order dist.Order) (string, error) { + buf := &bytes.Buffer{} + + tomlData := orderTOML{Order: order} + if err := toml.NewEncoder(buf).Encode(tomlData); err != nil { + return "", errors.Wrapf(err, "failed to marshal order.toml") + } + return buf.String(), nil +} + +func (b *Builder) stackLayer(dest string) (string, error) { + buf := &bytes.Buffer{} + err := toml.NewEncoder(buf).Encode(b.metadata.Stack) + if err != nil { + return "", errors.Wrapf(err, "failed to marshal stack.toml") + } + + layerTar := filepath.Join(dest, "stack.tar") + err = archive.CreateSingleFileTar(layerTar, stackPath, buf.String()) + if err != nil { + return "", errors.Wrapf(err, "failed to create stack.toml layer tar") + } + + return layerTar, nil +} + +func (b *Builder) embedLifecycleTar(tw *tar.Writer) error { + var regex = regexp.MustCompile(`^[^/]+/([^/]+)$`) + + lr, err := b.lifecycle.Open() + if err != nil { + return errors.Wrap(err, "failed to open lifecycle") + } + defer lr.Close() + tr := tar.NewReader(lr) + for { + header, err := tr.Next() + if err == io.EOF { + break + } + if err != nil { + return errors.Wrap(err, "failed to get next tar entry") + } + + pathMatches := regex.FindStringSubmatch(path.Clean(header.Name)) + if pathMatches != nil { + binaryName := pathMatches[1] + + header.Name = lifecycleDir + "/" + binaryName + err = tw.WriteHeader(header) + if err != nil { + return errors.Wrapf(err, "failed to write header for '%s'", header.Name) + } + + buf, err := ioutil.ReadAll(tr) + if err != nil { + return errors.Wrapf(err, "failed to read contents of '%s'", header.Name) + } + + _, err = tw.Write(buf) + if err != nil { + return errors.Wrapf(err, "failed to write contents to '%s'", header.Name) + } + } + } + + return nil +} + +func (b *Builder) envLayer(dest string, env map[string]string) (string, error) { + fh, err := os.Create(filepath.Join(dest, "env.tar")) + if err != nil { + return "", err + } + defer fh.Close() + + tw := tar.NewWriter(fh) + defer tw.Close() + + for k, v := range env { + if err := tw.WriteHeader(&tar.Header{ + Name: path.Join(platformDir, "env", k), + Size: int64(len(v)), + Mode: 0644, + ModTime: archive.NormalizedDateTime, + }); err != nil { + return "", err + } + if _, err := tw.Write([]byte(v)); err != nil { + return "", err + } + } + + return fh.Name(), nil +} + +func (b *Builder) lifecycleLayer(dest string) (string, error) { + fh, err := os.Create(filepath.Join(dest, "lifecycle.tar")) + if err != nil { + return "", err + } + defer fh.Close() + + tw := tar.NewWriter(fh) + defer tw.Close() + + if err := tw.WriteHeader(&tar.Header{ + Typeflag: tar.TypeDir, + Name: lifecycleDir, + Mode: 0755, + ModTime: archive.NormalizedDateTime, + }); err != nil { + return "", err + } + + err = b.embedLifecycleTar(tw) + if err != nil { + return "", errors.Wrap(err, "embedding lifecycle tar") + } + + return fh.Name(), nil +} diff --git a/vendor/github.com/buildpacks/pack/internal/builder/compat.go b/vendor/github.com/buildpacks/pack/internal/builder/compat.go new file mode 100644 index 00000000000..2a93fbb2137 --- /dev/null +++ b/vendor/github.com/buildpacks/pack/internal/builder/compat.go @@ -0,0 +1,152 @@ +package builder + +import ( + "archive/tar" + "bytes" + "fmt" + "os" + "path" + + "github.com/BurntSushi/toml" + "github.com/pkg/errors" + + "github.com/buildpacks/pack/internal/api" + "github.com/buildpacks/pack/internal/archive" + "github.com/buildpacks/pack/internal/dist" + "github.com/buildpacks/pack/internal/style" +) + +const ( + compatBuildpacksDir = "/buildpacks" + compatLifecycleDir = "/lifecycle" + compatStackPath = "/buildpacks/stack.toml" +) + +type V1Order []V1Group + +type V1Group struct { + Buildpacks []dist.BuildpackRef `toml:"buildpacks" json:"buildpacks"` +} + +func (o V1Order) ToOrder() dist.Order { + var order dist.Order + for _, gp := range o { + var buildpacks []dist.BuildpackRef + buildpacks = append(buildpacks, gp.Buildpacks...) + + order = append(order, dist.OrderEntry{ + Group: buildpacks, + }) + } + return order +} + +func orderToV1Order(o dist.Order) V1Order { + var order V1Order //nolint:prealloc + for _, gp := range o { + var buildpacks []dist.BuildpackRef + buildpacks = append(buildpacks, gp.Group...) + + order = append(order, V1Group{ + Buildpacks: buildpacks, + }) + } + + return order +} + +func (b *Builder) compatLayer(order dist.Order, dest string) (string, error) { + compatTar := path.Join(dest, "compat.tar") + fh, err := os.Create(compatTar) + if err != nil { + return "", err + } + defer fh.Close() + + tw := tar.NewWriter(fh) + defer tw.Close() + + if b.lifecycle != nil { + if err := compatLifecycle(tw); err != nil { + return "", err + } + } + + if err := b.compatBuildpacks(tw); err != nil { + return "", err + } + + if err := b.compatStack(tw); err != nil { + return "", errors.Wrapf(err, "failed to add %s to compat layer", style.Symbol(compatStackPath)) + } + + return compatTar, nil +} + +func compatLifecycle(tw *tar.Writer) error { + return addSymlink(tw, compatLifecycleDir, lifecycleDir) +} + +func (b *Builder) compatBuildpacks(tw *tar.Writer) error { + ts := archive.NormalizedDateTime + if err := tw.WriteHeader(b.rootOwnedDir(compatBuildpacksDir, ts)); err != nil { + return errors.Wrapf(err, "creating %s dir in layer", style.Symbol(dist.BuildpacksDir)) + } + for _, bp := range b.additionalBuildpacks { + descriptor := bp.Descriptor() + + compatDir := path.Join(compatBuildpacksDir, descriptor.EscapedID()) + if err := tw.WriteHeader(b.rootOwnedDir(compatDir, ts)); err != nil { + return errors.Wrapf(err, "creating %s dir in layer", style.Symbol(compatDir)) + } + compatLink := path.Join(compatDir, descriptor.Info.Version) + bpDir := path.Join(dist.BuildpacksDir, descriptor.EscapedID(), descriptor.Info.Version) + if err := addSymlink(tw, compatLink, bpDir); err != nil { + return err + } + + bpAPIVersion := b.lifecycleDescriptor.API.BuildpackVersion + if bpAPIVersion != nil && bpAPIVersion.Equal(api.MustParse("0.1")) { + if err := symlinkLatest(tw, bpDir, descriptor, b.metadata); err != nil { + return err + } + } + } + return nil +} + +func (b *Builder) compatStack(tw *tar.Writer) error { + stackBuf := &bytes.Buffer{} + if err := toml.NewEncoder(stackBuf).Encode(b.metadata.Stack); err != nil { + return errors.Wrapf(err, "failed to marshal stack.toml") + } + return archive.AddFileToTar(tw, compatStackPath, stackBuf.String()) +} + +func addSymlink(tw *tar.Writer, name, linkName string) error { + if err := tw.WriteHeader(&tar.Header{ + Name: name, + Linkname: linkName, + Typeflag: tar.TypeSymlink, + Mode: 0644, + ModTime: archive.NormalizedDateTime, + }); err != nil { + return errors.Wrapf(err, "creating %s symlink", style.Symbol(name)) + } + return nil +} + +// Deprecated: The 'latest' symlink is in place for backwards compatibility only. This should be removed as soon +// as we no longer support older releases that rely on it. +func symlinkLatest(tw *tar.Writer, baseTarDir string, bp dist.BuildpackDescriptor, metadata Metadata) error { + for _, b := range metadata.Buildpacks { + if b.ID == bp.Info.ID && b.Version == bp.Info.Version && b.Latest { + name := fmt.Sprintf("%s/%s/%s", compatBuildpacksDir, bp.EscapedID(), "latest") + if err := addSymlink(tw, name, baseTarDir); err != nil { + return errors.Wrapf(err, "creating latest symlink for buildpack '%s:%s'", bp.Info.ID, bp.Info.Version) + } + break + } + } + return nil +} diff --git a/vendor/github.com/buildpacks/pack/internal/builder/lifecycle.go b/vendor/github.com/buildpacks/pack/internal/builder/lifecycle.go new file mode 100644 index 00000000000..92f00345045 --- /dev/null +++ b/vendor/github.com/buildpacks/pack/internal/builder/lifecycle.go @@ -0,0 +1,149 @@ +package builder + +import ( + "archive/tar" + "fmt" + "io" + "path" + "regexp" + + "github.com/BurntSushi/toml" + "github.com/pkg/errors" + + "github.com/buildpacks/pack/internal/api" + "github.com/buildpacks/pack/internal/archive" + "github.com/buildpacks/pack/internal/dist" +) + +const ( + AssumedLifecycleVersion = "0.3.0" + AssumedPlatformAPIVersion = "0.1" + + DefaultLifecycleVersion = "0.5.0" + DefaultBuildpackAPIVersion = "0.2" + DefaultPlatformAPIVersion = "0.1" +) + +type Blob interface { + Open() (io.ReadCloser, error) +} + +//go:generate mockgen -package testmocks -destination testmocks/mock_lifecycle.go github.com/buildpacks/pack/internal/builder Lifecycle +type Lifecycle interface { + Blob + Descriptor() LifecycleDescriptor +} + +type LifecycleDescriptor struct { + Info LifecycleInfo `toml:"lifecycle"` + API LifecycleAPI `toml:"api"` +} + +type LifecycleInfo struct { + Version *Version `toml:"version" json:"version"` +} + +type LifecycleAPI struct { + BuildpackVersion *api.Version `toml:"buildpack" json:"buildpack"` + PlatformVersion *api.Version `toml:"platform" json:"platform"` +} + +type lifecycle struct { + descriptor LifecycleDescriptor + Blob +} + +func NewLifecycle(blob Blob) (Lifecycle, error) { + var err error + + br, err := blob.Open() + if err != nil { + return nil, errors.Wrap(err, "open lifecycle blob") + } + defer br.Close() + + var descriptor LifecycleDescriptor + _, buf, err := archive.ReadTarEntry(br, "lifecycle.toml") + + //TODO: make lifecycle descriptor required after v0.4.0 release [https://github.com/buildpacks/pack/issues/267] + if err != nil && errors.Cause(err) == archive.ErrEntryNotExist { + return &lifecycle{ + Blob: blob, + descriptor: LifecycleDescriptor{ + Info: LifecycleInfo{ + Version: VersionMustParse(AssumedLifecycleVersion), + }, + API: LifecycleAPI{ + BuildpackVersion: api.MustParse(dist.AssumedBuildpackAPIVersion), + PlatformVersion: api.MustParse(AssumedPlatformAPIVersion), + }, + }, + }, nil + } else if err != nil { + return nil, errors.Wrap(err, "decode lifecycle descriptor") + } + _, err = toml.Decode(string(buf), &descriptor) + if err != nil { + return nil, errors.Wrap(err, "decoding descriptor") + } + + lifecycle := &lifecycle{Blob: blob, descriptor: descriptor} + + if err = lifecycle.validateBinaries(); err != nil { + return nil, errors.Wrap(err, "validating binaries") + } + + return lifecycle, nil +} + +func (l *lifecycle) Descriptor() LifecycleDescriptor { + return l.descriptor +} + +// Binaries returns a list of all binaries contained in the lifecycle. +func (l *lifecycle) binaries() []string { + binaries := []string{ + "detector", + "restorer", + "analyzer", + "builder", + "exporter", + "launcher", + } + if l.Descriptor().API.PlatformVersion.Compare(api.MustParse("0.2")) < 0 { + binaries = append(binaries, "cacher") + } + return binaries +} + +func (l *lifecycle) validateBinaries() error { + rc, err := l.Open() + if err != nil { + return errors.Wrap(err, "create lifecycle blob reader") + } + defer rc.Close() + regex := regexp.MustCompile(`^[^/]+/([^/]+)$`) + headers := map[string]bool{} + tr := tar.NewReader(rc) + for { + header, err := tr.Next() + if err == io.EOF { + break + } + if err != nil { + return errors.Wrap(err, "failed to get next tar entry") + } + + pathMatches := regex.FindStringSubmatch(path.Clean(header.Name)) + if pathMatches != nil { + headers[pathMatches[1]] = true + } + } + for _, p := range l.binaries() { + _, found := headers[p] + if !found { + return fmt.Errorf("did not find '%s' in tar", p) + } + } + return nil +} diff --git a/vendor/github.com/buildpacks/pack/internal/builder/metadata.go b/vendor/github.com/buildpacks/pack/internal/builder/metadata.go new file mode 100644 index 00000000000..939a2a2b7cf --- /dev/null +++ b/vendor/github.com/buildpacks/pack/internal/builder/metadata.go @@ -0,0 +1,55 @@ +package builder + +import "github.com/buildpacks/pack/internal/dist" + +const ( + OrderLabel = "io.buildpacks.buildpack.order" +) + +type Metadata struct { + Description string `json:"description"` + Buildpacks []BuildpackMetadata `json:"buildpacks"` + Groups V1Order `json:"groups"` // deprecated + Stack StackMetadata `json:"stack"` + Lifecycle LifecycleMetadata `json:"lifecycle"` + CreatedBy CreatorMetadata `json:"createdBy"` +} + +type CreatorMetadata struct { + Name string `json:"name"` + Version string `json:"version"` +} + +type BuildpackMetadata struct { + dist.BuildpackInfo + Latest bool `json:"latest"` // deprecated +} + +type LifecycleMetadata struct { + LifecycleInfo + API LifecycleAPI `json:"api"` +} + +type StackMetadata struct { + RunImage RunImageMetadata `json:"runImage" toml:"run-image"` +} + +type RunImageMetadata struct { + Image string `json:"image" toml:"image"` + Mirrors []string `json:"mirrors" toml:"mirrors"` +} + +func processMetadata(md *Metadata) { + for i, bp := range md.Buildpacks { + var matchingBps []dist.BuildpackInfo + for _, bp2 := range md.Buildpacks { + if bp.ID == bp2.ID { + matchingBps = append(matchingBps, bp.BuildpackInfo) + } + } + + if len(matchingBps) == 1 { + md.Buildpacks[i].Latest = true + } + } +} diff --git a/vendor/github.com/buildpacks/pack/internal/builder/version.go b/vendor/github.com/buildpacks/pack/internal/builder/version.go new file mode 100644 index 00000000000..50131ad3ae9 --- /dev/null +++ b/vendor/github.com/buildpacks/pack/internal/builder/version.go @@ -0,0 +1,36 @@ +package builder + +import ( + "github.com/Masterminds/semver" + "github.com/pkg/errors" +) + +// Version is an extension to semver.Version to make it marshalable. +type Version struct { + semver.Version +} + +func VersionMustParse(v string) *Version { + return &Version{Version: *semver.MustParse(v)} +} + +func (v *Version) String() string { + return v.Version.String() +} + +// MarshalText makes Version satisfy the encoding.TextMarshaler interface. +func (v *Version) MarshalText() ([]byte, error) { + return []byte(v.Version.Original()), nil +} + +// UnmarshalText makes Version satisfy the encoding.TextUnmarshaler interface. +func (v *Version) UnmarshalText(text []byte) error { + s := string(text) + w, err := semver.NewVersion(s) + if err != nil { + return errors.Wrapf(err, "invalid semantic version %s", s) + } + + v.Version = *w + return nil +} diff --git a/vendor/github.com/buildpacks/pack/internal/buildpackage/builder.go b/vendor/github.com/buildpacks/pack/internal/buildpackage/builder.go new file mode 100644 index 00000000000..5acc1203491 --- /dev/null +++ b/vendor/github.com/buildpacks/pack/internal/buildpackage/builder.go @@ -0,0 +1,115 @@ +package buildpackage + +import ( + "io/ioutil" + "os" + + "github.com/buildpacks/imgutil" + "github.com/pkg/errors" + + "github.com/buildpacks/pack/internal/dist" + "github.com/buildpacks/pack/internal/stack" + "github.com/buildpacks/pack/internal/style" +) + +type ImageFactory interface { + NewImage(repoName string, local bool) (imgutil.Image, error) +} + +type PackageBuilder struct { + buildpack dist.Buildpack + dependencies []dist.Buildpack + imageFactory ImageFactory +} + +func NewBuilder(imageFactory ImageFactory) *PackageBuilder { + return &PackageBuilder{ + imageFactory: imageFactory, + } +} + +func (p *PackageBuilder) SetBuildpack(buildpack dist.Buildpack) { + p.buildpack = buildpack +} + +func (p *PackageBuilder) AddDependency(buildpack dist.Buildpack) { + p.dependencies = append(p.dependencies, buildpack) +} + +func (p *PackageBuilder) Save(repoName string, publish bool) (imgutil.Image, error) { + if p.buildpack == nil { + return nil, errors.New("buildpack must be set") + } + + stacks := p.buildpack.Descriptor().Stacks + for _, bp := range p.dependencies { + bpd := bp.Descriptor() + + if len(stacks) == 0 { + stacks = bpd.Stacks + } else if len(bpd.Stacks) > 0 { // skip over "meta-buildpacks" + stacks = stack.MergeCompatible(stacks, bpd.Stacks) + if len(stacks) == 0 { + return nil, errors.Errorf( + "buildpack %s does not support any stacks from %s", + style.Symbol(p.buildpack.Descriptor().Info.FullName()), + style.Symbol(bpd.Info.FullName()), + ) + } + } + } + + if len(stacks) == 0 { + return nil, errors.Errorf("no compatible stacks among provided buildpacks") + } + + image, err := p.imageFactory.NewImage(repoName, !publish) + if err != nil { + return nil, errors.Wrapf(err, "creating image") + } + + if err := dist.SetLabel(image, MetadataLabel, &Metadata{ + BuildpackInfo: p.buildpack.Descriptor().Info, + Stacks: stacks, + }); err != nil { + return nil, err + } + + tmpDir, err := ioutil.TempDir("", "create-package") + if err != nil { + return nil, err + } + defer os.RemoveAll(tmpDir) + + bpLayers := dist.BuildpackLayers{} + for _, bp := range append(p.dependencies, p.buildpack) { + bpLayerTar, err := dist.BuildpackToLayerTar(tmpDir, bp) + if err != nil { + return nil, err + } + + if err := image.AddLayer(bpLayerTar); err != nil { + return nil, errors.Wrapf(err, "adding layer tar for buildpack %s", style.Symbol(bp.Descriptor().Info.FullName())) + } + + diffID, err := dist.LayerDiffID(bpLayerTar) + if err != nil { + return nil, errors.Wrapf(err, + "getting content hashes for buildpack %s", + style.Symbol(bp.Descriptor().Info.FullName()), + ) + } + + dist.AddBuildpackToLayersMD(bpLayers, bp.Descriptor(), diffID.String()) + } + + if err := dist.SetLabel(image, dist.BuildpackLayersLabel, bpLayers); err != nil { + return nil, err + } + + if err := image.Save(); err != nil { + return nil, err + } + + return image, nil +} diff --git a/vendor/github.com/buildpacks/pack/internal/buildpackage/buildpackage.go b/vendor/github.com/buildpacks/pack/internal/buildpackage/buildpackage.go new file mode 100644 index 00000000000..845d7f00ee5 --- /dev/null +++ b/vendor/github.com/buildpacks/pack/internal/buildpackage/buildpackage.go @@ -0,0 +1,17 @@ +package buildpackage + +import ( + "github.com/buildpacks/pack/internal/dist" +) + +const MetadataLabel = "io.buildpacks.buildpackage.metadata" + +type Config struct { + Buildpack dist.BuildpackURI `toml:"buildpack"` + Dependencies []dist.ImageOrURI `toml:"dependencies"` +} + +type Metadata struct { + dist.BuildpackInfo + Stacks []dist.Stack `toml:"stacks" json:"stacks"` +} diff --git a/vendor/github.com/buildpacks/pack/internal/cache/image_cache.go b/vendor/github.com/buildpacks/pack/internal/cache/image_cache.go new file mode 100644 index 00000000000..ec85baab3a6 --- /dev/null +++ b/vendor/github.com/buildpacks/pack/internal/cache/image_cache.go @@ -0,0 +1,38 @@ +package cache + +import ( + "context" + "crypto/sha256" + "fmt" + + "github.com/docker/docker/api/types" + "github.com/docker/docker/client" + "github.com/google/go-containerregistry/pkg/name" +) + +type ImageCache struct { + docker *client.Client + image string +} + +func NewImageCache(imageRef name.Reference, dockerClient *client.Client) *ImageCache { + sum := sha256.Sum256([]byte(imageRef.Name())) + return &ImageCache{ + image: fmt.Sprintf("pack-cache-%x", sum[:6]), + docker: dockerClient, + } +} + +func (c *ImageCache) Name() string { + return c.image +} + +func (c *ImageCache) Clear(ctx context.Context) error { + _, err := c.docker.ImageRemove(ctx, c.Name(), types.ImageRemoveOptions{ + Force: true, + }) + if err != nil && !client.IsErrNotFound(err) { + return err + } + return nil +} diff --git a/vendor/github.com/buildpacks/pack/internal/cache/volume_cache.go b/vendor/github.com/buildpacks/pack/internal/cache/volume_cache.go new file mode 100644 index 00000000000..f12391f7082 --- /dev/null +++ b/vendor/github.com/buildpacks/pack/internal/cache/volume_cache.go @@ -0,0 +1,35 @@ +package cache + +import ( + "context" + "crypto/sha256" + "fmt" + + "github.com/docker/docker/client" + "github.com/google/go-containerregistry/pkg/name" +) + +type VolumeCache struct { + docker *client.Client + volume string +} + +func NewVolumeCache(imageRef name.Reference, suffix string, dockerClient *client.Client) *VolumeCache { + sum := sha256.Sum256([]byte(imageRef.Name())) + return &VolumeCache{ + volume: fmt.Sprintf("pack-cache-%x.%s", sum[:6], suffix), + docker: dockerClient, + } +} + +func (c *VolumeCache) Name() string { + return c.volume +} + +func (c *VolumeCache) Clear(ctx context.Context) error { + err := c.docker.VolumeRemove(ctx, c.Name(), true) + if err != nil && !client.IsErrNotFound(err) { + return err + } + return nil +} diff --git a/vendor/github.com/buildpacks/pack/internal/config/config.go b/vendor/github.com/buildpacks/pack/internal/config/config.go new file mode 100644 index 00000000000..86c8478d375 --- /dev/null +++ b/vendor/github.com/buildpacks/pack/internal/config/config.go @@ -0,0 +1,77 @@ +package config + +import ( + "os" + "path/filepath" + + "github.com/BurntSushi/toml" + "github.com/pkg/errors" +) + +type Config struct { + RunImages []RunImage `toml:"run-images"` + DefaultBuilder string `toml:"default-builder-image,omitempty"` +} + +type RunImage struct { + Image string `toml:"image"` + Mirrors []string `toml:"mirrors"` +} + +func DefaultConfigPath() (string, error) { + home, err := PackHome() + if err != nil { + return "", errors.Wrap(err, "getting pack home") + } + return filepath.Join(home, "config.toml"), nil +} + +func PackHome() (string, error) { + packHome := os.Getenv("PACK_HOME") + if packHome == "" { + home, err := os.UserHomeDir() + if err != nil { + return "", errors.Wrap(err, "getting user home") + } + packHome = filepath.Join(home, ".pack") + } + return packHome, nil +} + +func Read(path string) (Config, error) { + cfg := Config{} + _, err := toml.DecodeFile(path, &cfg) + if err != nil && !os.IsNotExist(err) { + return Config{}, errors.Wrapf(err, "failed to read config file at path %s", path) + } + + return cfg, nil +} + +func Write(cfg Config, path string) error { + if err := MkdirAll(filepath.Dir(path)); err != nil { + return err + } + w, err := os.Create(path) + if err != nil { + return err + } + defer w.Close() + + return toml.NewEncoder(w).Encode(cfg) +} + +func MkdirAll(path string) error { + return os.MkdirAll(path, 0777) +} + +func SetRunImageMirrors(cfg Config, image string, mirrors []string) Config { + for i := range cfg.RunImages { + if cfg.RunImages[i].Image == image { + cfg.RunImages[i].Mirrors = mirrors + return cfg + } + } + cfg.RunImages = append(cfg.RunImages, RunImage{Image: image, Mirrors: mirrors}) + return cfg +} diff --git a/vendor/github.com/buildpacks/pack/internal/container/run.go b/vendor/github.com/buildpacks/pack/internal/container/run.go new file mode 100644 index 00000000000..e615f04bab9 --- /dev/null +++ b/vendor/github.com/buildpacks/pack/internal/container/run.go @@ -0,0 +1,45 @@ +package container + +import ( + "context" + "fmt" + "io" + + "github.com/docker/docker/api/types" + dcontainer "github.com/docker/docker/api/types/container" + "github.com/docker/docker/client" + "github.com/docker/docker/pkg/stdcopy" + "github.com/pkg/errors" +) + +func Run(ctx context.Context, docker *client.Client, ctrID string, out, errOut io.Writer) error { + bodyChan, errChan := docker.ContainerWait(ctx, ctrID, dcontainer.WaitConditionNextExit) + + if err := docker.ContainerStart(ctx, ctrID, types.ContainerStartOptions{}); err != nil { + return errors.Wrap(err, "container start") + } + logs, err := docker.ContainerLogs(ctx, ctrID, types.ContainerLogsOptions{ + ShowStdout: true, + ShowStderr: true, + Follow: true, + }) + if err != nil { + return errors.Wrap(err, "container logs stdout") + } + + copyErr := make(chan error) + go func() { + _, err := stdcopy.StdCopy(out, errOut, logs) + copyErr <- err + }() + + select { + case body := <-bodyChan: + if body.StatusCode != 0 { + return fmt.Errorf("failed with status code: %d", body.StatusCode) + } + case err := <-errChan: + return err + } + return <-copyErr +} diff --git a/vendor/github.com/buildpacks/pack/internal/dist/buildpack.go b/vendor/github.com/buildpacks/pack/internal/dist/buildpack.go new file mode 100644 index 00000000000..183c6f3ff91 --- /dev/null +++ b/vendor/github.com/buildpacks/pack/internal/dist/buildpack.go @@ -0,0 +1,233 @@ +package dist + +import ( + "archive/tar" + "io" + "path" + + "github.com/BurntSushi/toml" + "github.com/pkg/errors" + + "github.com/buildpacks/pack/internal/api" + "github.com/buildpacks/pack/internal/archive" + "github.com/buildpacks/pack/internal/style" +) + +const AssumedBuildpackAPIVersion = "0.1" +const BuildpacksDir = "/cnb/buildpacks" + +type Blob interface { + Open() (io.ReadCloser, error) +} + +type buildpack struct { + descriptor BuildpackDescriptor + Blob `toml:"-"` +} + +func (b *buildpack) Descriptor() BuildpackDescriptor { + return b.descriptor +} + +//go:generate mockgen -package testmocks -destination testmocks/mock_buildpack.go github.com/buildpacks/pack/internal/dist Buildpack +type Buildpack interface { + // Open returns a reader to a tar with contents structured as per the distribution spec + // (currently '/cnbs/buildpacks/{ID}/{version}/*', all entries with a zeroed-out + // timestamp and root UID/GID). + Open() (io.ReadCloser, error) + Descriptor() BuildpackDescriptor +} + +type BuildpackInfo struct { + ID string `toml:"id" json:"id"` + Version string `toml:"version" json:"version,omitempty"` +} + +func (b BuildpackInfo) FullName() string { + if b.Version != "" { + return b.ID + "@" + b.Version + } + return b.ID +} + +type Stack struct { + ID string `json:"id"` + Mixins []string `json:"mixins,omitempty"` +} + +// BuildpackFromRootBlob constructs a buildpack from a blob. It is assumed that the buildpack contents reside at the root of the +// blob. The constructed buildpack contents will be structured as per the distribution spec (currently +// a tar with contents under '/cnbs/buildpacks/{ID}/{version}/*'). +func BuildpackFromRootBlob(blob Blob) (Buildpack, error) { + bpd := BuildpackDescriptor{} + rc, err := blob.Open() + if err != nil { + return nil, errors.Wrap(err, "open buildpack") + } + defer rc.Close() + + _, buf, err := archive.ReadTarEntry(rc, "buildpack.toml") + if err != nil { + return nil, errors.Wrap(err, "reading buildpack.toml") + } + + bpd.API = api.MustParse(AssumedBuildpackAPIVersion) + _, err = toml.Decode(string(buf), &bpd) + if err != nil { + return nil, errors.Wrap(err, "decoding buildpack.toml") + } + + err = validateDescriptor(bpd) + if err != nil { + return nil, errors.Wrap(err, "invalid buildpack.toml") + } + + db := &distBlob{ + openFn: func() io.ReadCloser { + return archive.GenerateTar(func(tw *tar.Writer) error { + return toDistTar(tw, bpd, blob) + }) + }, + } + + return &buildpack{ + descriptor: bpd, + Blob: db, + }, nil +} + +// BuildpackFromTarBlob constructs a buildpack from a ReadCloser to a tar. It is assumed that the buildpack +// contents are structured as per the distribution spec (currently '/cnbs/buildpacks/{ID}/{version}/*'). +func BuildpackFromTarBlob(bpd BuildpackDescriptor, blob Blob) Buildpack { + return &buildpack{ + Blob: blob, + descriptor: bpd, + } +} + +type distBlob struct { + openFn func() io.ReadCloser +} + +func (b *distBlob) Open() (io.ReadCloser, error) { + return b.openFn(), nil +} + +func toDistTar(tw *tar.Writer, bpd BuildpackDescriptor, blob Blob) error { + ts := archive.NormalizedDateTime + + if err := tw.WriteHeader(&tar.Header{ + Typeflag: tar.TypeDir, + Name: path.Join(BuildpacksDir, bpd.EscapedID()), + Mode: 0755, + ModTime: ts, + }); err != nil { + return errors.Wrapf(err, "writing buildpack id dir header") + } + + baseTarDir := path.Join(BuildpacksDir, bpd.EscapedID(), bpd.Info.Version) + if err := tw.WriteHeader(&tar.Header{ + Typeflag: tar.TypeDir, + Name: baseTarDir, + Mode: 0755, + ModTime: ts, + }); err != nil { + return errors.Wrapf(err, "writing buildpack version dir header") + } + + rc, err := blob.Open() + if err != nil { + return errors.Wrap(err, "reading buildpack blob") + } + defer rc.Close() + + tr := tar.NewReader(rc) + for { + header, err := tr.Next() + if err == io.EOF { + break + } + if err != nil { + return errors.Wrap(err, "failed to get next tar entry") + } + + archive.NormalizeHeader(header) + header.Name = path.Clean(header.Name) + if header.Name == "." || header.Name == "/" { + continue + } + + header.Mode = calcFileMode(header) + header.Name = path.Join(baseTarDir, header.Name) + err = tw.WriteHeader(header) + if err != nil { + return errors.Wrapf(err, "failed to write header for '%s'", header.Name) + } + + _, err = io.Copy(tw, tr) + if err != nil { + return errors.Wrapf(err, "failed to write contents to '%s'", header.Name) + } + } + + return nil +} + +func calcFileMode(header *tar.Header) int64 { + switch { + case header.Typeflag == tar.TypeDir: + return 0755 + case nameOneOf(header.Name, + path.Join("bin", "detect"), + path.Join("bin", "build"), + ): + return 0755 + case anyExecBit(header.Mode): + return 0755 + } + + return 0644 +} + +func nameOneOf(name string, paths ...string) bool { + for _, p := range paths { + if name == p { + return true + } + } + return false +} + +func anyExecBit(mode int64) bool { + return mode&0111 != 0 +} + +func validateDescriptor(bpd BuildpackDescriptor) error { + if bpd.Info.ID == "" { + return errors.Errorf("%s is required", style.Symbol("buildpack.id")) + } + + if bpd.Info.Version == "" { + return errors.Errorf("%s is required", style.Symbol("buildpack.version")) + } + + if len(bpd.Order) == 0 && len(bpd.Stacks) == 0 { + return errors.Errorf( + "buildpack %s: must have either %s or an %s defined", + style.Symbol(bpd.Info.FullName()), + style.Symbol("stacks"), + style.Symbol("order"), + ) + } + + if len(bpd.Order) >= 1 && len(bpd.Stacks) >= 1 { + return errors.Errorf( + "buildpack %s: cannot have both %s and an %s defined", + style.Symbol(bpd.Info.FullName()), + style.Symbol("stacks"), + style.Symbol("order"), + ) + } + + return nil +} diff --git a/vendor/github.com/buildpacks/pack/internal/dist/buildpack_descriptor.go b/vendor/github.com/buildpacks/pack/internal/dist/buildpack_descriptor.go new file mode 100644 index 00000000000..6a57a1a7ac2 --- /dev/null +++ b/vendor/github.com/buildpacks/pack/internal/dist/buildpack_descriptor.go @@ -0,0 +1,59 @@ +package dist + +import ( + "fmt" + "sort" + "strings" + + "github.com/buildpacks/pack/internal/api" + "github.com/buildpacks/pack/internal/stringset" + "github.com/buildpacks/pack/internal/style" +) + +type BuildpackDescriptor struct { + API *api.Version `toml:"api"` + Info BuildpackInfo `toml:"buildpack"` + Stacks []Stack `toml:"stacks"` + Order Order `toml:"order"` +} + +func (b *BuildpackDescriptor) EscapedID() string { + return strings.Replace(b.Info.ID, "/", "_", -1) +} + +func (b *BuildpackDescriptor) EnsureStackSupport(stackID string, providedMixins []string, validateRunStageMixins bool) error { + if len(b.Stacks) == 0 { + return nil // Order buildpack, no validation required + } + + bpMixins, err := b.findMixinsForStack(stackID) + if err != nil { + return err + } + + if !validateRunStageMixins { + var filtered []string + for _, m := range bpMixins { + if !strings.HasPrefix(m, "run:") { + filtered = append(filtered, m) + } + } + bpMixins = filtered + } + + _, missing, _ := stringset.Compare(providedMixins, bpMixins) + if len(missing) > 0 { + sort.Strings(missing) + return fmt.Errorf("buildpack %s requires missing mixin(s): %s", style.Symbol(b.Info.FullName()), strings.Join(missing, ", ")) + } + return nil +} + +func (b *BuildpackDescriptor) findMixinsForStack(stackID string) ([]string, error) { + for _, s := range b.Stacks { + if s.ID == stackID { + return s.Mixins, nil + } + } + return nil, fmt.Errorf("buildpack %s does not support stack %s", style.Symbol(b.Info.FullName()), style.Symbol(stackID)) +} diff --git a/vendor/github.com/buildpacks/pack/internal/dist/dist.go b/vendor/github.com/buildpacks/pack/internal/dist/dist.go new file mode 100644 index 00000000000..3b8b9f4dd6d --- /dev/null +++ b/vendor/github.com/buildpacks/pack/internal/dist/dist.go @@ -0,0 +1,51 @@ +package dist + +import "github.com/buildpacks/pack/internal/api" + +const BuildpackLayersLabel = "io.buildpacks.buildpack.layers" + +type BuildpackURI struct { + URI string `toml:"uri"` +} + +type ImageRef struct { + ImageName string `toml:"image"` +} + +type ImageOrURI struct { + BuildpackURI + ImageRef +} + +type Order []OrderEntry + +type OrderEntry struct { + Group []BuildpackRef `toml:"group" json:"group"` +} + +type BuildpackRef struct { + BuildpackInfo + Optional bool `toml:"optional,omitempty" json:"optional,omitempty"` +} + +type BuildpackLayers map[string]map[string]BuildpackLayerInfo + +type BuildpackLayerInfo struct { + API *api.Version `json:"api"` + Stacks []Stack `json:"stacks"` + Order Order `json:"order,omitempty"` + LayerDiffID string `json:"layerDiffID"` +} + +func AddBuildpackToLayersMD(layerMD BuildpackLayers, descriptor BuildpackDescriptor, diffID string) { + bpInfo := descriptor.Info + if _, ok := layerMD[bpInfo.ID]; !ok { + layerMD[bpInfo.ID] = map[string]BuildpackLayerInfo{} + } + layerMD[bpInfo.ID][bpInfo.Version] = BuildpackLayerInfo{ + API: descriptor.API, + Stacks: descriptor.Stacks, + Order: descriptor.Order, + LayerDiffID: diffID, + } +} diff --git a/vendor/github.com/buildpacks/pack/internal/dist/image.go b/vendor/github.com/buildpacks/pack/internal/dist/image.go new file mode 100644 index 00000000000..6bbc2d6c57f --- /dev/null +++ b/vendor/github.com/buildpacks/pack/internal/dist/image.go @@ -0,0 +1,43 @@ +package dist + +import ( + "encoding/json" + + "github.com/pkg/errors" + + "github.com/buildpacks/pack/internal/style" +) + +type Labeled interface { + Name() string + Label(name string) (value string, err error) +} + +type Labelable interface { + SetLabel(name string, value string) error +} + +func SetLabel(labelable Labelable, label string, data interface{}) error { + dataBytes, err := json.Marshal(data) + if err != nil { + return errors.Wrapf(err, "marshalling data to JSON for label %s", style.Symbol(label)) + } + if err := labelable.SetLabel(label, string(dataBytes)); err != nil { + return errors.Wrapf(err, "setting label %s", style.Symbol(label)) + } + return nil +} + +func GetLabel(labeled Labeled, label string, obj interface{}) (ok bool, err error) { + labelData, err := labeled.Label(label) + if err != nil { + return false, errors.Wrapf(err, "retrieving label %s", style.Symbol(label)) + } + if labelData != "" { + if err := json.Unmarshal([]byte(labelData), obj); err != nil { + return false, errors.Wrapf(err, "unmarshalling label %s", style.Symbol(label)) + } + return true, nil + } + return false, nil +} diff --git a/vendor/github.com/buildpacks/pack/internal/dist/layers.go b/vendor/github.com/buildpacks/pack/internal/dist/layers.go new file mode 100644 index 00000000000..514b748d064 --- /dev/null +++ b/vendor/github.com/buildpacks/pack/internal/dist/layers.go @@ -0,0 +1,54 @@ +package dist + +import ( + "fmt" + "io" + "os" + "path/filepath" + + v1 "github.com/google/go-containerregistry/pkg/v1" + "github.com/google/go-containerregistry/pkg/v1/tarball" + "github.com/pkg/errors" +) + +func BuildpackToLayerTar(dest string, bp Buildpack) (string, error) { + bpd := bp.Descriptor() + bpReader, err := bp.Open() + if err != nil { + return "", errors.Wrap(err, "opening buildpack blob") + } + defer bpReader.Close() + + layerTar := filepath.Join(dest, fmt.Sprintf("%s.%s.tar", bpd.EscapedID(), bpd.Info.Version)) + fh, err := os.Create(layerTar) + if err != nil { + return "", errors.Wrap(err, "create file for tar") + } + defer fh.Close() + + if _, err := io.Copy(fh, bpReader); err != nil { + return "", errors.Wrap(err, "writing buildpack blob to tar") + } + + return layerTar, nil +} + +func LayerDiffID(layerTarPath string) (v1.Hash, error) { + fh, err := os.Open(layerTarPath) + if err != nil { + return v1.Hash{}, errors.Wrap(err, "opening tar file") + } + defer fh.Close() + + layer, err := tarball.LayerFromFile(layerTarPath) + if err != nil { + return v1.Hash{}, errors.Wrap(err, "reading layer tar") + } + + hash, err := layer.DiffID() + if err != nil { + return v1.Hash{}, errors.Wrap(err, "generating diff id") + } + + return hash, nil +} diff --git a/vendor/github.com/buildpacks/pack/internal/image/factory.go b/vendor/github.com/buildpacks/pack/internal/image/factory.go new file mode 100644 index 00000000000..dbf3b377c54 --- /dev/null +++ b/vendor/github.com/buildpacks/pack/internal/image/factory.go @@ -0,0 +1,29 @@ +package image + +import ( + "github.com/buildpacks/imgutil" + "github.com/buildpacks/imgutil/local" + "github.com/buildpacks/imgutil/remote" + "github.com/docker/docker/client" + "github.com/google/go-containerregistry/pkg/authn" +) + +type DefaultImageFactory struct { + dockerClient *client.Client + keychain authn.Keychain +} + +func NewFactory(dockerClient *client.Client, keychain authn.Keychain) *DefaultImageFactory { + return &DefaultImageFactory{ + dockerClient: dockerClient, + keychain: keychain, + } +} + +func (f *DefaultImageFactory) NewImage(repoName string, daemon bool) (imgutil.Image, error) { + if daemon { + return local.NewImage(repoName, f.dockerClient) + } + + return remote.NewImage(repoName, f.keychain) +} diff --git a/vendor/github.com/buildpacks/pack/internal/image/fetcher.go b/vendor/github.com/buildpacks/pack/internal/image/fetcher.go new file mode 100644 index 00000000000..3d62b3f0c4a --- /dev/null +++ b/vendor/github.com/buildpacks/pack/internal/image/fetcher.go @@ -0,0 +1,149 @@ +package image + +import ( + "context" + "encoding/base64" + "encoding/json" + "io" + "strings" + + "github.com/buildpacks/imgutil" + "github.com/buildpacks/imgutil/local" + "github.com/buildpacks/imgutil/remote" + "github.com/buildpacks/lifecycle/auth" + "github.com/docker/docker/api/types" + "github.com/docker/docker/client" + "github.com/docker/docker/pkg/jsonmessage" + "github.com/google/go-containerregistry/pkg/authn" + "github.com/pkg/errors" + + "github.com/buildpacks/pack/internal/style" + "github.com/buildpacks/pack/logging" +) + +type Fetcher struct { + docker *client.Client + logger logging.Logger +} + +func NewFetcher(logger logging.Logger, docker *client.Client) *Fetcher { + return &Fetcher{ + logger: logger, + docker: docker, + } +} + +var ErrNotFound = errors.New("not found") + +func (f *Fetcher) Fetch(ctx context.Context, name string, daemon, pull bool) (image imgutil.Image, err error) { + if daemon && !pull { + return f.fetchDaemonImage(name) + } + + image, err = remote.NewImage(name, authn.DefaultKeychain, remote.FromBaseImage(name)) + if err != nil { + return nil, err + } + + remoteFound := image.Found() + + if daemon { + if remoteFound { + f.logger.Debugf("Pulling image %s", style.Symbol(name)) + if err := f.pullImage(ctx, name); err != nil { + return nil, err + } + } + return f.fetchDaemonImage(name) + } + + if !remoteFound { + return nil, errors.Wrapf(ErrNotFound, "image %s does not exist in registry", style.Symbol(name)) + } + + return image, nil +} + +func (f *Fetcher) fetchDaemonImage(name string) (imgutil.Image, error) { + image, err := local.NewImage(name, f.docker, local.FromBaseImage(name)) + if err != nil { + return nil, err + } + + if !image.Found() { + return nil, errors.Wrapf(ErrNotFound, "image %s does not exist on the daemon", style.Symbol(name)) + } + return image, nil +} + +func (f *Fetcher) pullImage(ctx context.Context, imageID string) error { + regAuth, err := registryAuth(imageID) + if err != nil { + return err + } + rc, err := f.docker.ImagePull(ctx, imageID, types.ImagePullOptions{ + RegistryAuth: regAuth, + }) + if err != nil { + return err + } + writer := logging.GetInfoWriter(f.logger) + type descriptor interface { + Fd() uintptr + } + var termFd uintptr + isTerm := false + if f, ok := writer.(descriptor); ok { + isTerm = true + termFd = f.Fd() + } + err = jsonmessage.DisplayJSONMessagesStream(rc, &colorizedWriter{writer}, termFd, isTerm, nil) + if err != nil { + return err + } + + return rc.Close() +} + +func registryAuth(ref string) (string, error) { + _, a, err := auth.ReferenceForRepoName(authn.DefaultKeychain, ref) + if err != nil { + return "", errors.Wrapf(err, "resolve auth for ref %s", ref) + } + authConfig, err := a.Authorization() + if err != nil { + return "", err + } + + dataJSON, err := json.Marshal(authConfig) + if err != nil { + return "", err + } + + return base64.StdEncoding.EncodeToString(dataJSON), nil +} + +type colorizedWriter struct { + writer io.Writer +} + +type colorFunc = func(string, ...interface{}) string + +func (w *colorizedWriter) Write(p []byte) (n int, err error) { + msg := string(p) + colorizers := map[string]colorFunc{ + "Waiting": style.Waiting, + "Pulling fs layer": style.Waiting, + "Downloading": style.Working, + "Download complete": style.Working, + "Extracting": style.Working, + "Pull complete": style.Complete, + "Already exists": style.Complete, + "=": style.ProgressBar, + ">": style.ProgressBar, + } + for pattern, colorize := range colorizers { + msg = strings.Replace(msg, pattern, colorize(pattern), -1) + } + return w.writer.Write([]byte(msg)) +} diff --git a/vendor/github.com/buildpacks/pack/internal/paths/paths.go b/vendor/github.com/buildpacks/pack/internal/paths/paths.go new file mode 100644 index 00000000000..b9be2634be9 --- /dev/null +++ b/vendor/github.com/buildpacks/pack/internal/paths/paths.go @@ -0,0 +1,88 @@ +package paths + +import ( + "net/url" + "os" + "path/filepath" + "regexp" + "runtime" + "strings" +) + +var schemeRegexp = regexp.MustCompile(`^.+://.*`) + +func IsURI(ref string) bool { + return schemeRegexp.MatchString(ref) +} + +func IsDir(path string) (bool, error) { + fileInfo, err := os.Stat(path) + if err != nil { + return false, err + } + + return fileInfo.IsDir(), nil +} + +func FilePathToURI(path string) (string, error) { + var err error + if !filepath.IsAbs(path) { + path, err = filepath.Abs(path) + if err != nil { + return "", err + } + } + + if runtime.GOOS == "windows" { + if strings.HasPrefix(path, `\\`) { + return "file://" + filepath.ToSlash(strings.TrimPrefix(path, `\\`)), nil + } + return "file:///" + filepath.ToSlash(path), nil + } + return "file://" + path, nil +} + +// examples: +// +// - unix file: file://laptop/some%20dir/file.tgz +// +// - windows drive: file:///C:/Documents%20and%20Settings/file.tgz +// +// - windows share: file://laptop/My%20Documents/file.tgz +// +func URIToFilePath(uri string) (string, error) { + var ( + osPath string + err error + ) + + osPath = filepath.FromSlash(strings.TrimPrefix(uri, "file://")) + + if osPath, err = url.PathUnescape(osPath); err != nil { + return "", nil + } + + if runtime.GOOS == "windows" { + if strings.HasPrefix(osPath, `\`) { + return strings.TrimPrefix(osPath, `\`), nil + } + return `\\` + osPath, nil + } + return osPath, nil +} + +func ToAbsolute(uri, relativeTo string) (string, error) { + parsed, err := url.Parse(uri) + if err != nil { + return "", err + } + + if parsed.Scheme == "" { + if !filepath.IsAbs(parsed.Path) { + absPath := filepath.Join(relativeTo, parsed.Path) + return FilePathToURI(absPath) + } + } + + return uri, nil +} diff --git a/vendor/github.com/buildpacks/pack/internal/stack/merge.go b/vendor/github.com/buildpacks/pack/internal/stack/merge.go new file mode 100644 index 00000000000..7eb9b4321fd --- /dev/null +++ b/vendor/github.com/buildpacks/pack/internal/stack/merge.go @@ -0,0 +1,62 @@ +package stack + +import ( + "sort" + + "github.com/buildpacks/pack/internal/dist" + "github.com/buildpacks/pack/internal/stringset" +) + +// MergeCompatible determines the allowable set of stacks that a combination of buildpacks may run on, given each +// buildpack's set of stacks. Compatibility between the two sets of buildpack stacks is defined by the following rules: +// +// 1. The stack must be supported by both buildpacks. That is, any resulting stack ID must appear in both input sets. +// 2. For each supported stack ID, all required mixins for all buildpacks must be provided by the result. That is, +// mixins for the stack ID in both input sets are unioned. +// +// --- +// +// Examples: +// +// stacksA = [{ID: "stack1", mixins: ["build:mixinA", "mixinB", "run:mixinC"]}}] +// stacksB = [{ID: "stack1", mixins: ["build:mixinA", "run:mixinC"]}}] +// result = [{ID: "stack1", mixins: ["build:mixinA", "mixinB", "run:mixinC"]}}] +// +// stacksA = [{ID: "stack1", mixins: ["build:mixinA"]}}, {ID: "stack2", mixins: ["mixinA"]}}] +// stacksB = [{ID: "stack1", mixins: ["run:mixinC"]}}, {ID: "stack2", mixins: ["mixinA"]}}] +// result = [{ID: "stack1", mixins: ["build:mixinA", "run:mixinC"]}}, {ID: "stack2", mixins: ["mixinA"]}}] +// +// stacksA = [{ID: "stack1", mixins: ["build:mixinA"]}}, {ID: "stack2", mixins: ["mixinA"]}}] +// stacksB = [{ID: "stack2", mixins: ["mixinA", "run:mixinB"]}}] +// result = [{ID: "stack2", mixins: ["mixinA", "run:mixinB"]}}] +// +// stacksA = [{ID: "stack1", mixins: ["build:mixinA"]}}] +// stacksB = [{ID: "stack2", mixins: ["mixinA", "run:mixinB"]}}] +// result = [] +// +func MergeCompatible(stacksA []dist.Stack, stacksB []dist.Stack) []dist.Stack { + set := map[string][]string{} + + for _, s := range stacksA { + set[s.ID] = s.Mixins + } + + var results []dist.Stack + for _, s := range stacksB { + if stackMixins, ok := set[s.ID]; ok { + mixinsSet := stringset.FromSlice(append(stackMixins, s.Mixins...)) + var mixins []string + for s := range mixinsSet { + mixins = append(mixins, s) + } + sort.Strings(mixins) + + results = append(results, dist.Stack{ + ID: s.ID, + Mixins: mixins, + }) + } + } + + return results +} diff --git a/vendor/github.com/buildpacks/pack/internal/stack/mixins.go b/vendor/github.com/buildpacks/pack/internal/stack/mixins.go new file mode 100644 index 00000000000..b3e77c2827a --- /dev/null +++ b/vendor/github.com/buildpacks/pack/internal/stack/mixins.go @@ -0,0 +1,55 @@ +package stack + +import ( + "fmt" + "sort" + "strings" + + "github.com/buildpacks/pack/internal/stringset" + "github.com/buildpacks/pack/internal/style" +) + +const MixinsLabel = "io.buildpacks.stack.mixins" + +func ValidateMixins(buildImageName string, buildImageMixins []string, runImageName string, runImageMixins []string) error { + if invalid := FindStageMixins(buildImageMixins, "run"); len(invalid) > 0 { + sort.Strings(invalid) + return fmt.Errorf("%s contains run-only mixin(s): %s", style.Symbol(buildImageName), strings.Join(invalid, ", ")) + } + + if invalid := FindStageMixins(runImageMixins, "build"); len(invalid) > 0 { + sort.Strings(invalid) + return fmt.Errorf("%s contains build-only mixin(s): %s", style.Symbol(runImageName), strings.Join(invalid, ", ")) + } + + buildImageMixins = removeStageMixins(buildImageMixins, "build") + runImageMixins = removeStageMixins(runImageMixins, "run") + + _, missing, _ := stringset.Compare(runImageMixins, buildImageMixins) + + if len(missing) > 0 { + sort.Strings(missing) + return fmt.Errorf("%s missing required mixin(s): %s", style.Symbol(runImageName), strings.Join(missing, ", ")) + } + return nil +} + +func FindStageMixins(mixins []string, stage string) []string { + var found []string + for _, m := range mixins { + if strings.HasPrefix(m, stage+":") { + found = append(found, m) + } + } + return found +} + +func removeStageMixins(mixins []string, stage string) []string { + var filtered []string + for _, m := range mixins { + if !strings.HasPrefix(m, stage+":") { + filtered = append(filtered, m) + } + } + return filtered +} diff --git a/vendor/github.com/buildpacks/pack/internal/stringset/stringset.go b/vendor/github.com/buildpacks/pack/internal/stringset/stringset.go new file mode 100644 index 00000000000..feb7842e7ae --- /dev/null +++ b/vendor/github.com/buildpacks/pack/internal/stringset/stringset.go @@ -0,0 +1,37 @@ +package stringset + +// FromSlice converts the given slice to a set in the form of unique keys in a map. +// The value associated with each key should not be relied upon. A value is present +// in the set if its key is present in the map, regardless of the key's value. +func FromSlice(strings []string) map[string]interface{} { + set := map[string]interface{}{} + for _, s := range strings { + set[s] = nil + } + return set +} + +// Compare performs a set comparison between two slices. `extra` represents elements present in +// `strings1` but not `strings2`. `missing` represents elements present in `strings2` that are +// missing from `strings1`. `common` represents elements present in both slices. Since the input +// slices are treated as sets, duplicates will be removed in any outputs. +func Compare(strings1, strings2 []string) (extra []string, missing []string, common []string) { + set1 := FromSlice(strings1) + set2 := FromSlice(strings2) + + for s := range set1 { + if _, ok := set2[s]; !ok { + extra = append(extra, s) + continue + } + common = append(common, s) + } + + for s := range set2 { + if _, ok := set1[s]; !ok { + missing = append(missing, s) + } + } + + return extra, missing, common +} diff --git a/vendor/github.com/buildpacks/pack/internal/style/style.go b/vendor/github.com/buildpacks/pack/internal/style/style.go new file mode 100644 index 00000000000..62d75fe7ab7 --- /dev/null +++ b/vendor/github.com/buildpacks/pack/internal/style/style.go @@ -0,0 +1,39 @@ +package style + +import ( + "fmt" + + "github.com/heroku/color" +) + +var Noop = func(format string, a ...interface{}) string { + return color.WhiteString("") + fmt.Sprintf(format, a...) +} + +var Symbol = func(format string, a ...interface{}) string { + if color.Enabled() { + return Key(format, a...) + } + return "'" + fmt.Sprintf(format, a...) + "'" +} + +var Key = color.HiBlueString + +var Tip = color.New(color.FgGreen, color.Bold).SprintfFunc() + +var Warn = color.New(color.FgYellow, color.Bold).SprintfFunc() + +var Error = color.New(color.FgRed, color.Bold).SprintfFunc() + +var Step = func(format string, a ...interface{}) string { + return color.CyanString("===> "+format, a...) +} + +var Prefix = color.CyanString + +var TimestampColorCode = color.FgHiBlack + +var Waiting = color.HiBlackString +var Working = color.HiBlueString +var Complete = color.GreenString +var ProgressBar = color.HiBlueString diff --git a/vendor/github.com/buildpacks/pack/logging/default_logger.go b/vendor/github.com/buildpacks/pack/logging/default_logger.go new file mode 100644 index 00000000000..02684eebaac --- /dev/null +++ b/vendor/github.com/buildpacks/pack/logging/default_logger.go @@ -0,0 +1,66 @@ +package logging + +import ( + "fmt" + "io" + "log" +) + +// New creates a default logger for the pack library. Note that the pack CLI has it's own logger. +func New(w io.Writer) Logger { + return &defaultLogger{ + out: log.New(w, "", log.LstdFlags|log.Lmicroseconds), + } +} + +type defaultLogger struct { + out *log.Logger +} + +const ( + debugPrefix = "DEBUG:" + infoPrefix = "INFO:" + warnPrefix = "WARN:" + errorPrefix = "ERROR:" + prefixFmt = "%-7s %s" +) + +func (l *defaultLogger) Debug(msg string) { + l.out.Printf(prefixFmt, debugPrefix, msg) +} + +func (l *defaultLogger) Debugf(format string, v ...interface{}) { + l.out.Printf(prefixFmt, debugPrefix, fmt.Sprintf(format, v...)) +} + +func (l *defaultLogger) Info(msg string) { + l.out.Printf(prefixFmt, infoPrefix, msg) +} + +func (l *defaultLogger) Infof(format string, v ...interface{}) { + l.out.Printf(prefixFmt, infoPrefix, fmt.Sprintf(format, v...)) +} + +func (l *defaultLogger) Warn(msg string) { + l.out.Printf(prefixFmt, warnPrefix, msg) +} + +func (l *defaultLogger) Warnf(format string, v ...interface{}) { + l.out.Printf(prefixFmt, warnPrefix, fmt.Sprintf(format, v...)) +} + +func (l *defaultLogger) Error(msg string) { + l.out.Printf(prefixFmt, errorPrefix, msg) +} + +func (l *defaultLogger) Errorf(format string, v ...interface{}) { + l.out.Printf(prefixFmt, errorPrefix, fmt.Sprintf(format, v...)) +} + +func (l *defaultLogger) Writer() io.Writer { + return l.out.Writer() +} + +func (l *defaultLogger) IsVerbose() bool { + return false +} diff --git a/vendor/github.com/buildpacks/pack/logging/logger.go b/vendor/github.com/buildpacks/pack/logging/logger.go new file mode 100644 index 00000000000..94212f393f9 --- /dev/null +++ b/vendor/github.com/buildpacks/pack/logging/logger.go @@ -0,0 +1,82 @@ +// Package logging defines the minimal interface that loggers must support to be used by pack. +package logging + +import ( + "fmt" + "io" + + "github.com/buildpacks/pack/internal/style" +) + +// Logger defines behavior required by a logging package used by pack libraries +type Logger interface { + Debug(msg string) + Debugf(fmt string, v ...interface{}) + + Info(msg string) + Infof(fmt string, v ...interface{}) + + Warn(msg string) + Warnf(fmt string, v ...interface{}) + + Error(msg string) + Errorf(fmt string, v ...interface{}) + + Writer() io.Writer + + IsVerbose() bool +} + +// WithInfoErrorWriter is an optional interface for loggers that want to support a separate writer for errors and standard logging. +// the DebugInfoWriter should write to stderr if quiet is false. +type WithInfoErrorWriter interface { + InfoErrorWriter() io.Writer +} + +// WithInfoWriter is an optional interface what will return a writer that will write raw output if quiet is false. +type WithInfoWriter interface { + InfoWriter() io.Writer +} + +// GetInfoErrorWriter will return an ErrorWriter, typically stderr if one exists, otherwise the standard logger writer +// will be returned. +func GetInfoErrorWriter(l Logger) io.Writer { + if er, ok := l.(WithInfoErrorWriter); ok { + return er.InfoErrorWriter() + } + return l.Writer() +} + +// GetInfoWriter returns a writer +// See WithInfoWriter +func GetInfoWriter(l Logger) io.Writer { + if ew, ok := l.(WithInfoWriter); ok { + return ew.InfoWriter() + } + return l.Writer() +} + +// PrefixWriter will prefix writes +type PrefixWriter struct { + out io.Writer + prefix string +} + +// NewPrefixWriter writes by w will be prefixed +func NewPrefixWriter(w io.Writer, prefix string) *PrefixWriter { + return &PrefixWriter{ + out: w, + prefix: fmt.Sprintf("[%s] ", style.Prefix(prefix)), + } +} + +// Writes bytes to the embedded log function +func (w *PrefixWriter) Write(buf []byte) (int, error) { + _, _ = fmt.Fprint(w.out, w.prefix+string(buf)) + return len(buf), nil +} + +// Tip logs a tip. +func Tip(l Logger, format string, v ...interface{}) { + l.Infof(style.Tip("Tip: ")+format, v...) +} diff --git a/vendor/github.com/buildpacks/pack/pack.go b/vendor/github.com/buildpacks/pack/pack.go new file mode 100644 index 00000000000..9b34f94edf7 --- /dev/null +++ b/vendor/github.com/buildpacks/pack/pack.go @@ -0,0 +1,74 @@ +package pack + +import ( + "context" + "io" + + "github.com/pkg/errors" + + "github.com/buildpacks/pack/internal/dist" + "github.com/buildpacks/pack/internal/style" +) + +func extractPackagedBuildpacks(ctx context.Context, pkgImageRef string, fetcher ImageFetcher, publish, noPull bool) ([]dist.Buildpack, error) { + pkgImage, err := fetcher.Fetch(ctx, pkgImageRef, !publish, !noPull) + if err != nil { + return nil, errors.Wrapf(err, "fetching image %s", style.Symbol(pkgImageRef)) + } + + bpLayers := dist.BuildpackLayers{} + ok, err := dist.GetLabel(pkgImage, dist.BuildpackLayersLabel, &bpLayers) + if err != nil { + return nil, err + } + + if !ok { + return nil, errors.Errorf( + "label %s not present on package %s", + style.Symbol(dist.BuildpackLayersLabel), + style.Symbol(pkgImageRef), + ) + } + + var bps []dist.Buildpack + for bpID, v := range bpLayers { + for bpVersion, bpInfo := range v { + desc := dist.BuildpackDescriptor{ + API: bpInfo.API, + Info: dist.BuildpackInfo{ + ID: bpID, + Version: bpVersion, + }, + Stacks: bpInfo.Stacks, + Order: bpInfo.Order, + } + + diffID := bpInfo.LayerDiffID // Allow use in closure + b := &openerBlob{ + opener: func() (io.ReadCloser, error) { + rc, err := pkgImage.GetLayer(diffID) + if err != nil { + return nil, errors.Wrapf(err, + "extracting buildpack %s layer (diffID %s) from package %s", + style.Symbol(desc.Info.FullName()), + style.Symbol(diffID), + style.Symbol(pkgImage.Name()), + ) + } + return rc, nil + }, + } + + bps = append(bps, dist.BuildpackFromTarBlob(desc, b)) + } + } + return bps, nil +} + +type openerBlob struct { + opener func() (io.ReadCloser, error) +} + +func (b *openerBlob) Open() (io.ReadCloser, error) { + return b.opener() +} diff --git a/vendor/github.com/buildpacks/pack/rebase.go b/vendor/github.com/buildpacks/pack/rebase.go new file mode 100644 index 00000000000..46dd15828f6 --- /dev/null +++ b/vendor/github.com/buildpacks/pack/rebase.go @@ -0,0 +1,74 @@ +package pack + +import ( + "context" + + "github.com/buildpacks/lifecycle" + "github.com/pkg/errors" + + "github.com/buildpacks/pack/internal/builder" + "github.com/buildpacks/pack/internal/dist" + "github.com/buildpacks/pack/internal/style" +) + +type RebaseOptions struct { + RepoName string + Publish bool + SkipPull bool + RunImage string + AdditionalMirrors map[string][]string +} + +func (c *Client) Rebase(ctx context.Context, opts RebaseOptions) error { + imageRef, err := c.parseTagReference(opts.RepoName) + if err != nil { + return errors.Wrapf(err, "invalid image name '%s'", opts.RepoName) + } + + appImage, err := c.imageFetcher.Fetch(ctx, opts.RepoName, !opts.Publish, !opts.SkipPull) + if err != nil { + return err + } + + var md lifecycle.LayersMetadataCompat + if ok, err := dist.GetLabel(appImage, lifecycle.LayerMetadataLabel, &md); err != nil { + return err + } else if !ok { + return errors.Errorf("could not find label %s on image", style.Symbol(lifecycle.LayerMetadataLabel)) + } + + runImageName := c.resolveRunImage( + opts.RunImage, + imageRef.Context().RegistryStr(), + builder.StackMetadata{ + RunImage: builder.RunImageMetadata{ + Image: md.Stack.RunImage.Image, + Mirrors: md.Stack.RunImage.Mirrors, + }, + }, + opts.AdditionalMirrors) + + if runImageName == "" { + return errors.New("run image must be specified") + } + + baseImage, err := c.imageFetcher.Fetch(ctx, runImageName, !opts.Publish, !opts.SkipPull) + if err != nil { + return err + } + + c.logger.Infof("Rebasing %s on run image %s", style.Symbol(appImage.Name()), style.Symbol(baseImage.Name())) + rebaser := &lifecycle.Rebaser{Logger: c.logger} + err = rebaser.Rebase(appImage, baseImage, nil) + if err != nil { + return err + } + + appImageIdentifier, err := appImage.Identifier() + if err != nil { + return err + } + + c.logger.Infof("Rebased Image: %s", style.Symbol(appImageIdentifier.String())) + return nil +} diff --git a/vendor/github.com/buildpacks/pack/run.go b/vendor/github.com/buildpacks/pack/run.go new file mode 100644 index 00000000000..d35ed8674d6 --- /dev/null +++ b/vendor/github.com/buildpacks/pack/run.go @@ -0,0 +1,48 @@ +package pack + +import ( + "context" + "crypto/sha256" + "fmt" + + "github.com/pkg/errors" + + "github.com/buildpacks/pack/internal/app" + "github.com/buildpacks/pack/internal/style" +) + +type RunOptions struct { + AppPath string // defaults to current working directory + Builder string // defaults to default builder on the client config + RunImage string // defaults to the best mirror from the builder image + Env map[string]string + NoPull bool + ClearCache bool + Buildpacks []string + Ports []string +} + +func (c *Client) Run(ctx context.Context, opts RunOptions) error { + appPath, err := c.processAppPath(opts.AppPath) + if err != nil { + return errors.Wrapf(err, "invalid app dir '%s'", opts.AppPath) + } + sum := sha256.Sum256([]byte(appPath)) + imageName := fmt.Sprintf("pack.local/run/%x", sum[:8]) + err = c.Build(ctx, BuildOptions{ + AppPath: appPath, + Builder: opts.Builder, + RunImage: opts.RunImage, + Env: opts.Env, + Image: imageName, + NoPull: opts.NoPull, + ClearCache: opts.ClearCache, + Buildpacks: opts.Buildpacks, + }) + if err != nil { + return errors.Wrap(err, "build failed") + } + appImage := &app.Image{RepoName: imageName, Logger: c.logger} + c.logger.Debug(style.Step("RUNNING")) + return appImage.Run(ctx, c.docker, opts.Ports) +} diff --git a/vendor/github.com/heroku/color/.gitignore b/vendor/github.com/heroku/color/.gitignore new file mode 100644 index 00000000000..ed3ac085ae5 --- /dev/null +++ b/vendor/github.com/heroku/color/.gitignore @@ -0,0 +1,16 @@ +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, build with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out +.idea/ +c.out +*.test +*.prof \ No newline at end of file diff --git a/vendor/github.com/heroku/color/.golangcli.yml b/vendor/github.com/heroku/color/.golangcli.yml new file mode 100644 index 00000000000..b9bd6501351 --- /dev/null +++ b/vendor/github.com/heroku/color/.golangcli.yml @@ -0,0 +1,26 @@ +run: + concurrency: 4 + +linter-settings: + goimports: + local-prefixes: github.com/heroku/code + lll: + line-length: 110 + + +linters: + enable-all: true + disable: + - golint + - maligned + - gochecknoglobals + +issues: + exclude-rules: + - path: _test\.go + linters: + - scopelint + - funlen + - path: color\.go + linters: + - gocritic diff --git a/vendor/github.com/heroku/color/LICENSE b/vendor/github.com/heroku/color/LICENSE new file mode 100644 index 00000000000..d23abe74002 --- /dev/null +++ b/vendor/github.com/heroku/color/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 Heroku + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/heroku/color/Makefile b/vendor/github.com/heroku/color/Makefile new file mode 100644 index 00000000000..17c681e420e --- /dev/null +++ b/vendor/github.com/heroku/color/Makefile @@ -0,0 +1,21 @@ +PROJECT_ROOT := $(shell pwd) + +.PHONY: test bench fmt lint + +test: + @go test -race -coverprofile c.out -cpuprofile=cpu2.prof github.com/heroku/color + +bench: + @go test -bench=. -count=5 -cpu=1,2,4,8 -cpuprofile=cpu.prof github.com/heroku/color + +cover: test + @go tool cover -html=c.out + +lint: $(GOPATH)/bin/golangci-lint + @echo "--> Running linter with default config" + @golangci-lint run --deadline 3m0s -c $(PROJECT_ROOT)/.golangcli.yml + +$(GOPATH)/bin/golangci-lint: + @echo "--> Installing linter" + curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(shell go env GOPATH)/bin v1.18.0 + diff --git a/vendor/github.com/heroku/color/README.md b/vendor/github.com/heroku/color/README.md new file mode 100644 index 00000000000..52c1644bc49 --- /dev/null +++ b/vendor/github.com/heroku/color/README.md @@ -0,0 +1,109 @@ +# Color [![GoDoc](https://godoc.org/github.com/heroku/color?status.svg)](https://godoc.org/github.com/heroku/color) [![CircleCI](https://circleci.com/gh/heroku/color.svg?style=svg)](https://circleci.com/gh/heroku/color) + +Color is based on the [github.com/fatih/color](https://github.com/fatih/color) package. Unfortunately the original +color package is archived and is no longer supported. Like the original, this package lets you use colorized outputs in +terms of [ANSI Escape Codes](http://en.wikipedia.org/wiki/ANSI_escape_code#Colors) in Golang but offers a number of +improvements from the original. Posix and Windows platforms are supported. + +Color seeks to remain *mostly* backward compatible with fatih/color but has a number of changes to support concurrency, +improved performance and a more idiomatic style. + +## Changes And Improvements + +The methods of the new `Color` struct do not mutate the sender. This +results in better concurrency support and improved performance. + +You don't need to remember to wrap io.Writer arguments in `colorable.NewColorable` in order to support Windows functionality. + +Package public global variables are removed. `color.NoColor` was removed and replaced with the `Disable` function. + Colored output can be toggled using the `Disable`. `color.Output` and `color.Error`replaced by `Stdout()` and `Stderr()` +. + +Instances of `Console` can be passed to methods in third party packages that take `io.Writer` as an argument. If the + third party package emits ANSI color information the passed in writer will be interpreted correctly on Windows. In + addition, color information can be stripped for a console by calling `Console.DisableColors(true)`. + +Performance is improved significantly, as much as 400%. Note that some functions that you'd expect to take an +array of interface{} take an array of strings instead because underlying calls to fmt.SprintXX functions are slow. + +`fatih/color` has race conditions. This package was developed with `test.Parallel` and `-race` enabled for tests. Thus +far no race conditions are known and so this package is suitable for use in a multi goroutine environment. + +## Examples + +### Standard colors + +```go +// Print with default helper functions +color.Cyan("Prints text in cyan.") + +// A newline will be appended automatically +color.Blue("Prints %s in blue.", "text") +``` + +### Mix and reuse colors + +```go +// Create a new color object +color.Stdout().Println(color.New(color.FgCyan, color.Underline), "Prints cyan text with an underline.") +``` + +### Use your own output (io.Writer) + +```go +// Use your own io.Writer output +wtr := color.NewConsole(os.Stderr) +wtr.Println(color.New(color.FgBlue), "Hello! I'm blue.") +``` + +### Custom print functions (PrintFunc) + +```go +// Create a custom print function for convenience +red := color.StdErr().PrintfFunc(color.New(color.FgRed)) +red("Warning") +red("Error: %s", err) + +// Mix up multiple attributes +notice := color.Stdout().PrintlnFunc(color.New(color.Bold, color.FgGreen)) +notice("Don't forget this...") +``` +### Insert into noncolor strings (SprintFunc) + +```go +// Create SprintXxx functions to mix strings with other non-colorized strings: +yellow := color.New(color.FgYellow).SprintFunc() +red := color.New(color.FgRed).SprintFunc() +fmt.Printf("This is a %s and this is %s.\n", yellow("warning"), red("error")) + +info := color.New(color.FgWhite, color.BgGreen).SprintFunc() +fmt.Printf("This %s rocks!\n", info("package")) + +// Use helper functions +fmt.Println("This", color.RedString("warning"), "should be not neglected.") +fmt.Printf("%v %v\n", color.GreenString("Info:"), "an important message.") +``` +### Disable/Enable color + +There might be a case where you want to explicitly disable/enable color output. + +`Color` has support to disable/enable colors on a per `Console` basis. +For example suppose you have a CLI app and a `--no-color` bool flag. You +can easily disable the color output with: + +```go + +var flagNoColor = flag.Bool("no-color", false, "Disable color output") +color.Stdout().DisableColors(*flagNoColor) + +``` +## Credits + + * [Fatih Arslan](https://github.com/fatih) + * Windows support via @mattn: [colorable](https://github.com/mattn/go-colorable) + +## License + +The MIT License (MIT) - see [`LICENSE.md`](https://github.com/heroku/color/blob/master/LICENSE) for more details + + diff --git a/vendor/github.com/heroku/color/attributes.go b/vendor/github.com/heroku/color/attributes.go new file mode 100644 index 00000000000..552b88b6b19 --- /dev/null +++ b/vendor/github.com/heroku/color/attributes.go @@ -0,0 +1,175 @@ +package color + +import ( + "fmt" +) + +// Attribute defines a single SGR Code. +type Attribute uint64 + +// String returns color code as a string. +func (a Attribute) String() string { + return attributeToSGRCode[a] +} + +// Name returns a human readable name for an Attribute. +func (a Attribute) Name() string { + m := map[Attribute]string{ + Reset: "Reset", + Bold: "Bold", + Faint: "Faint", + Italic: "Italic", + Underline: "Underline", + BlinkSlow: "BlinkSlow", + BlinkRapid: "BlinkRapid", + ReverseVideo: "ReverseVideo", + Concealed: "Concealed", + CrossedOut: "CrossedOut", + FgBlack: "FgBlack", + FgRed: "FgRed", + FgGreen: "FgGreen", + FgYellow: "FgYellow", + FgBlue: "FgBlue", + FgMagenta: "FgMagenta", + FgCyan: "FgCyan", + FgWhite: "FgWhite", + FgHiBlack: "FgHiBlack", + FgHiRed: "FgHiRed", + FgHiGreen: "FgHiGreen", + FgHiYellow: "FgHiYellow", + FgHiBlue: "FgHiBlue", + FgHiMagenta: "FgHiMagenta", + FgHiCyan: "FgHiCyan", + FgHiWhite: "FgHiWhite", + BgBlack: "BgBlack", + BgRed: "BgRed", + BgGreen: "BgGreen", + BgYellow: "BgYellow", + BgBlue: "BgBlue", + BgMagenta: "BgMagenta", + BgCyan: "BgCyan", + BgWhite: "BgWhite", + BgHiBlack: "BgHiBlack", + BgHiRed: "BgHiRed", + BgHiGreen: "BgHiGreen", + BgHiYellow: "BgHiYellow", + BgHiBlue: "BgHiBlue", + BgHiMagenta: "BgHiMagenta", + BgHiCyan: "BgHiCyan", + BgHiWhite: "BgHiWhite", + } + if s, ok := m[a]; ok { + return s + } + return fmt.Sprintf("unknown color %d", a) +} + +const ( + Reset Attribute = 1 << iota + Bold + Faint + Italic + Underline + BlinkSlow + BlinkRapid + ReverseVideo + Concealed + CrossedOut + FgBlack + FgRed + FgGreen + FgYellow + FgBlue + FgMagenta + FgCyan + FgWhite + FgHiBlack + FgHiRed + FgHiGreen + FgHiYellow + FgHiBlue + FgHiMagenta + FgHiCyan + FgHiWhite + BgBlack + BgRed + BgGreen + BgYellow + BgBlue + BgMagenta + BgCyan + BgWhite + BgHiBlack + BgHiRed + BgHiGreen + BgHiYellow + BgHiBlue + BgHiMagenta + BgHiCyan + BgHiWhite +) + +var attributeToSGRCode = map[Attribute]string{ + Reset: "0", + Bold: "1", + Faint: "2", + Italic: "3", + Underline: "4", + BlinkSlow: "5", + BlinkRapid: "6", + ReverseVideo: "7", + Concealed: "8", + CrossedOut: "9", + FgBlack: "30", + FgRed: "31", + FgGreen: "32", + FgYellow: "33", + FgBlue: "34", + FgMagenta: "35", + FgCyan: "36", + FgWhite: "37", + BgBlack: "40", + BgRed: "41", + BgGreen: "42", + BgYellow: "43", + BgBlue: "44", + BgMagenta: "45", + BgCyan: "46", + BgWhite: "47", + FgHiBlack: "90", + FgHiRed: "91", + FgHiGreen: "92", + FgHiYellow: "93", + FgHiBlue: "94", + FgHiMagenta: "95", + FgHiCyan: "96", + FgHiWhite: "97", + BgHiBlack: "100", + BgHiRed: "101", + BgHiGreen: "102", + BgHiYellow: "103", + BgHiBlue: "104", + BgHiMagenta: "105", + BgHiCyan: "106", + BgHiWhite: "107", +} + +func to_codes(attrs []Attribute) []string { + codes := make([]string, len(attrs)) + for i := 0; i < len(attrs); i++ { + code, ok := attributeToSGRCode[attrs[i]] + if !ok { + return nil + } + codes[i] = code + } + return codes +} + +func to_key(attr []Attribute) Attribute { + var key Attribute + for i := 0; i < len(attr); i++ { + key |= attr[i] + } + return key +} diff --git a/vendor/github.com/heroku/color/cache.go b/vendor/github.com/heroku/color/cache.go new file mode 100644 index 00000000000..60c58f3ae9f --- /dev/null +++ b/vendor/github.com/heroku/color/cache.go @@ -0,0 +1,53 @@ +package color + +import "sync" + +var cacheSingleton *colorCache +var cacheOnce sync.Once + +func cache() *colorCache { + cacheOnce.Do(func() { + cacheSingleton = &colorCache{ + cache: make(colorMap), + } + }) + return cacheSingleton +} + +type colorMap map[Attribute]*Color + +type colorCache struct { + sync.RWMutex + cache colorMap +} + +func (cc *colorCache) value(attrs ...Attribute) *Color { + key := to_key(attrs) + if v := cc.getIfExists(key); v != nil { + return v + } + cc.Lock() + v := &Color{ + colorStart: chainSGRCodes(attrs), + } + cc.cache[key] = v + cc.Unlock() + return v +} + +func (vc *colorCache) getIfExists(key Attribute) *Color { + vc.RLock() + if v, ok := vc.cache[key]; ok { + vc.RUnlock() + return v + + } + vc.RUnlock() + return nil +} + +func (vc *colorCache) clear() { + vc.Lock() + defer vc.Unlock() + vc.cache = make(colorMap) +} diff --git a/vendor/github.com/heroku/color/color.go b/vendor/github.com/heroku/color/color.go new file mode 100644 index 00000000000..ca6d5cc2e71 --- /dev/null +++ b/vendor/github.com/heroku/color/color.go @@ -0,0 +1,271 @@ +package color + +import ( + "fmt" + "strings" +) + +const ( + escape = "\x1b[" + endCode = "m" + lineFeed = "\n" + delimiter = ";" + colorReset = "\x1b[0m" +) + +func chainSGRCodes(a []Attribute) string { + codes := to_codes(a) + if len(codes) == 0 { + return colorReset + } + if len(codes) == 1 { + return escape + codes[0] + endCode + } + var bld strings.Builder + bld.Grow((len(codes) * 2) + len(escape) + len(endCode)) + bld.WriteString(escape) + delimsAdded := 0 + for i := 0; i < len(a); i++ { + if delimsAdded > 0 { + _, _ = bld.WriteString(delimiter) + } + bld.WriteString(codes[i]) + delimsAdded++ + } + bld.WriteString(endCode) + return bld.String() +} + +// Color contains methods to create colored strings of text. +type Color struct { + colorStart string +} + +// New creates a Color. It takes a list of Attributes to define +// the appearance of output. +func New(attrs ...Attribute) *Color { + return cache().value(attrs...) +} + +// Sprint returns text decorated with the display Attributes passed to Color constructor function. +func (v Color) Sprint(a ...interface{}) string { + if Enabled() { + return v.wrap(fmt.Sprint(a...)) + } + return fmt.Sprint(a...) +} + +// Sprint formats according to the format specifier and returns text decorated with the display Attributes +// passed to Color constructor function. +func (v Color) Sprintf(format string, a ...interface{}) string { + if Enabled() { + return v.wrap(fmt.Sprintf(format, a...)) + } + return fmt.Sprintf(format, a...) +} + +// Sprint returns text decorated with the display Attributes and terminated by a line feed. +func (v Color) Sprintln(a ...interface{}) string { + var s string + if Enabled() { + s = v.wrap(fmt.Sprint(a...)) + } else { + s = fmt.Sprint(a...) + } + if !strings.HasSuffix(s, lineFeed) { + s += lineFeed + } + return s +} + +// SprintFunc returns function that wraps Sprint. +func (v Color) SprintFunc() func(a ...interface{}) string { + return func(a ...interface{}) string { + return v.Sprint(a...) + } +} + +// SprintfFunc returns function that wraps Sprintf. +func (v Color) SprintfFunc() func(format string, a ...interface{}) string { + return func(format string, a ...interface{}) string { + return v.Sprintf(format, a...) + } +} + +// SprintlnFunc returns function that wraps Sprintln. +func (v Color) SprintlnFunc() func(a ...interface{}) string { + return func(a ...interface{}) string { + return v.Sprintln(a...) + } +} + +func (v Color) wrap(s ...string) string { + var b strings.Builder + b.Grow(len(v.colorStart) + len(s) + len(colorReset)) + b.WriteString(v.colorStart) + for i := 0; i < len(s); i++ { + b.WriteString(s[i]) + } + b.WriteString(colorReset) + return b.String() +} + +func colorString(format string, attr Attribute, a ...interface{}) string { + return cache().value(attr).Sprintf(format, a...) +} + +// Black helper to produce black text to stdout. +func Black(format string, a ...interface{}) { Stdout().colorPrint(format, FgBlack, a...) } + +// BlackE helper to produce black text to stderr. +func BlackE(format string, a ...interface{}) { Stderr().colorPrint(format, FgBlack, a...) } + +// Red helper to produce red text to stdout. +func Red(format string, a ...interface{}) { Stdout().colorPrint(format, FgRed, a...) } + +// RedE helper to produce red text to stderr. +func RedE(format string, a ...interface{}) { Stderr().colorPrint(format, FgRed, a...) } + +// Green helper to produce green text to stdout. +func Green(format string, a ...interface{}) { Stdout().colorPrint(format, FgGreen, a...) } + +// GreenE helper to produce green text to stderr. +func GreenE(format string, a ...interface{}) { Stderr().colorPrint(format, FgGreen, a...) } + +// Yellow helper to produce yellow text to stdout. +func Yellow(format string, a ...interface{}) { Stdout().colorPrint(format, FgYellow, a...) } + +// YellowE helper to produce yellow text to stderr. +func YellowE(format string, a ...interface{}) { Stderr().colorPrint(format, FgYellow, a...) } + +// Blue helper to produce blue text to stdout. +func Blue(format string, a ...interface{}) { Stdout().colorPrint(format, FgBlue, a...) } + +// BlueE helper to produce blue text to stderr. +func BlueE(format string, a ...interface{}) { Stderr().colorPrint(format, FgBlue, a...) } + +// Magenta helper to produce magenta text to stdout. +func Magenta(format string, a ...interface{}) { Stdout().colorPrint(format, FgMagenta, a...) } + +// MagentaE produces magenta text to stderr. +func MagentaE(format string, a ...interface{}) { Stderr().colorPrint(format, FgMagenta, a...) } + +// Cyan helper to produce cyan text to stdout. +func Cyan(format string, a ...interface{}) { Stdout().colorPrint(format, FgCyan, a...) } + +// CyanE helper to produce cyan text to stderr. +func CyanE(format string, a ...interface{}) { Stderr().colorPrint(format, FgCyan, a...) } + +// White helper to produce white text to stdout. +func White(format string, a ...interface{}) { Stdout().colorPrint(format, FgWhite, a...) } + +// WhiteE helper to produce white text to stderr. +func WhiteE(format string, a ...interface{}) { Stderr().colorPrint(format, FgWhite, a...) } + +// BlackString returns a string decorated with black attributes. +func BlackString(format string, a ...interface{}) string { return colorString(format, FgBlack, a...) } + +// RedString returns a string decorated with red attributes. +func RedString(format string, a ...interface{}) string { return colorString(format, FgRed, a...) } + +// GreenString returns a string decorated with green attributes. +func GreenString(format string, a ...interface{}) string { return colorString(format, FgGreen, a...) } + +// YellowString returns a string decorated with yellow attributes. +func YellowString(format string, a ...interface{}) string { return colorString(format, FgYellow, a...) } + +// BlueString returns a string decorated with blue attributes. +func BlueString(format string, a ...interface{}) string { return colorString(format, FgBlue, a...) } + +// MagentaString returns a string decorated with magenta attributes. +func MagentaString(format string, a ...interface{}) string { + return colorString(format, FgMagenta, a...) +} + +// CyanString returns a string decorated with cyan attributes. +func CyanString(format string, a ...interface{}) string { return colorString(format, FgCyan, a...) } + +// WhiteString returns a string decorated with white attributes. +func WhiteString(format string, a ...interface{}) string { return colorString(format, FgWhite, a...) } + +// HiBlack helper to produce black text to stdout. +func HiBlack(format string, a ...interface{}) { Stdout().colorPrint(format, FgHiBlack, a...) } + +// HiBlackE helper to produce black text to stderr. +func HiBlackE(format string, a ...interface{}) { Stderr().colorPrint(format, FgHiBlack, a...) } + +// HiRed helper to write high contrast red text to stdout. +func HiRed(format string, a ...interface{}) { Stdout().colorPrint(format, FgHiRed, a...) } + +// HiRedE helper to write high contrast red text to stderr. +func HiRedE(format string, a ...interface{}) { Stderr().colorPrint(format, FgHiRed, a...) } + +// HiGreen helper writes high contrast green text to stdout. +func HiGreen(format string, a ...interface{}) { Stdout().colorPrint(format, FgHiGreen, a...) } + +// HiGreenE helper writes high contrast green text to stderr. +func HiGreenE(format string, a ...interface{}) { Stderr().colorPrint(format, FgHiGreen, a...) } + +// HiYellow helper writes high contrast yellow text to stdout. +func HiYellow(format string, a ...interface{}) { Stdout().colorPrint(format, FgHiYellow, a...) } + +// HiYellowE helper writes high contrast yellow text to stderr. +func HiYellowE(format string, a ...interface{}) { Stderr().colorPrint(format, FgHiYellow, a...) } + +// HiBlue helper writes high contrast blue text to stdout. +func HiBlue(format string, a ...interface{}) { Stdout().colorPrint(format, FgHiBlue, a...) } + +// HiBlueE helper writes high contrast blue text to stderr. +func HiBlueE(format string, a ...interface{}) { Stderr().colorPrint(format, FgHiBlue, a...) } + +// HiMagenta writes high contrast magenta text to stdout. +func HiMagenta(format string, a ...interface{}) { Stdout().colorPrint(format, FgHiMagenta, a...) } + +// HiMagentaE writes high contrast magenta text to stderr. +func HiMagentaE(format string, a ...interface{}) { Stderr().colorPrint(format, FgHiMagenta, a...) } + +// HiCyan writes high contrast cyan colored text to stdout. +func HiCyan(format string, a ...interface{}) { Stdout().colorPrint(format, FgHiCyan, a...) } + +// HiCyanE writes high contrast contrast cyan colored text to stderr. +func HiCyanE(format string, a ...interface{}) { Stderr().colorPrint(format, FgHiCyan, a...) } + +// HiWhite writes high contrast white colored text to stdout. +func HiWhite(format string, a ...interface{}) { Stdout().colorPrint(format, FgHiWhite, a...) } + +// HiWhiteE writes high contrast white colored text to stderr. +func HiWhiteE(format string, a ...interface{}) { Stderr().colorPrint(format, FgHiWhite, a...) } + +// HiBlackString returns a high contrast black string. +func HiBlackString(format string, a ...interface{}) string { + return colorString(format, FgHiBlack, a...) +} + +// HiRedString returns a high contrast contrast black string. +func HiRedString(format string, a ...interface{}) string { return colorString(format, FgHiRed, a...) } + +// HiGreenString returns a high contrast green string. +func HiGreenString(format string, a ...interface{}) string { + return colorString(format, FgHiGreen, a...) +} + +// HiYellowString returns a high contrast yellow string. +func HiYellowString(format string, a ...interface{}) string { + return colorString(format, FgHiYellow, a...) +} + +// HiBlueString returns a high contrast blue string. +func HiBlueString(format string, a ...interface{}) string { return colorString(format, FgHiBlue, a...) } + +// HiMagentaString returns a high contrast magenta string. +func HiMagentaString(format string, a ...interface{}) string { + return colorString(format, FgHiMagenta, a...) +} + +// HiCyanString returns a high contrast cyan string. +func HiCyanString(format string, a ...interface{}) string { return colorString(format, FgHiCyan, a...) } + +// HiWhiteString returns a high contrast white string. +func HiWhiteString(format string, a ...interface{}) string { + return colorString(format, FgHiWhite, a...) +} diff --git a/vendor/github.com/heroku/color/console.go b/vendor/github.com/heroku/color/console.go new file mode 100644 index 00000000000..031a7442ee0 --- /dev/null +++ b/vendor/github.com/heroku/color/console.go @@ -0,0 +1,167 @@ +// Package color produces colored output in terms of ANSI Escape Codes. Posix and Windows platforms are supported. +package color + +import ( + "fmt" + "io" + "os" + "strings" + "sync" + + "github.com/mattn/go-colorable" +) + +var noColor bool +var noColorLock sync.RWMutex + +// Disable is used to turn color output on and off globally. +func Disable(flag bool) { + noColorLock.Lock() + defer noColorLock.Unlock() + noColor = flag +} + +// Enabled returns flag indicating whether colors are enabled or not. +func Enabled() bool { + noColorLock.RLock() + defer noColorLock.RUnlock() + return !noColor +} + +var stdout *Console // Don't use directly use Stdout() instead. +var stdoutOnce sync.Once + +// Stdout returns an io.Writer that writes colored text to standard out. +func Stdout() *Console { + stdoutOnce.Do(func() { + stdout = NewConsole(os.Stdout) + }) + return stdout +} + +var stderr *Console // Don't use directly use Stderr() instead. +var stderrOnce sync.Once + +// Stderr returns an io.Writer that writes colored text to standard error. +func Stderr() *Console { + stderrOnce.Do(func() { + stderr = NewConsole(os.Stderr) + }) + return stderr +} + +// Console manages state for output, typically stdout or stderr. +type Console struct { + sync.Mutex + colored io.Writer + noncolored io.Writer + current io.Writer + fileDescriptor uintptr +} + +// NewConsole creates a wrapper around out which will output platform independent colored text. +func NewConsole(out *os.File) *Console { + c := &Console{ + colored: colorable.NewColorable(out), + noncolored: colorable.NewNonColorable(out), + fileDescriptor: out.Fd(), + } + if Enabled() { + c.current = c.colored + return c + } + c.current = c.noncolored + return c +} + +func (c *Console) Fd() uintptr { + c.Lock() + defer c.Unlock() + return c.fileDescriptor +} + +// DisableColors if true ANSI color information will be removed for this console object. Passing true will enable +// colors for this Console, even if colors are disabled globally. +func (c *Console) DisableColors(strip bool) { + c.Lock() + defer c.Unlock() + if strip { + c.current = c.noncolored + return + } + c.current = c.colored +} + +// Set will cause the color passed in as an argument to be written until Unset is called. +func (c *Console) Set(color *Color) { + c.Lock() + defer c.Unlock() + _, _ = c.current.Write([]byte(color.colorStart)) +} + +// Unset will restore console output to default. It will undo colored console output defined from a call to Set. +func (c *Console) Unset() { + c.Lock() + defer c.Unlock() + _, _ = c.current.Write([]byte(colorReset)) +} + +// Write so we can treat a console as a Writer +func (c *Console) Write(b []byte) (int, error) { + c.Lock() + n, err := c.current.Write(b) + c.Unlock() + return n, err +} + +// Print writes colored text to the console. The number of bytes written +// is returned. +func (c *Console) Print(col *Color, args ...string) (int, error) { + return c.Write([]byte(col.wrap(args...))) +} + +// Printf formats according to a format specifier and writes colored text to the console. +func (c *Console) Printf(col *Color, format string, args ...interface{}) (int, error) { + return c.Write([]byte(col.wrap(fmt.Sprintf(format, args...)))) +} + +// Println writes colored text to console, appending input with a line feed. +// The number of bytes written is returned. +func (c *Console) Println(col *Color, args ...string) (int, error) { + s := col.wrap(args...) + if !strings.HasSuffix(s, lineFeed) { + s += lineFeed + } + return c.Write([]byte(s)) + +} + +// PrintFunc returns a wrapper function for Print. +func (c *Console) PrintFunc(col *Color) func(a ...string) { + return func(a ...string) { + _, _ = c.Print(col, a...) + } +} + +// PrintfFunc returns a wrapper function for Printf. +func (c *Console) PrintfFunc(col *Color) func(format string, args ...interface{}) { + return func(format string, s ...interface{}) { + _, _ = c.Printf(col, format, s...) + } +} + +// PrintlnFunc returns a wrapper function for Println. +func (c *Console) PrintlnFunc(col *Color) func(a ...string) { + return func(a ...string) { + _, _ = c.Println(col, a...) + } +} + +func (c *Console) colorPrint(format string, attr Attribute, a ...interface{}) { + col := cache().value(attr) + if !strings.HasSuffix(format, lineFeed) { + _, _ = c.Println(col, fmt.Sprintf(format, a...)) + return + } + _, _ = c.Printf(col, format, fmt.Sprint(a...)) +} diff --git a/vendor/github.com/heroku/color/go.mod b/vendor/github.com/heroku/color/go.mod new file mode 100644 index 00000000000..d9507de7f80 --- /dev/null +++ b/vendor/github.com/heroku/color/go.mod @@ -0,0 +1,5 @@ +module github.com/heroku/color + +go 1.13 + +require github.com/mattn/go-colorable v0.1.2 diff --git a/vendor/github.com/heroku/color/go.sum b/vendor/github.com/heroku/color/go.sum new file mode 100644 index 00000000000..0a92752b3a7 --- /dev/null +++ b/vendor/github.com/heroku/color/go.sum @@ -0,0 +1,6 @@ +github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU= +github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 h1:DH4skfRX4EBpamg7iV4ZlCpblAHI6s6TDM39bFZumv8= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= diff --git a/vendor/github.com/mitchellh/ioprogress/LICENSE b/vendor/github.com/mitchellh/ioprogress/LICENSE new file mode 100644 index 00000000000..22985159044 --- /dev/null +++ b/vendor/github.com/mitchellh/ioprogress/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Mitchell Hashimoto + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/github.com/mitchellh/ioprogress/README.md b/vendor/github.com/mitchellh/ioprogress/README.md new file mode 100644 index 00000000000..3d291e9d14e --- /dev/null +++ b/vendor/github.com/mitchellh/ioprogress/README.md @@ -0,0 +1,42 @@ +# ioprogress + +ioprogress is a Go (golang) library with implementations of `io.Reader` +and `io.Writer` that draws progress bars. The primary use case for these +are for CLI applications but alternate progress bar writers can be supplied +for alternate environments. + +## Example + +![Progress](http://g.recordit.co/GO5HxT16QH.gif) + +## Installation + +Standard `go get`: + +``` +$ go get github.com/mitchellh/ioprogress +``` + +## Usage + +Here is an example of outputting a basic progress bar to the CLI as +we're "downloading" from some other `io.Reader` (perhaps from a network +connection): + +```go +// Imagine this came from some external source, such as a network connection, +// and that we have the full size of it, such as from a Content-Length HTTP +// header. +var r io.Reader + +// Create the progress reader +progressR := &ioprogress.Reader{ + Reader: r, + Size: rSize, +} + +// Copy all of the reader to some local file f. As it copies, the +// progressR will write progress to the terminal on os.Stdout. This is +// customizable. +io.Copy(f, progressR) +``` diff --git a/vendor/github.com/mitchellh/ioprogress/draw.go b/vendor/github.com/mitchellh/ioprogress/draw.go new file mode 100644 index 00000000000..83b7305a02f --- /dev/null +++ b/vendor/github.com/mitchellh/ioprogress/draw.go @@ -0,0 +1,104 @@ +package ioprogress + +import ( + "fmt" + "io" + "os" + "strings" +) + +// DrawFunc is the callback type for drawing progress. +type DrawFunc func(int64, int64) error + +// DrawTextFormatFunc is a callback used by DrawFuncs that draw text in +// order to format the text into some more human friendly format. +type DrawTextFormatFunc func(int64, int64) string + +var defaultDrawFunc DrawFunc + +func init() { + defaultDrawFunc = DrawTerminal(os.Stdout) +} + +// DrawTerminal returns a DrawFunc that draws a progress bar to an io.Writer +// that is assumed to be a terminal (and therefore respects carriage returns). +func DrawTerminal(w io.Writer) DrawFunc { + return DrawTerminalf(w, func(progress, total int64) string { + return fmt.Sprintf("%d/%d", progress, total) + }) +} + +// DrawTerminalf returns a DrawFunc that draws a progress bar to an io.Writer +// that is formatted with the given formatting function. +func DrawTerminalf(w io.Writer, f DrawTextFormatFunc) DrawFunc { + var maxLength int + + return func(progress, total int64) error { + if progress == -1 && total == -1 { + _, err := fmt.Fprintf(w, "\n") + return err + } + + // Make sure we pad it to the max length we've ever drawn so that + // we don't have trailing characters. + line := f(progress, total) + if len(line) < maxLength { + line = fmt.Sprintf( + "%s%s", + line, + strings.Repeat(" ", maxLength-len(line))) + } + maxLength = len(line) + + _, err := fmt.Fprint(w, line+"\r") + return err + } +} + +var byteUnits = []string{"B", "KB", "MB", "GB", "TB", "PB"} + +// DrawTextFormatBytes is a DrawTextFormatFunc that formats the progress +// and total into human-friendly byte formats. +func DrawTextFormatBytes(progress, total int64) string { + return fmt.Sprintf("%s/%s", byteUnitStr(progress), byteUnitStr(total)) +} + +// DrawTextFormatBar returns a DrawTextFormatFunc that draws a progress +// bar with the given width (in characters). This can be used in conjunction +// with another DrawTextFormatFunc to create a progress bar with bytes, for +// example: +// +// bar := DrawTextFormatBar(20) +// func(progress, total int64) string { +// return fmt.Sprintf( +// "%s %s", +// bar(progress, total), +// DrawTextFormatBytes(progress, total)) +// } +// +func DrawTextFormatBar(width int64) DrawTextFormatFunc { + width -= 2 + + return func(progress, total int64) string { + current := int64((float64(progress) / float64(total)) * float64(width)) + return fmt.Sprintf( + "[%s%s]", + strings.Repeat("=", int(current)), + strings.Repeat(" ", int(width-current))) + } +} + +func byteUnitStr(n int64) string { + var unit string + size := float64(n) + for i := 1; i < len(byteUnits); i++ { + if size < 1000 { + unit = byteUnits[i-1] + break + } + + size = size / 1000 + } + + return fmt.Sprintf("%.3g %s", size, unit) +} diff --git a/vendor/github.com/mitchellh/ioprogress/reader.go b/vendor/github.com/mitchellh/ioprogress/reader.go new file mode 100644 index 00000000000..7d52731e2d2 --- /dev/null +++ b/vendor/github.com/mitchellh/ioprogress/reader.go @@ -0,0 +1,107 @@ +package ioprogress + +import ( + "io" + "time" +) + +// Reader is an implementation of io.Reader that draws the progress of +// reading some data. +type Reader struct { + // Reader is the underlying reader to read from + Reader io.Reader + + // Size is the total size of the data coming out of the reader. + Size int64 + + // DrawFunc is the callback to invoke to draw the progress bar. By + // default, this will be DrawTerminal(os.Stdout). + // + // DrawInterval is the minimum time to wait between reads to update the + // progress bar. + DrawFunc DrawFunc + DrawInterval time.Duration + + progress int64 + lastDraw time.Time +} + +// Read reads from the underlying reader and invokes the DrawFunc if +// appropriate. The DrawFunc is executed when there is data that is +// read (progress is made) and at least DrawInterval time has passed. +func (r *Reader) Read(p []byte) (int, error) { + // If we haven't drawn before, initialize the progress bar + if r.lastDraw.IsZero() { + r.initProgress() + } + + // Read from the underlying source + n, err := r.Reader.Read(p) + + // Always increment the progress even if there was an error + r.progress += int64(n) + + // If we don't have any errors, then draw the progress. If we are + // at the end of the data, then finish the progress. + if err == nil { + // Only draw if we read data or we've never read data before (to + // initialize the progress bar). + if n > 0 { + r.drawProgress() + } + } + if err == io.EOF { + r.finishProgress() + } + + return n, err +} + +func (r *Reader) drawProgress() { + // If we've drawn before, then make sure that the draw interval + // has passed before we draw again. + interval := r.DrawInterval + if interval == 0 { + interval = time.Second + } + if !r.lastDraw.IsZero() { + nextDraw := r.lastDraw.Add(interval) + if time.Now().Before(nextDraw) { + return + } + } + + // Draw + f := r.drawFunc() + f(r.progress, r.Size) + + // Record this draw so that we don't draw again really quickly + r.lastDraw = time.Now() +} + +func (r *Reader) finishProgress() { + f := r.drawFunc() + f(r.progress, r.Size) + + // Print a newline + f(-1, -1) + + // Reset lastDraw so we don't finish again + var zeroDraw time.Time + r.lastDraw = zeroDraw +} + +func (r *Reader) initProgress() { + var zeroDraw time.Time + r.lastDraw = zeroDraw + r.drawProgress() + r.lastDraw = zeroDraw +} + +func (r *Reader) drawFunc() DrawFunc { + if r.DrawFunc == nil { + return defaultDrawFunc + } + + return r.DrawFunc +} diff --git a/vendor/golang.org/x/sync/singleflight/singleflight.go b/vendor/golang.org/x/sync/singleflight/singleflight.go new file mode 100644 index 00000000000..97a1aa4bb30 --- /dev/null +++ b/vendor/golang.org/x/sync/singleflight/singleflight.go @@ -0,0 +1,120 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package singleflight provides a duplicate function call suppression +// mechanism. +package singleflight // import "golang.org/x/sync/singleflight" + +import "sync" + +// call is an in-flight or completed singleflight.Do call +type call struct { + wg sync.WaitGroup + + // These fields are written once before the WaitGroup is done + // and are only read after the WaitGroup is done. + val interface{} + err error + + // forgotten indicates whether Forget was called with this call's key + // while the call was still in flight. + forgotten bool + + // These fields are read and written with the singleflight + // mutex held before the WaitGroup is done, and are read but + // not written after the WaitGroup is done. + dups int + chans []chan<- Result +} + +// Group represents a class of work and forms a namespace in +// which units of work can be executed with duplicate suppression. +type Group struct { + mu sync.Mutex // protects m + m map[string]*call // lazily initialized +} + +// Result holds the results of Do, so they can be passed +// on a channel. +type Result struct { + Val interface{} + Err error + Shared bool +} + +// Do executes and returns the results of the given function, making +// sure that only one execution is in-flight for a given key at a +// time. If a duplicate comes in, the duplicate caller waits for the +// original to complete and receives the same results. +// The return value shared indicates whether v was given to multiple callers. +func (g *Group) Do(key string, fn func() (interface{}, error)) (v interface{}, err error, shared bool) { + g.mu.Lock() + if g.m == nil { + g.m = make(map[string]*call) + } + if c, ok := g.m[key]; ok { + c.dups++ + g.mu.Unlock() + c.wg.Wait() + return c.val, c.err, true + } + c := new(call) + c.wg.Add(1) + g.m[key] = c + g.mu.Unlock() + + g.doCall(c, key, fn) + return c.val, c.err, c.dups > 0 +} + +// DoChan is like Do but returns a channel that will receive the +// results when they are ready. +func (g *Group) DoChan(key string, fn func() (interface{}, error)) <-chan Result { + ch := make(chan Result, 1) + g.mu.Lock() + if g.m == nil { + g.m = make(map[string]*call) + } + if c, ok := g.m[key]; ok { + c.dups++ + c.chans = append(c.chans, ch) + g.mu.Unlock() + return ch + } + c := &call{chans: []chan<- Result{ch}} + c.wg.Add(1) + g.m[key] = c + g.mu.Unlock() + + go g.doCall(c, key, fn) + + return ch +} + +// doCall handles the single call for a key. +func (g *Group) doCall(c *call, key string, fn func() (interface{}, error)) { + c.val, c.err = fn() + c.wg.Done() + + g.mu.Lock() + if !c.forgotten { + delete(g.m, key) + } + for _, ch := range c.chans { + ch <- Result{c.val, c.err, c.dups > 0} + } + g.mu.Unlock() +} + +// Forget tells the singleflight to forget about a key. Future calls +// to Do for this key will call the function rather than waiting for +// an earlier call to complete. +func (g *Group) Forget(key string) { + g.mu.Lock() + if c, ok := g.m[key]; ok { + c.forgotten = true + } + delete(g.m, key) + g.mu.Unlock() +} diff --git a/vendor/modules.txt b/vendor/modules.txt index b11afa60151..0146a95f17b 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -30,15 +30,49 @@ github.com/Azure/go-autorest/tracing github.com/BurntSushi/toml # github.com/MakeNowJust/heredoc v1.0.0 github.com/MakeNowJust/heredoc +# github.com/Masterminds/semver v1.4.2 +github.com/Masterminds/semver # github.com/Microsoft/go-winio v0.4.14 github.com/Microsoft/go-winio github.com/Microsoft/go-winio/pkg/guid +# github.com/apex/log v1.1.2-0.20190827100214-baa5455d1012 +github.com/apex/log # github.com/beorn7/perks v1.0.1 github.com/beorn7/perks/quantile # github.com/blang/semver v3.5.1+incompatible github.com/blang/semver # github.com/bmatcuk/doublestar v1.2.2 github.com/bmatcuk/doublestar +# github.com/buildpacks/imgutil v0.0.0-20191212154113-dc184e0d403b +github.com/buildpacks/imgutil +github.com/buildpacks/imgutil/local +github.com/buildpacks/imgutil/remote +# github.com/buildpacks/lifecycle v0.5.1-0.20191217221752-3b74c943b7b3 +github.com/buildpacks/lifecycle +github.com/buildpacks/lifecycle/archive +github.com/buildpacks/lifecycle/auth +github.com/buildpacks/lifecycle/cmd +# github.com/buildpacks/pack v0.6.0 +github.com/buildpacks/pack +github.com/buildpacks/pack/builder +github.com/buildpacks/pack/cmd +github.com/buildpacks/pack/internal/api +github.com/buildpacks/pack/internal/app +github.com/buildpacks/pack/internal/archive +github.com/buildpacks/pack/internal/blob +github.com/buildpacks/pack/internal/build +github.com/buildpacks/pack/internal/builder +github.com/buildpacks/pack/internal/buildpackage +github.com/buildpacks/pack/internal/cache +github.com/buildpacks/pack/internal/config +github.com/buildpacks/pack/internal/container +github.com/buildpacks/pack/internal/dist +github.com/buildpacks/pack/internal/image +github.com/buildpacks/pack/internal/paths +github.com/buildpacks/pack/internal/stack +github.com/buildpacks/pack/internal/stringset +github.com/buildpacks/pack/internal/style +github.com/buildpacks/pack/logging # github.com/cespare/xxhash/v2 v2.1.0 github.com/cespare/xxhash/v2 # github.com/containerd/continuity v0.0.0-20190827140505-75bee3e2ccb6 @@ -207,6 +241,8 @@ github.com/grpc-ecosystem/grpc-gateway/utilities # github.com/hashicorp/golang-lru v0.5.3 github.com/hashicorp/golang-lru github.com/hashicorp/golang-lru/simplelru +# github.com/heroku/color v0.0.6 +github.com/heroku/color # github.com/imdario/mergo v0.3.8 github.com/imdario/mergo # github.com/inconshreveable/mousetrap v1.0.0 @@ -243,6 +279,8 @@ github.com/mgutz/ansi github.com/mitchellh/go-homedir # github.com/mitchellh/go-wordwrap v1.0.0 github.com/mitchellh/go-wordwrap +# github.com/mitchellh/ioprogress v0.0.0-20180201004757-6a23b12fa88e +github.com/mitchellh/ioprogress # github.com/moby/buildkit v0.6.3 github.com/moby/buildkit/frontend/dockerfile/command github.com/moby/buildkit/frontend/dockerfile/parser @@ -372,6 +410,7 @@ golang.org/x/oauth2/jws golang.org/x/oauth2/jwt # golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e golang.org/x/sync/errgroup +golang.org/x/sync/singleflight # golang.org/x/sys v0.0.0-20191127021746-63cb32ae39b2 golang.org/x/sys/cpu golang.org/x/sys/unix