github.com/openshift/source-to-image@v1.4.1-0.20240516041539-bf52fc02204e/pkg/docker/test/client.go (about) 1 package test 2 3 import ( 4 "bufio" 5 "bytes" 6 "errors" 7 "fmt" 8 "io" 9 "io/ioutil" 10 "net" 11 "time" 12 13 dockertypes "github.com/docker/docker/api/types" 14 dockercontainer "github.com/docker/docker/api/types/container" 15 dockernetwork "github.com/docker/docker/api/types/network" 16 v1 "github.com/opencontainers/image-spec/specs-go/v1" 17 "golang.org/x/net/context" 18 ) 19 20 // FakeConn fakes a net.Conn 21 type FakeConn struct { 22 } 23 24 // Read reads bytes 25 func (c FakeConn) Read(b []byte) (n int, err error) { 26 return 0, nil 27 } 28 29 // Write writes bytes 30 func (c FakeConn) Write(b []byte) (n int, err error) { 31 return 0, nil 32 } 33 34 // Close closes the connection 35 func (c FakeConn) Close() error { 36 return nil 37 } 38 39 // LocalAddr returns the local address 40 func (c FakeConn) LocalAddr() net.Addr { 41 ip, _ := net.ResolveIPAddr("ip4", "127.0.0.1") 42 return ip 43 } 44 45 // RemoteAddr returns the remote address 46 func (c FakeConn) RemoteAddr() net.Addr { 47 ip, _ := net.ResolveIPAddr("ip4", "127.0.0.1") 48 return ip 49 } 50 51 // SetDeadline sets the deadline 52 func (c FakeConn) SetDeadline(t time.Time) error { 53 return nil 54 } 55 56 // SetReadDeadline sets the read deadline 57 func (c FakeConn) SetReadDeadline(t time.Time) error { 58 return nil 59 } 60 61 // SetWriteDeadline sets the write deadline 62 func (c FakeConn) SetWriteDeadline(t time.Time) error { 63 return nil 64 } 65 66 // FakeDockerClient provides a Fake client for Docker testing 67 type FakeDockerClient struct { 68 CopyToContainerID string 69 CopyToContainerPath string 70 CopyToContainerContent io.Reader 71 72 CopyFromContainerID string 73 CopyFromContainerPath string 74 CopyFromContainerErr error 75 76 WaitContainerID string 77 WaitContainerResult int 78 WaitContainerErr error 79 WaitContainerErrInspectJSON dockertypes.ContainerJSON 80 81 ContainerCommitID string 82 ContainerCommitOptions dockertypes.ContainerCommitOptions 83 ContainerCommitResponse dockertypes.IDResponse 84 ContainerCommitErr error 85 86 BuildImageOpts dockertypes.ImageBuildOptions 87 BuildImageErr error 88 Images map[string]dockertypes.ImageInspect 89 90 Containers map[string]dockercontainer.Config 91 92 PullFail error 93 94 Calls []string 95 } 96 97 // NewFakeDockerClient returns a new FakeDockerClient 98 func NewFakeDockerClient() *FakeDockerClient { 99 return &FakeDockerClient{ 100 Images: make(map[string]dockertypes.ImageInspect), 101 Containers: make(map[string]dockercontainer.Config), 102 Calls: make([]string, 0), 103 } 104 } 105 106 // ImageInspectWithRaw returns the image information and its raw representation. 107 func (d *FakeDockerClient) ImageInspectWithRaw(ctx context.Context, imageID string) (dockertypes.ImageInspect, []byte, error) { 108 d.Calls = append(d.Calls, "inspect_image") 109 110 if _, exists := d.Images[imageID]; exists { 111 return d.Images[imageID], nil, nil 112 } 113 return dockertypes.ImageInspect{}, nil, fmt.Errorf("No such image: %q", imageID) 114 } 115 116 // CopyToContainer copies content into the container filesystem. 117 func (d *FakeDockerClient) CopyToContainer(ctx context.Context, container, path string, content io.Reader, opts dockertypes.CopyToContainerOptions) error { 118 d.CopyToContainerID = container 119 d.CopyToContainerPath = path 120 d.CopyToContainerContent = content 121 return nil 122 } 123 124 // CopyFromContainer gets the content from the container and returns it as a Reader 125 // to manipulate it in the host. It's up to the caller to close the reader. 126 func (d *FakeDockerClient) CopyFromContainer(ctx context.Context, container, srcPath string) (io.ReadCloser, dockertypes.ContainerPathStat, error) { 127 d.CopyFromContainerID = container 128 d.CopyFromContainerPath = srcPath 129 return ioutil.NopCloser(bytes.NewReader([]byte(""))), dockertypes.ContainerPathStat{}, d.CopyFromContainerErr 130 } 131 132 // ContainerWait pauses execution until a container exits. 133 func (d *FakeDockerClient) ContainerWait(ctx context.Context, containerID string, condition dockercontainer.WaitCondition) (<-chan dockercontainer.WaitResponse, <-chan error) { 134 d.WaitContainerID = containerID 135 resultC := make(chan dockercontainer.WaitResponse) 136 errC := make(chan error, 1) 137 138 go func() { 139 if d.WaitContainerErr != nil { 140 errC <- d.WaitContainerErr 141 return 142 } 143 144 resultC <- dockercontainer.WaitResponse{StatusCode: int64(d.WaitContainerResult)} 145 }() 146 147 return resultC, errC 148 } 149 150 // ContainerCommit applies changes into a container and creates a new tagged image. 151 func (d *FakeDockerClient) ContainerCommit(ctx context.Context, container string, options dockertypes.ContainerCommitOptions) (dockertypes.IDResponse, error) { 152 d.ContainerCommitID = container 153 d.ContainerCommitOptions = options 154 return d.ContainerCommitResponse, d.ContainerCommitErr 155 } 156 157 // ContainerAttach attaches a connection to a container in the server. 158 func (d *FakeDockerClient) ContainerAttach(ctx context.Context, container string, options dockertypes.ContainerAttachOptions) (dockertypes.HijackedResponse, error) { 159 d.Calls = append(d.Calls, "attach") 160 return dockertypes.HijackedResponse{Conn: FakeConn{}, Reader: bufio.NewReader(&bytes.Buffer{})}, nil 161 } 162 163 // ImageBuild sends request to the daemon to build images. 164 func (d *FakeDockerClient) ImageBuild(ctx context.Context, buildContext io.Reader, options dockertypes.ImageBuildOptions) (dockertypes.ImageBuildResponse, error) { 165 d.BuildImageOpts = options 166 return dockertypes.ImageBuildResponse{ 167 Body: ioutil.NopCloser(bytes.NewReader([]byte(""))), 168 }, d.BuildImageErr 169 } 170 171 // ContainerCreate creates a new container based in the given configuration. 172 func (d *FakeDockerClient) ContainerCreate(ctx context.Context, config *dockercontainer.Config, hostConfig *dockercontainer.HostConfig, networkingConfig *dockernetwork.NetworkingConfig, platform *v1.Platform, containerName string) (dockercontainer.CreateResponse, error) { 173 d.Calls = append(d.Calls, "create") 174 175 d.Containers[containerName] = *config 176 return dockercontainer.CreateResponse{}, nil 177 } 178 179 // ContainerInspect returns the container information. 180 func (d *FakeDockerClient) ContainerInspect(ctx context.Context, containerID string) (dockertypes.ContainerJSON, error) { 181 d.Calls = append(d.Calls, "inspect_container") 182 return d.WaitContainerErrInspectJSON, nil 183 } 184 185 // ContainerRemove kills and removes a container from the docker host. 186 func (d *FakeDockerClient) ContainerRemove(ctx context.Context, containerID string, options dockertypes.ContainerRemoveOptions) error { 187 d.Calls = append(d.Calls, "remove") 188 189 if _, exists := d.Containers[containerID]; exists { 190 delete(d.Containers, containerID) 191 return nil 192 } 193 return errors.New("container does not exist") 194 } 195 196 // ContainerKill terminates the container process but does not remove the container from the docker host. 197 func (d *FakeDockerClient) ContainerKill(ctx context.Context, containerID, signal string) error { 198 return nil 199 } 200 201 // ContainerStart sends a request to the docker daemon to start a container. 202 func (d *FakeDockerClient) ContainerStart(ctx context.Context, containerID string, options dockertypes.ContainerStartOptions) error { 203 d.Calls = append(d.Calls, "start") 204 return nil 205 } 206 207 // ImagePull requests the docker host to pull an image from a remote registry. 208 func (d *FakeDockerClient) ImagePull(ctx context.Context, ref string, options dockertypes.ImagePullOptions) (io.ReadCloser, error) { 209 d.Calls = append(d.Calls, "pull") 210 211 if d.PullFail != nil { 212 return nil, d.PullFail 213 } 214 215 return ioutil.NopCloser(bytes.NewReader([]byte{})), nil 216 } 217 218 // ImageRemove removes an image from the docker host. 219 func (d *FakeDockerClient) ImageRemove(ctx context.Context, imageID string, options dockertypes.ImageRemoveOptions) ([]dockertypes.ImageDeleteResponseItem, error) { 220 d.Calls = append(d.Calls, "remove_image") 221 222 if _, exists := d.Images[imageID]; exists { 223 delete(d.Images, imageID) 224 return []dockertypes.ImageDeleteResponseItem{}, nil 225 } 226 return []dockertypes.ImageDeleteResponseItem{}, errors.New("image does not exist") 227 } 228 229 // ServerVersion returns information of the docker client and server host. 230 func (d *FakeDockerClient) ServerVersion(ctx context.Context) (dockertypes.Version, error) { 231 return dockertypes.Version{}, nil 232 }