github.com/YousefHaggyHeroku/pack@v1.5.5/internal/image/fetcher_test.go (about) 1 package image_test 2 3 import ( 4 "bytes" 5 "context" 6 "fmt" 7 "math/rand" 8 "os" 9 "testing" 10 "time" 11 12 "github.com/buildpacks/imgutil/local" 13 "github.com/buildpacks/imgutil/remote" 14 "github.com/docker/docker/client" 15 "github.com/google/go-containerregistry/pkg/authn" 16 "github.com/heroku/color" 17 "github.com/sclevine/spec" 18 "github.com/sclevine/spec/report" 19 20 pubcfg "github.com/YousefHaggyHeroku/pack/config" 21 "github.com/YousefHaggyHeroku/pack/internal/image" 22 "github.com/YousefHaggyHeroku/pack/internal/logging" 23 h "github.com/YousefHaggyHeroku/pack/testhelpers" 24 ) 25 26 var docker client.CommonAPIClient 27 var registryConfig *h.TestRegistryConfig 28 29 func TestFetcher(t *testing.T) { 30 rand.Seed(time.Now().UTC().UnixNano()) 31 32 color.Disable(true) 33 defer color.Disable(false) 34 35 h.RequireDocker(t) 36 37 registryConfig = h.RunRegistry(t) 38 defer registryConfig.StopRegistry(t) 39 40 // TODO: is there a better solution to the auth problem? 41 os.Setenv("DOCKER_CONFIG", registryConfig.DockerConfigDir) 42 43 var err error 44 docker, err = client.NewClientWithOpts(client.FromEnv, client.WithVersion("1.38")) 45 h.AssertNil(t, err) 46 spec.Run(t, "Fetcher", testFetcher, spec.Report(report.Terminal{})) 47 } 48 49 func testFetcher(t *testing.T, when spec.G, it spec.S) { 50 var ( 51 fetcher *image.Fetcher 52 repoName string 53 repo string 54 outBuf bytes.Buffer 55 ) 56 57 it.Before(func() { 58 repo = "some-org/" + h.RandString(10) 59 repoName = registryConfig.RepoName(repo) 60 fetcher = image.NewFetcher(logging.NewLogWithWriters(&outBuf, &outBuf), docker) 61 }) 62 63 when("#Fetch", func() { 64 when("daemon is false", func() { 65 when("PullAlways", func() { 66 when("there is a remote image", func() { 67 it.Before(func() { 68 img, err := remote.NewImage(repoName, authn.DefaultKeychain) 69 h.AssertNil(t, err) 70 71 h.AssertNil(t, img.Save()) 72 }) 73 74 it("returns the remote image", func() { 75 _, err := fetcher.Fetch(context.TODO(), repoName, false, pubcfg.PullAlways) 76 h.AssertNil(t, err) 77 }) 78 }) 79 80 when("there is no remote image", func() { 81 it("returns an error", func() { 82 _, err := fetcher.Fetch(context.TODO(), repoName, false, pubcfg.PullAlways) 83 h.AssertError(t, err, fmt.Sprintf("image '%s' does not exist in registry", repoName)) 84 }) 85 }) 86 }) 87 88 when("PullIfNotPresent", func() { 89 when("there is a remote image", func() { 90 it.Before(func() { 91 img, err := remote.NewImage(repoName, authn.DefaultKeychain) 92 h.AssertNil(t, err) 93 94 h.AssertNil(t, img.Save()) 95 }) 96 97 it("returns the remote image", func() { 98 _, err := fetcher.Fetch(context.TODO(), repoName, false, pubcfg.PullIfNotPresent) 99 h.AssertNil(t, err) 100 }) 101 }) 102 103 when("there is no remote image", func() { 104 it("returns an error", func() { 105 _, err := fetcher.Fetch(context.TODO(), repoName, false, pubcfg.PullIfNotPresent) 106 h.AssertError(t, err, fmt.Sprintf("image '%s' does not exist in registry", repoName)) 107 }) 108 }) 109 }) 110 }) 111 112 when("daemon is true", func() { 113 when("PullNever", func() { 114 when("there is a local image", func() { 115 it.Before(func() { 116 // Make sure the repoName is not a valid remote repo. 117 // This is to verify that no remote check is made 118 // when there's a valid local image. 119 repoName = "invalidhost" + repoName 120 121 img, err := local.NewImage(repoName, docker) 122 h.AssertNil(t, err) 123 124 h.AssertNil(t, img.Save()) 125 }) 126 127 it.After(func() { 128 h.DockerRmi(docker, repoName) 129 }) 130 131 it("returns the local image", func() { 132 _, err := fetcher.Fetch(context.TODO(), repoName, true, pubcfg.PullNever) 133 h.AssertNil(t, err) 134 }) 135 }) 136 137 when("there is no local image", func() { 138 it("returns an error", func() { 139 _, err := fetcher.Fetch(context.TODO(), repoName, true, pubcfg.PullNever) 140 h.AssertError(t, err, fmt.Sprintf("image '%s' does not exist on the daemon", repoName)) 141 }) 142 }) 143 }) 144 145 when("PullAlways", func() { 146 when("there is a remote image", func() { 147 var ( 148 logger *logging.LogWithWriters 149 output func() string 150 ) 151 152 it.Before(func() { 153 // Instantiate a pull-able local image 154 // as opposed to a remote image so that the image 155 // is created with the OS of the docker daemon 156 img, err := local.NewImage(repoName, docker) 157 h.AssertNil(t, err) 158 defer h.DockerRmi(docker, repoName) 159 160 h.AssertNil(t, img.Save()) 161 162 h.AssertNil(t, h.PushImage(docker, img.Name(), registryConfig)) 163 164 var outCons *color.Console 165 outCons, output = h.MockWriterAndOutput() 166 logger = logging.NewLogWithWriters(outCons, outCons) 167 fetcher = image.NewFetcher(logger, docker) 168 }) 169 170 it.After(func() { 171 h.DockerRmi(docker, repoName) 172 }) 173 174 it("pull the image and return the local copy", func() { 175 _, err := fetcher.Fetch(context.TODO(), repoName, true, pubcfg.PullAlways) 176 h.AssertNil(t, err) 177 h.AssertNotEq(t, output(), "") 178 }) 179 180 it("doesn't log anything in quiet mode", func() { 181 logger.WantQuiet(true) 182 _, err := fetcher.Fetch(context.TODO(), repoName, true, pubcfg.PullAlways) 183 h.AssertNil(t, err) 184 h.AssertEq(t, output(), "") 185 }) 186 }) 187 188 when("there is no remote image", func() { 189 when("there is a local image", func() { 190 it.Before(func() { 191 img, err := local.NewImage(repoName, docker) 192 h.AssertNil(t, err) 193 194 h.AssertNil(t, img.Save()) 195 }) 196 197 it.After(func() { 198 h.DockerRmi(docker, repoName) 199 }) 200 201 it("returns the local image", func() { 202 _, err := fetcher.Fetch(context.TODO(), repoName, true, pubcfg.PullAlways) 203 h.AssertNil(t, err) 204 }) 205 }) 206 207 when("there is no local image", func() { 208 it("returns an error", func() { 209 _, err := fetcher.Fetch(context.TODO(), repoName, true, pubcfg.PullAlways) 210 h.AssertError(t, err, fmt.Sprintf("image '%s' does not exist on the daemon", repoName)) 211 }) 212 }) 213 }) 214 }) 215 216 when("PullIfNotPresent", func() { 217 when("there is a remote image", func() { 218 var ( 219 label = "label" 220 remoteImgLabel string 221 ) 222 223 it.Before(func() { 224 // Instantiate a pull-able local image 225 // as opposed to a remote image so that the image 226 // is created with the OS of the docker daemon 227 remoteImg, err := local.NewImage(repoName, docker) 228 h.AssertNil(t, err) 229 defer h.DockerRmi(docker, repoName) 230 231 h.AssertNil(t, remoteImg.SetLabel(label, "1")) 232 h.AssertNil(t, remoteImg.Save()) 233 234 h.AssertNil(t, h.PushImage(docker, remoteImg.Name(), registryConfig)) 235 236 remoteImgLabel, err = remoteImg.Label(label) 237 h.AssertNil(t, err) 238 }) 239 240 it.After(func() { 241 h.DockerRmi(docker, repoName) 242 }) 243 244 when("there is a local image", func() { 245 var localImgLabel string 246 247 it.Before(func() { 248 localImg, err := local.NewImage(repoName, docker) 249 h.AssertNil(t, localImg.SetLabel(label, "2")) 250 h.AssertNil(t, err) 251 252 h.AssertNil(t, localImg.Save()) 253 254 localImgLabel, err = localImg.Label(label) 255 h.AssertNil(t, err) 256 }) 257 258 it.After(func() { 259 h.DockerRmi(docker, repoName) 260 }) 261 262 it("returns the local image", func() { 263 fetchedImg, err := fetcher.Fetch(context.TODO(), repoName, true, pubcfg.PullIfNotPresent) 264 h.AssertNil(t, err) 265 h.AssertNotContains(t, outBuf.String(), "Pulling image") 266 267 fetchedImgLabel, err := fetchedImg.Label(label) 268 h.AssertNil(t, err) 269 270 h.AssertEq(t, fetchedImgLabel, localImgLabel) 271 h.AssertNotEq(t, fetchedImgLabel, remoteImgLabel) 272 }) 273 }) 274 275 when("there is no local image", func() { 276 it("returns the remote image", func() { 277 fetchedImg, err := fetcher.Fetch(context.TODO(), repoName, true, pubcfg.PullIfNotPresent) 278 h.AssertNil(t, err) 279 280 fetchedImgLabel, err := fetchedImg.Label(label) 281 h.AssertNil(t, err) 282 h.AssertEq(t, fetchedImgLabel, remoteImgLabel) 283 }) 284 }) 285 }) 286 287 when("there is no remote image", func() { 288 when("there is a local image", func() { 289 it.Before(func() { 290 img, err := local.NewImage(repoName, docker) 291 h.AssertNil(t, err) 292 293 h.AssertNil(t, img.Save()) 294 }) 295 296 it.After(func() { 297 h.DockerRmi(docker, repoName) 298 }) 299 300 it("returns the local image", func() { 301 _, err := fetcher.Fetch(context.TODO(), repoName, true, pubcfg.PullIfNotPresent) 302 h.AssertNil(t, err) 303 }) 304 }) 305 306 when("there is no local image", func() { 307 it("returns an error", func() { 308 _, err := fetcher.Fetch(context.TODO(), repoName, true, pubcfg.PullIfNotPresent) 309 h.AssertError(t, err, fmt.Sprintf("image '%s' does not exist on the daemon", repoName)) 310 }) 311 }) 312 }) 313 }) 314 }) 315 }) 316 }