diff --git a/.travis.yml b/.travis.yml index ba309996d..146aed30a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,15 +11,10 @@ jobs: - 1.11.x env: - GO111MODULE=on - - DOCKER_TLS_VERIFY=1 - - secure: U0WHj8cs5dMFrfabxgmhl7Id6UL3+kELfIee7tREvBj3UKZl6iS2P6wA8oQkyvwLH1h+mO0QdTnQqwtH6cUnP1jNHG15loN3KM1504OB64UEv0AnOezrPZLhDQwBWT7T+Rw6iBjBWGUk9KdCuT5/JKlP46ZllRVuMphhtnJwGVggFL+W2ol6oL8qg1/pVT6HZNEwfsbBe3HH3EYw8mhvhM2WjscQKEjiNiIClKwO/IcJdZ0iCUSKvTk20nNIGOnIMfAXtmwMGJAB/nRmHDnzV3ijxyUsCPo6Ae2f/bJsU1The0gCItw9yAag6ckeeudPQtLLRlzZr/Z5l2Z05qWRr7v2BIIVDrs7lBYPUCkoJGy8azCTAnB3BdR0iv/w+6L/p5eK9rHxtW8zI+8rgswfxmAzZjAVDMuIDXXg/PUkK/g27UmzInUmf3gOJk9hItfYtT43hVqp0ZfFTZBtrwOjwVriHKl7o4jGwIkBWWr7UeFzASL0QE45e6yYxlobyuF/plww6ECe/tbGUrXRd52M01VWEqJqHqFZ3v/QUU7ZoYMYLZHAelXrQ9ymIFgBRiXCOCFrofzjMt8KgKEUHre++pBm6E9boUW3mcc6p9Wsi/Mh1cVjr/Fk3T0+4TqTm+Yo2yyabmOCQlRHubLRYcwOdJ9dkXBMIcS7IsQ6szG6kR8= go_import_path: github.com/buildpack/lifecycle script: | - openssl aes-256-cbc -K $encrypted_e607085e6307_key -iv $encrypted_e607085e6307_iv -in .travis/key.pem.enc -out .travis/key.pem -d test -z "$(bin/format | tee >(cat >&2))" - export DOCKER_CERT_PATH=$PWD/.travis/ - go test -v ./... - go test -tags=image -v ./image/... + go test -v -parallel=1 -p=1 -count=1 ./... - stage: build and push images if: branch = master AND fork = false env: diff --git a/.travis/ca.pem b/.travis/ca.pem deleted file mode 100644 index 0f36c4a37..000000000 --- a/.travis/ca.pem +++ /dev/null @@ -1,32 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIFkjCCA3qgAwIBAgIJAKUNDX8opC9EMA0GCSqGSIb3DQEBCwUAMF4xCzAJBgNV -BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX -aWRnaXRzIFB0eSBMdGQxFzAVBgNVBAMMDjM1LjE4OC4xNDkuMTU2MB4XDTE4MTEw -MjEyNTIzM1oXDTE5MTEwMjEyNTIzM1owXjELMAkGA1UEBhMCQVUxEzARBgNVBAgM -ClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEX -MBUGA1UEAwwOMzUuMTg4LjE0OS4xNTYwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw -ggIKAoICAQCmywVM8vJZ/nhgRP8t3scQDscagOK9Oe4vVYlvbQPlNqQAqVQUS3Xk -7qHziGU3b+JqMB7roLqoxLixZPcirhuSF128uFEHUAWPiL4sJxT8q/CyeKccrJgz -lrtU/5zHeAXCmg9m+Huw7cLDhHsSdMprYN8UFryZoaBUKqDUdtB/377v93UaT4EG -quS+/iJIOTq92+uf3ZqAeBVJAnKsvgqapVn4rnkW1P0MS24pwIgGKsOJYLYBiLlX -pmsjF4Cobh4XCvIqS2fiG1ogNgMWU7IUtrX+0qm5uzBtnRmUXl8/xCMsuGyOTesO -+0IYqv7N8ERO8I3ZFwrMdMHFJF1hRA2yWEdhLuen9TTvPLgqPASmkl/UVVUUZPhi -utM9Y3t/Es7DwO6k+N47WHCZ6M4IqQemVS48CEoFTKq2lBJvvit3oX1LHwwC+Wht -rNC1+YndrhjSvy7JkORnSV2VCDxvdtczkQ7oPUVtf9KU/GHBuYINjUX5S8d07jM8 -qj9Ry2RAZd3nYuf7upkmV5cNcrJw3aGK7SkGJE04OdVGHNDMWMeaufg4Vl+c3dYA -1/ij5pp0+7Wpndx4VCHPV1CeQuL7B2hcGKkXtgtCouK17DzPk3Xp9o0eg0dKhJGh -QEI9tUZ4sR14u4RaczB86nHtdLx01Iutgz7yK4djDlojz7nFMefYewIDAQABo1Mw -UTAdBgNVHQ4EFgQULPLY6c+OXLXMmHHtulI5FErrf4cwHwYDVR0jBBgwFoAULPLY -6c+OXLXMmHHtulI5FErrf4cwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsF -AAOCAgEACSNfR7AizY5yCT337yuK//Z7/YnQGWJQPDMavBRbaw8wCbqvIvEjJqVv -eFtbuWG3WKYG4kqL8q4uphZOXTT1LWu+mZdHAhiHrfiym95vNJ+Qa2/dHrggrcs0 -WdOFCwiDKk7kgwSW/WPe8ND9WnR+oHndjbm0xlVxk7KJviexpXSJ6IW/E8OS0o3+ -G+YmM1/EtuoscAkCAGiAE2YCX8wqYmmGgDX0swpOAjF7r+8TOksKcZuN5NbAdGnG -Lt2CvO5MYrYcr5NH0Qptm9bSR9ukC1vt2YxyPkwOp7fa12CYvfaQ8EzQLtpAHOLG -7TS3TQPb93IZwIYYJ2NlX3nMWTvbP9LS9EwwLRvnLuz8cIqPqs7v2HwKaPqA4EQM -Ez0ngQyG7lWahtdYKIbj2eE9ks50qDQn0pu3BPaPVHDfHU3KHCfrdnrHiXFGstpQ -6vjjqZR26SY9yMtDCSX/aoo1Kd6XhY5ZZR6/EPRtrPbEuGRz/59vqupYZ5aiJH5g -OQMHtCCYW88qhhuE4hkuaQpMNPOkLO+mZyQSAao96Nh0339Oqi4yyBJ9WT2RTzvu -J62WCmkj7dADvJnGLuDGSwUstq3UegIDHSshRRpU4QTnZmGtwS6fmSviPUM+fFbr -kOBmgpiQs4ezFF/6pm2BfMhqxv63v/dFtKMTsYO5l7VVx0j/dcc= ------END CERTIFICATE----- diff --git a/.travis/cert.pem b/.travis/cert.pem deleted file mode 100644 index f920dd492..000000000 --- a/.travis/cert.pem +++ /dev/null @@ -1,30 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIFNjCCAx6gAwIBAgIJAKGTQxXI9phQMA0GCSqGSIb3DQEBCwUAMF4xCzAJBgNV -BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX -aWRnaXRzIFB0eSBMdGQxFzAVBgNVBAMMDjM1LjE4OC4xNDkuMTU2MB4XDTE4MTEw -MjEyNTI1NFoXDTE5MTEwMjEyNTI1NFowETEPMA0GA1UEAwwGY2xpZW50MIICIjAN -BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAvBhNzYinC+SzZOCv2Oi6TRW5/FCi -I9kF8cE8FKTyQe4v5dlmnMK8Ku5azNKIYYdE6vkLZp+YSUfD4FXw5gwUsI31L3Lr -t6SdmDD5YcxOroNum85BNUPXF27hSSUTxnfh4Dezz8Q7W0jqMbQqFt1jcDtJytaj -ZNlVm4zEUCgvNZRvR+QQ2XoMCpN/v4YbVSZROLL+0Mew06WV06ym3EY1B4fmH4/+ -YoGHRzSZsT5P1xf6EhtnQ4B4uvFWfQAKuxyLgyE+nJacBApgW8CLU8/aRiRNeleB -W6VK6SHp301nXqtvVYeg+Xlh3f+NVvWXmeZbqEjr/9tQLdaJU2i9lKp7HzdtXtfF -XQMZLLnmPi6u0aeYFgWAR+yKGlRll4vy0wyrhhRYb7KmjBGSwRDjEMR7/JRYrbXc -vcTIKadewF3CBXljhyz3/xUhAsLQl2HuPh3NBuDcsE2TtwAonFK5jZvCMl6yyV3y -BENoB6S8GmGii1Dr+f6qrKsFs4RPtDy48D6ziRCohL2fWLCsXVGrLqoj5G0bkj31 -GMLre+cG4IJaAswLjS8RT+XuqMMn/YO5ieio1acKyYl+gS3aIwCjJ1dUVX0GdIn8 -irExky0zedTrAymNVu6AA8626DBLLJJEKvrwSTWD8F6rZrdTHUS/OJ0KCr4UDUPs -NwJm63uSZnoZ8EECAwEAAaNEMEIwKwYDVR0RBCQwIoIOMzUuMTg4LjE0OS4xNTaH -BCO8lZyHBAqAAAKHBH8AAAEwEwYDVR0lBAwwCgYIKwYBBQUHAwIwDQYJKoZIhvcN -AQELBQADggIBAJckHbk88A8VAQm3tFVIdHiVzQPQKsK59OzhjY5ng55KoWhRHTWZ -AKurpw4ZnOYZRy1Lk/n6Jun2JEEHUIE1SxKK8HfNO+T6mHoxSOkIQg9dd3aBzpyI -3ktX7jPoLIXELKAZa7G3J7Ym5c3YmDSTrQ04EVaZtuIcaCCLXvP/cv2OsC6X7MdC -WxNtGRriE85pDc3Me/Vafiv9Cdo4OiksTtiiUH5TgV9CYIzR7/n+QhGsZ1aJ/1wV -ko6uviCPxgYMQNQZtQZT1PSrKHYmul6XC+Wz+CgsXLRi7ADPTZS6TJq0psMU28wQ -VNOL50Vjj2FFz+XwM8hEqr7ZSAQ8Jmgm+mQWsTs022w0tIrNh085T1F9hNEt1beK -8fPW2J8fukN9QqUYYfwEjW7LGTIiKnWdMXHPeiHSHx4uQeCUb2zfPEa4Cx+h6cn/ -ySI0MAmKJNN3s2jst6giNhMC5md2VNxW3nr1JYfgalcWTqL3HL2ENYUj2Dnx8e6i -E2XOZmJ57/Wy83zYw08HgghdWdBkyxNpxTolwmBZhxSmtg1fa1VKlolAPGy0/jw+ -WoldSxU3AE81qLwcFRnf6N6wXV41AvEjC1vICLws4ZyhWLSyq70OH4D2LAEIkv7Z -owippOqhOdI3frlMh+3DqhpZ/5nts6RnA1ujuiTUf+pIYBbznB8VFqZh ------END CERTIFICATE----- diff --git a/.travis/key.pem.enc b/.travis/key.pem.enc deleted file mode 100644 index 04211f074..000000000 Binary files a/.travis/key.pem.enc and /dev/null differ diff --git a/cmd/analyzer/main.go b/cmd/analyzer/main.go index fed598ff3..3207dc241 100644 --- a/cmd/analyzer/main.go +++ b/cmd/analyzer/main.go @@ -2,7 +2,6 @@ package main import ( "flag" - "github.com/buildpack/lifecycle/image" "log" "os" @@ -10,6 +9,7 @@ import ( "github.com/buildpack/lifecycle" "github.com/buildpack/lifecycle/cmd" + "github.com/buildpack/lifecycle/image" ) var ( @@ -60,7 +60,7 @@ func analyzer() error { var err error var previousImage image.Image - factory, err := image.NewFactory(image.WithEnvKeychain, image.WithLegacyEnvKeychain) + factory, err := image.NewFactory(image.WithOutWriter(os.Stdout), image.WithEnvKeychain, image.WithLegacyEnvKeychain) if err != nil { return err } diff --git a/cmd/exporter/main.go b/cmd/exporter/main.go index 9cda64a8e..06cb0f843 100644 --- a/cmd/exporter/main.go +++ b/cmd/exporter/main.go @@ -75,7 +75,7 @@ func export() error { ArtifactsDir: artifactsDir, } - factory, err := image.NewFactory(image.WithEnvKeychain, image.WithLegacyEnvKeychain) + factory, err := image.NewFactory(image.WithOutWriter(os.Stdout), image.WithEnvKeychain, image.WithLegacyEnvKeychain) if err != nil { return err } diff --git a/go.mod b/go.mod index 4294e120e..8c136cb24 100644 --- a/go.mod +++ b/go.mod @@ -1,20 +1,28 @@ module github.com/buildpack/lifecycle require ( + github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 // indirect github.com/BurntSushi/toml v0.3.1 - github.com/dgodd/dockerdial v1.0.1 + github.com/Microsoft/go-winio v0.4.11 // indirect + github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect github.com/docker/distribution v2.7.0+incompatible // indirect github.com/docker/docker v0.7.3-0.20181027010111-b8e87cfdad8d github.com/docker/go-connections v0.4.0 + github.com/docker/go-units v0.3.3 // indirect github.com/gogo/protobuf v1.2.0 // indirect github.com/golang/mock v1.2.0 github.com/google/go-cmp v0.2.0 github.com/google/go-containerregistry v0.0.0-20190110221225-f514e780f7cd + github.com/gorilla/context v1.1.1 // indirect + github.com/gorilla/mux v1.6.2 // indirect + github.com/opencontainers/go-digest v1.0.0-rc1 // indirect + github.com/opencontainers/image-spec v1.0.1 // indirect github.com/pkg/errors v0.8.0 github.com/sclevine/spec v1.0.0 github.com/sirupsen/logrus v1.2.0 // indirect golang.org/x/net v0.0.0-20181201002055-351d144fa1fc // indirect golang.org/x/sys v0.0.0-20181128092732-4ed8d59d0b35 // indirect + golang.org/x/time v0.0.0-20181108054448-85acf8d2951c // indirect google.golang.org/grpc v1.17.0 // indirect gotest.tools v2.2.0+incompatible // indirect ) diff --git a/go.sum b/go.sum index b79dc94ac..2f55507cd 100644 --- a/go.sum +++ b/go.sum @@ -10,9 +10,6 @@ github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8 github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 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/docker/distribution v0.0.0-20180327202408-83389a148052/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.7.0+incompatible h1:neUDAlf3wX6Ml4HdqTrbcOHXtfRN0TFIwt6YFL7N9RU= github.com/docker/distribution v2.7.0+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker v0.7.3-0.20181027010111-b8e87cfdad8d h1:i8JkxYtxGIN2F2bHkhzj0S6iKQBOUSQrLbeVHWpOs4I= @@ -21,12 +18,10 @@ github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKoh github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-units v0.3.3 h1:Xk8S3Xj5sLGlG5g67hJmYMmUgXv5N4PhkjJHHqrwnTk= github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.0 h1:xU6/SpYbvkNYiptHJYEDRseDLvYE7wSqhYYNy0QSUzI= github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= 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.2.0 h1:28o5sBqPkBsMGnC6b4MvE2TzSr5/AT4c/1fLqVGIwlk= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= @@ -40,10 +35,7 @@ github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8 github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/mux v1.6.2 h1:Pgr17XVTNXAk3q/r4CpKzC5xBM/qW1uVLV+IhRZpIIk= github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -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/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 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ= @@ -56,7 +48,6 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 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.1.1/go.mod h1:zrgwTnHtNr00buQ1vSptGe8m1f/BbgsPukg8qsT7A+A= github.com/sirupsen/logrus v1.2.0 h1:juTguoYk5qI21pwyTXY3B3Y5cOTH3ZUyZCg1v/mihuo= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -64,10 +55,8 @@ github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1 github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793 h1:u+LnwYTOOW7Ukr/fppxEb1Nwz0AtPflrblfvUudpo+I= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -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/net v0.0.0-20180826012351-8a410e7b638d/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-20181201002055-351d144fa1fc h1:a3CU5tJYVj92DY2LaA1kUkrsqD5/3mLDhx2NcNqyW+0= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -75,7 +64,6 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6Zh golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/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-20181025063200-d989b31c8746/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181128092732-4ed8d59d0b35 h1:YAFjXN64LMvktoUZH9zgY4lGc/msGN7HQfoSuKCgaDU= golang.org/x/sys v0.0.0-20181128092732-4ed8d59d0b35/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= @@ -86,10 +74,8 @@ golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGm 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.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= google.golang.org/grpc v1.17.0 h1:TRJYBgMclJvGYn2rIMjj+h9KtMt5r1Ij7ODVRIZkwhk= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= -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= diff --git a/image/factory.go b/image/factory.go index a32b1d004..ab0338a96 100644 --- a/image/factory.go +++ b/image/factory.go @@ -1,6 +1,9 @@ package image import ( + "io" + "io/ioutil" + "github.com/docker/docker/client" "github.com/google/go-containerregistry/pkg/authn" "github.com/pkg/errors" @@ -13,11 +16,13 @@ type Factory struct { Docker *client.Client FS *fs.FS Keychain authn.Keychain + Out io.Writer } func NewFactory(ops ...func(*Factory)) (*Factory, error) { f := &Factory{ FS: &fs.FS{}, + Out: ioutil.Discard, Keychain: authn.DefaultKeychain, } @@ -41,6 +46,12 @@ func WithLegacyEnvKeychain(factory *Factory) { factory.Keychain = authn.NewMultiKeychain(&auth.LegacyEnvKeychain{}, factory.Keychain) } +func WithOutWriter(w io.Writer) func(factory *Factory) { + return func(factory *Factory) { + factory.Out = w + } +} + func newDocker() (*client.Client, error) { docker, err := client.NewClientWithOpts(client.FromEnv, client.WithVersion("1.38")) if err != nil { diff --git a/image/local.go b/image/local.go index 6c4bd9c0b..c70568192 100644 --- a/image/local.go +++ b/image/local.go @@ -19,6 +19,8 @@ import ( "github.com/docker/docker/api/types" dockertypes "github.com/docker/docker/api/types" dockerclient "github.com/docker/docker/client" + "github.com/docker/docker/pkg/jsonmessage" + "github.com/docker/docker/pkg/term" "github.com/google/go-containerregistry/pkg/name" "github.com/pkg/errors" @@ -42,7 +44,7 @@ type local struct { func (f *Factory) NewLocal(repoName string, pull bool) (Image, error) { if pull { - if err := f.pullImage(f.Docker, repoName); err != nil { + if err := f.pullImage(f.Out, f.Docker, repoName); err != nil { return nil, fmt.Errorf("failed to pull image '%s' : %s", repoName, err) } } @@ -408,7 +410,7 @@ func (l *local) prevDownload() error { return outerErr } -func (f *Factory) pullImage(dockerCli *dockerclient.Client, ref string) error { +func (f *Factory) pullImage(output io.Writer, dockerCli *dockerclient.Client, ref string) error { regAuth, err := f.registryAuth(ref) if err != nil { return errors.Wrap(err, "auth for docker pull") @@ -426,9 +428,13 @@ func (f *Factory) pullImage(dockerCli *dockerclient.Client, ref string) error { return err } } - if _, err := io.Copy(ioutil.Discard, rc); err != nil { + + termFd, isTerm := term.GetFdInfo(output) + err = jsonmessage.DisplayJSONMessagesStream(rc, output, termFd, isTerm, nil) + if err != nil { return err } + return rc.Close() } diff --git a/image/local_test.go b/image/local_test.go index 0a23f1b39..b6c3ea541 100644 --- a/image/local_test.go +++ b/image/local_test.go @@ -1,8 +1,7 @@ -// +build image - package image_test import ( + "bytes" "context" "fmt" "io" @@ -27,9 +26,15 @@ import ( h "github.com/buildpack/lifecycle/testhelpers" ) +var localTestRegistry *h.DockerRegistry + func TestLocal(t *testing.T) { - t.Parallel() rand.Seed(time.Now().UTC().UnixNano()) + + localTestRegistry = h.NewDockerRegistry() + localTestRegistry.Start(t) + defer localTestRegistry.Stop(t) + spec.Run(t, "local", testLocal, spec.Parallel(), spec.Report(report.Terminal{})) } @@ -45,6 +50,7 @@ func testLocal(t *testing.T, when spec.G, it spec.S) { factory = image.Factory{ Docker: dockerCli, FS: &fs.FS{}, + Out: ioutil.Discard, Keychain: authn.DefaultKeychain, } repoName = "pack-image-test-" + h.RandString(10) @@ -605,34 +611,80 @@ func testLocal(t *testing.T, when spec.G, it spec.S) { }) when("#Found", func() { - when("it exists", func() { + when("pull from remote", func() { it.Before(func() { - h.CreateImageOnLocal(t, dockerCli, repoName, fmt.Sprintf(` + repoName = "localhost:" + localTestRegistry.Port + "/pack-image-test-" + h.RandString(10) + }) + + when("it exists", func() { + var outBuf bytes.Buffer + it.Before(func() { + repoName = "localhost:" + localTestRegistry.Port + "/pack-image-test-" + h.RandString(10) + h.CreateImageOnRemote(t, dockerCli, repoName, fmt.Sprintf(` FROM scratch LABEL repo_name_for_randomisation=%s `, repoName)) + + factory.Out = &outBuf + }) + + it("returns true, nil", func() { + dockerImage, err := factory.NewLocal(repoName, true) + h.AssertNil(t, err) + exists, err := dockerImage.Found() + + h.AssertNil(t, err) + h.AssertEq(t, exists, true) + }) + + it("retrieve image pull output", func() { + _, err := factory.NewLocal(repoName, true) + h.AssertNil(t, err) + + h.Eventually(t, func() bool { + return strings.Contains(outBuf.String(), "Downloaded newer image for "+repoName) + }, 100*time.Millisecond, 10*time.Second) + }) }) - it.After(func() { - h.DockerRmi(dockerCli, repoName) + when("it does not exist", func() { + it("returns false, nil", func() { + _, err := factory.NewLocal(repoName, true) + h.AssertError(t, err, "not found") + }) }) + }) - it("returns true, nil", func() { - image, err := factory.NewLocal(repoName, false) - exists, err := image.Found() + when("no pull from remote", func() { + when("it exists", func() { + it.Before(func() { + h.CreateImageOnLocal(t, dockerCli, repoName, fmt.Sprintf(` + FROM scratch + LABEL repo_name_for_randomisation=%s + `, repoName)) + }) - h.AssertNil(t, err) - h.AssertEq(t, exists, true) + it.After(func() { + h.DockerRmi(dockerCli, repoName) + }) + + it("returns true, nil", func() { + image, err := factory.NewLocal(repoName, false) + exists, err := image.Found() + + h.AssertNil(t, err) + h.AssertEq(t, exists, true) + }) }) - }) - when("it does not exist", func() { - it("returns false, nil", func() { - image, err := factory.NewLocal(repoName, false) - exists, err := image.Found() + when("it does not exist", func() { + it("returns false, nil", func() { + image, err := factory.NewLocal(repoName, false) + exists, err := image.Found() - h.AssertNil(t, err) - h.AssertEq(t, exists, false) + h.AssertNil(t, err) + h.AssertEq(t, exists, false) + }) }) }) }) diff --git a/image/remote_test.go b/image/remote_test.go index 4d3b6e91c..33c017fac 100644 --- a/image/remote_test.go +++ b/image/remote_test.go @@ -1,5 +1,3 @@ -// +build image - package image_test import ( @@ -30,11 +28,13 @@ import ( var registryPort string func TestRemote(t *testing.T) { - t.Parallel() rand.Seed(time.Now().UTC().UnixNano()) - registryPort = h.RunRegistry(t, false) - defer h.StopRegistry(t) + dockerRegistry := h.NewDockerRegistry() + dockerRegistry.Start(t) + defer dockerRegistry.Stop(t) + + registryPort = dockerRegistry.Port spec.Run(t, "remote", testRemote, spec.Sequential(), spec.Report(report.Terminal{})) } diff --git a/testhelpers/docker_registry.go b/testhelpers/docker_registry.go new file mode 100644 index 000000000..19b6163f7 --- /dev/null +++ b/testhelpers/docker_registry.go @@ -0,0 +1,59 @@ +package testhelpers + +import ( + "context" + "fmt" + "testing" + "time" + + dockertypes "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/container" + "github.com/docker/go-connections/nat" +) + +type DockerRegistry struct { + Port string + Name string +} + +func NewDockerRegistry() *DockerRegistry { + return &DockerRegistry{} +} + +func (registry *DockerRegistry) Start(t *testing.T) { + t.Log("run registry") + t.Helper() + registry.Name = "test-registry-" + RandString(10) + + AssertNil(t, PullImage(DockerCli(t), "registry:2")) + ctx := context.Background() + ctr, err := DockerCli(t).ContainerCreate(ctx, &container.Config{ + Image: "registry:2", + }, &container.HostConfig{ + AutoRemove: true, + PortBindings: nat.PortMap{ + "5000/tcp": []nat.PortBinding{{}}, + }, + }, nil, registry.Name) + AssertNil(t, err) + err = DockerCli(t).ContainerStart(ctx, ctr.ID, dockertypes.ContainerStartOptions{}) + AssertNil(t, err) + + inspect, err := DockerCli(t).ContainerInspect(ctx, ctr.ID) + AssertNil(t, err) + registry.Port = inspect.NetworkSettings.Ports["5000/tcp"][0].HostPort + + Eventually(t, func() bool { + txt, err := HttpGetE(fmt.Sprintf("http://localhost:%s/v2/", registry.Port)) + return err == nil && txt != "" + }, 100*time.Millisecond, 10*time.Second) +} + +func (registry *DockerRegistry) Stop(t *testing.T) { + t.Log("stop registry") + t.Helper() + if registry.Name != "" { + DockerCli(t).ContainerKill(context.Background(), registry.Name, "SIGKILL") + DockerCli(t).ContainerRemove(context.TODO(), registry.Name, dockertypes.ContainerRemoveOptions{Force: true}) + } +} diff --git a/testhelpers/testhelpers.go b/testhelpers/testhelpers.go index c02302a4b..d95601629 100644 --- a/testhelpers/testhelpers.go +++ b/testhelpers/testhelpers.go @@ -9,9 +9,7 @@ import ( "fmt" "io" "io/ioutil" - "log" "math/rand" - "net" "net/http" "os" "os/exec" @@ -22,13 +20,12 @@ import ( "testing" "time" - "github.com/buildpack/lifecycle/fs" - "github.com/dgodd/dockerdial" dockertypes "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/container" - dockerClient "github.com/docker/docker/client" - "github.com/docker/go-connections/nat" + dockercli "github.com/docker/docker/client" "github.com/google/go-cmp/cmp" + + "github.com/buildpack/lifecycle/fs" ) func RandString(n int) string { @@ -82,96 +79,18 @@ func AssertNil(t *testing.T, actual interface{}) { } } -var dockerCliVal *dockerClient.Client +var dockerCliVal *dockercli.Client var dockerCliOnce sync.Once -func DockerCli(t *testing.T) *dockerClient.Client { +func DockerCli(t *testing.T) *dockercli.Client { dockerCliOnce.Do(func() { var dockerCliErr error - dockerCliVal, dockerCliErr = dockerClient.NewClientWithOpts(dockerClient.FromEnv, dockerClient.WithVersion("1.38")) + dockerCliVal, dockerCliErr = dockercli.NewClientWithOpts(dockercli.FromEnv, dockercli.WithVersion("1.38")) AssertNil(t, dockerCliErr) }) return dockerCliVal } -var runRegistryName, runRegistryPort string -var runRegistryOnce sync.Once - -func RunRegistry(t *testing.T, seedRegistry bool) (localPort string) { - t.Log("run registry") - t.Helper() - runRegistryOnce.Do(func() { - runRegistryName = "test-registry-" + RandString(10) - - AssertNil(t, PullImage(DockerCli(t), "registry:2")) - ctx := context.Background() - ctr, err := DockerCli(t).ContainerCreate(ctx, &container.Config{ - Image: "registry:2", - }, &container.HostConfig{ - AutoRemove: true, - PortBindings: nat.PortMap{ - "5000/tcp": []nat.PortBinding{{}}, - }, - }, nil, runRegistryName) - AssertNil(t, err) - defer DockerCli(t).ContainerRemove(ctx, ctr.ID, dockertypes.ContainerRemoveOptions{}) - err = DockerCli(t).ContainerStart(ctx, ctr.ID, dockertypes.ContainerStartOptions{}) - AssertNil(t, err) - - inspect, err := DockerCli(t).ContainerInspect(context.TODO(), ctr.ID) - AssertNil(t, err) - runRegistryPort = inspect.NetworkSettings.Ports["5000/tcp"][0].HostPort - - if os.Getenv("DOCKER_HOST") != "" { - err := proxyDockerHostPort(DockerCli(t), runRegistryPort) - AssertNil(t, err) - } - - Eventually(t, func() bool { - txt, err := HttpGetE(fmt.Sprintf("http://localhost:%s/v2/", runRegistryPort)) - return err == nil && txt != "" - }, 100*time.Millisecond, 10*time.Second) - - if seedRegistry { - t.Log("seed registry") - for _, f := range []func(*testing.T, string) string{DefaultBuildImage, DefaultRunImage, DefaultBuilderImage} { - AssertNil(t, pushImage(DockerCli(t), f(t, runRegistryPort))) - } - } - }) - return runRegistryPort -} -func proxyDockerHostPort(dockerCli *dockerClient.Client, port string) error { - ln, err := net.Listen("tcp", ":"+port) - if err != nil { - return err - } - - go func() { - // TODO exit somehow. - for { - conn, err := ln.Accept() - if err != nil { - log.Println(err) - continue - } - go func(conn net.Conn) { - defer conn.Close() - c, err := dockerdial.Dial("tcp", "localhost:"+port) - if err != nil { - log.Println(err) - return - } - defer c.Close() - - go io.Copy(c, conn) - io.Copy(conn, c) - }(conn) - } - }() - return nil -} - func Eventually(t *testing.T, test func() bool, every time.Duration, timeout time.Duration) { t.Helper() @@ -192,70 +111,9 @@ func Eventually(t *testing.T, test func() bool, every time.Duration, timeout tim } } -func StopRegistry(t *testing.T) { - t.Log("stop registry") - t.Helper() - if runRegistryName != "" { - DockerCli(t).ContainerKill(context.Background(), runRegistryName, "SIGKILL") - DockerCli(t).ContainerRemove(context.TODO(), runRegistryName, dockertypes.ContainerRemoveOptions{Force: true}) - } -} - var getBuildImageOnce sync.Once -func DefaultBuildImage(t *testing.T, registryPort string) string { - t.Helper() - tag := packTag() - getBuildImageOnce.Do(func() { - if tag == "latest" { - AssertNil(t, PullImage(DockerCli(t), fmt.Sprintf("packs/build:%s", tag))) - } - AssertNil(t, DockerCli(t).ImageTag( - context.Background(), - fmt.Sprintf("packs/build:%s", tag), - fmt.Sprintf("localhost:%s/packs/build:%s", registryPort, tag), - )) - }) - return fmt.Sprintf("localhost:%s/packs/build:%s", registryPort, tag) -} - -var getRunImageOnce sync.Once - -func DefaultRunImage(t *testing.T, registryPort string) string { - t.Helper() - tag := packTag() - getRunImageOnce.Do(func() { - if tag == "latest" { - AssertNil(t, PullImage(DockerCli(t), fmt.Sprintf("packs/run:%s", tag))) - } - AssertNil(t, DockerCli(t).ImageTag( - context.Background(), - fmt.Sprintf("packs/run:%s", tag), - fmt.Sprintf("localhost:%s/packs/run:%s", registryPort, tag), - )) - }) - return fmt.Sprintf("localhost:%s/packs/run:%s", registryPort, tag) -} - -var getBuilderImageOnce sync.Once - -func DefaultBuilderImage(t *testing.T, registryPort string) string { - t.Helper() - tag := packTag() - getBuilderImageOnce.Do(func() { - if tag == "latest" { - AssertNil(t, PullImage(DockerCli(t), fmt.Sprintf("packs/samples:%s", tag))) - } - AssertNil(t, DockerCli(t).ImageTag( - context.Background(), - fmt.Sprintf("packs/samples:%s", tag), - fmt.Sprintf("localhost:%s/packs/samples:%s", registryPort, tag), - )) - }) - return fmt.Sprintf("localhost:%s/packs/samples:%s", registryPort, tag) -} - -func CreateImageOnLocal(t *testing.T, dockerCli *dockerClient.Client, repoName, dockerFile string) { +func CreateImageOnLocal(t *testing.T, dockerCli *dockercli.Client, repoName, dockerFile string) { ctx := context.Background() buildContext, err := (&fs.FS{}).CreateSingleFileTar("Dockerfile", dockerFile) @@ -273,7 +131,7 @@ func CreateImageOnLocal(t *testing.T, dockerCli *dockerClient.Client, repoName, res.Body.Close() } -func CreateImageOnRemote(t *testing.T, dockerCli *dockerClient.Client, repoName, dockerFile string) string { +func CreateImageOnRemote(t *testing.T, dockerCli *dockercli.Client, repoName, dockerFile string) string { t.Helper() defer DockerRmi(dockerCli, repoName) @@ -293,7 +151,7 @@ func CreateImageOnRemote(t *testing.T, dockerCli *dockerClient.Client, repoName, return topLayer } -func PullImage(dockerCli *dockerClient.Client, ref string) error { +func PullImage(dockerCli *dockercli.Client, ref string) error { rc, err := dockerCli.ImagePull(context.Background(), ref, dockertypes.ImagePullOptions{}) if err != nil { // Retry @@ -308,7 +166,7 @@ func PullImage(dockerCli *dockerClient.Client, ref string) error { return rc.Close() } -func DockerRmi(dockerCli *dockerClient.Client, repoNames ...string) error { +func DockerRmi(dockerCli *dockercli.Client, repoNames ...string) error { var err error ctx := context.Background() for _, name := range repoNames { @@ -324,7 +182,7 @@ func DockerRmi(dockerCli *dockerClient.Client, repoNames ...string) error { return err } -func CopySingleFileFromContainer(dockerCli *dockerClient.Client, ctrID, path string) (string, error) { +func CopySingleFileFromContainer(dockerCli *dockercli.Client, ctrID, path string) (string, error) { r, _, err := dockerCli.CopyFromContainer(context.Background(), ctrID, path) if err != nil { return "", err @@ -339,7 +197,7 @@ func CopySingleFileFromContainer(dockerCli *dockerClient.Client, ctrID, path str return string(b), err } -func CopySingleFileFromImage(dockerCli *dockerClient.Client, repoName, path string) (string, error) { +func CopySingleFileFromImage(dockerCli *dockercli.Client, repoName, path string) (string, error) { ctr, err := dockerCli.ContainerCreate(context.Background(), &container.Config{ Image: repoName, @@ -354,7 +212,7 @@ func CopySingleFileFromImage(dockerCli *dockerClient.Client, repoName, path stri return CopySingleFileFromContainer(dockerCli, ctr.ID, path) } -func pushImage(dockerCli *dockerClient.Client, ref string) error { +func pushImage(dockerCli *dockercli.Client, ref string) error { rc, err := dockerCli.ImagePush(context.Background(), ref, dockertypes.ImagePushOptions{RegistryAuth: "{}"}) if err != nil { return err