github.com/buildpacks/pack@v0.33.3-0.20240516162812-884dd1837311/acceptance/managers/image_manager.go (about) 1 //go:build acceptance 2 // +build acceptance 3 4 package managers 5 6 import ( 7 "bytes" 8 "context" 9 "fmt" 10 "testing" 11 "time" 12 13 dockertypes "github.com/docker/docker/api/types" 14 "github.com/docker/docker/api/types/container" 15 "github.com/docker/docker/client" 16 "github.com/docker/go-connections/nat" 17 18 h "github.com/buildpacks/pack/testhelpers" 19 ) 20 21 var DefaultDuration = 10 * time.Second 22 23 type ImageManager struct { 24 testObject *testing.T 25 assert h.AssertionManager 26 dockerCli client.CommonAPIClient 27 } 28 29 func NewImageManager(t *testing.T, dockerCli client.CommonAPIClient) ImageManager { 30 return ImageManager{ 31 testObject: t, 32 assert: h.NewAssertionManager(t), 33 dockerCli: dockerCli, 34 } 35 } 36 37 func (im ImageManager) CleanupImages(imageNames ...string) { 38 im.testObject.Helper() 39 err := h.DockerRmi(im.dockerCli, imageNames...) 40 if err != nil { 41 im.testObject.Logf("%s: Failed to remove image from %s", err, imageNames) 42 } 43 } 44 45 func (im ImageManager) InspectLocal(image string) (dockertypes.ImageInspect, error) { 46 im.testObject.Helper() 47 inspect, _, err := im.dockerCli.ImageInspectWithRaw(context.Background(), image) 48 return inspect, err 49 } 50 51 func (im ImageManager) GetImageID(image string) string { 52 im.testObject.Helper() 53 inspect, err := im.InspectLocal(image) 54 im.assert.Nil(err) 55 return inspect.ID 56 } 57 58 func (im ImageManager) HostOS() string { 59 im.testObject.Helper() 60 daemonInfo, err := im.dockerCli.Info(context.Background()) 61 im.assert.Nil(err) 62 return daemonInfo.OSType 63 } 64 65 func (im ImageManager) TagImage(image, ref string) { 66 im.testObject.Helper() 67 err := im.dockerCli.ImageTag(context.Background(), image, ref) 68 im.assert.Nil(err) 69 } 70 71 func (im ImageManager) PullImage(image, registryAuth string) { 72 im.testObject.Helper() 73 err := h.PullImageWithAuth(im.dockerCli, image, registryAuth) 74 im.assert.Nil(err) 75 } 76 77 func (im ImageManager) ExposePortOnImage(image, containerName string) TestContainer { 78 im.testObject.Helper() 79 ctx := context.Background() 80 81 ctr, err := im.dockerCli.ContainerCreate(ctx, &container.Config{ 82 Image: image, 83 ExposedPorts: map[nat.Port]struct{}{"8080/tcp": {}}, 84 Healthcheck: nil, 85 }, &container.HostConfig{ 86 PortBindings: nat.PortMap{ 87 "8080/tcp": []nat.PortBinding{{}}, 88 }, 89 AutoRemove: true, 90 }, nil, nil, containerName) 91 im.assert.Nil(err) 92 93 err = im.dockerCli.ContainerStart(ctx, ctr.ID, container.StartOptions{}) 94 im.assert.Nil(err) 95 return TestContainer{ 96 testObject: im.testObject, 97 dockerCli: im.dockerCli, 98 assert: im.assert, 99 name: containerName, 100 id: ctr.ID, 101 } 102 } 103 104 func (im ImageManager) CreateContainer(name string) TestContainer { 105 im.testObject.Helper() 106 containerName := "test-" + h.RandString(10) 107 ctr, err := im.dockerCli.ContainerCreate(context.Background(), &container.Config{ 108 Image: name, 109 }, nil, nil, nil, containerName) 110 im.assert.Nil(err) 111 112 return TestContainer{ 113 testObject: im.testObject, 114 dockerCli: im.dockerCli, 115 assert: im.assert, 116 name: containerName, 117 id: ctr.ID, 118 } 119 } 120 121 type TestContainer struct { 122 testObject *testing.T 123 dockerCli client.CommonAPIClient 124 assert h.AssertionManager 125 name string 126 id string 127 } 128 129 func (t TestContainer) RunWithOutput() string { 130 t.testObject.Helper() 131 var b bytes.Buffer 132 err := h.RunContainer(context.Background(), t.dockerCli, t.id, &b, &b) 133 t.assert.Nil(err) 134 return b.String() 135 } 136 137 func (t TestContainer) Cleanup() { 138 t.testObject.Helper() 139 t.dockerCli.ContainerKill(context.Background(), t.name, "SIGKILL") 140 t.dockerCli.ContainerRemove(context.Background(), t.name, container.RemoveOptions{Force: true}) 141 } 142 143 func (t TestContainer) WaitForResponse(duration time.Duration) string { 144 t.testObject.Helper() 145 ticker := time.NewTicker(500 * time.Millisecond) 146 defer ticker.Stop() 147 timer := time.NewTimer(duration) 148 defer timer.Stop() 149 150 appURI := fmt.Sprintf("http://%s", h.RegistryHost(h.DockerHostname(t.testObject), t.hostPort())) 151 for { 152 select { 153 case <-ticker.C: 154 resp, err := h.HTTPGetE(appURI, map[string]string{}) 155 if err != nil { 156 break 157 } 158 return resp 159 case <-timer.C: 160 t.testObject.Fatalf("timeout waiting for response: %v", duration) 161 } 162 } 163 } 164 165 func (t TestContainer) hostPort() string { 166 t.testObject.Helper() 167 i, err := t.dockerCli.ContainerInspect(context.Background(), t.name) 168 t.assert.Nil(err) 169 for _, port := range i.NetworkSettings.Ports { 170 for _, binding := range port { 171 return binding.HostPort 172 } 173 } 174 175 t.testObject.Fatalf("Failed to fetch host port for %s: no ports exposed", t.name) 176 return "" 177 }