|
1 | 1 | package framework |
2 | 2 |
|
3 | 3 | import ( |
| 4 | + "archive/tar" |
| 5 | + "bytes" |
4 | 6 | "context" |
5 | 7 | "errors" |
6 | 8 | "fmt" |
| 9 | + "github.com/docker/docker/api/types/container" |
7 | 10 | "github.com/docker/docker/client" |
8 | 11 | "github.com/docker/go-connections/nat" |
9 | 12 | "github.com/google/uuid" |
10 | 13 | tc "github.com/testcontainers/testcontainers-go" |
| 14 | + "io" |
11 | 15 | "os" |
12 | 16 | "os/exec" |
13 | 17 | "strings" |
@@ -132,3 +136,86 @@ func RebuildDockerImage(once *sync.Once, dockerfile string, buildContext string, |
132 | 136 | } |
133 | 137 | return fmt.Sprintf("localhost:5050/%s:latest", imageName), nil |
134 | 138 | } |
| 139 | + |
| 140 | +// DockerClient wraps a Docker API client and provides convenience methods |
| 141 | +type DockerClient struct { |
| 142 | + cli *client.Client |
| 143 | +} |
| 144 | + |
| 145 | +// NewDockerClient creates a new instance of DockerClient |
| 146 | +func NewDockerClient() (*DockerClient, error) { |
| 147 | + cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) |
| 148 | + if err != nil { |
| 149 | + return nil, fmt.Errorf("failed to create Docker client: %w", err) |
| 150 | + } |
| 151 | + return &DockerClient{cli: cli}, nil |
| 152 | +} |
| 153 | + |
| 154 | +// CopyFile copies a file into a container by name |
| 155 | +func (dc *DockerClient) CopyFile(containerName, sourceFile, targetPath string) error { |
| 156 | + ctx := context.Background() |
| 157 | + containerID, err := dc.findContainerIDByName(ctx, containerName) |
| 158 | + if err != nil { |
| 159 | + return fmt.Errorf("failed to find container ID by name: %s", containerName) |
| 160 | + } |
| 161 | + return dc.copyToContainer(containerID, sourceFile, targetPath) |
| 162 | +} |
| 163 | + |
| 164 | +// findContainerIDByName finds a container ID by its name |
| 165 | +func (dc *DockerClient) findContainerIDByName(ctx context.Context, containerName string) (string, error) { |
| 166 | + containers, err := dc.cli.ContainerList(ctx, container.ListOptions{ |
| 167 | + All: true, |
| 168 | + }) |
| 169 | + if err != nil { |
| 170 | + return "", fmt.Errorf("failed to list containers: %w", err) |
| 171 | + } |
| 172 | + for _, c := range containers { |
| 173 | + for _, name := range c.Names { |
| 174 | + if name == "/"+containerName { |
| 175 | + return c.ID, nil |
| 176 | + } |
| 177 | + } |
| 178 | + } |
| 179 | + return "", fmt.Errorf("container with name %s not found", containerName) |
| 180 | +} |
| 181 | + |
| 182 | +// copyToContainer copies a file into a container |
| 183 | +func (dc *DockerClient) copyToContainer(containerID, sourceFile, targetPath string) error { |
| 184 | + ctx := context.Background() |
| 185 | + src, err := os.Open(sourceFile) |
| 186 | + if err != nil { |
| 187 | + return fmt.Errorf("could not open source file: %w", err) |
| 188 | + } |
| 189 | + defer src.Close() |
| 190 | + |
| 191 | + // Create a tar archive containing the file |
| 192 | + var buf bytes.Buffer |
| 193 | + tw := tar.NewWriter(&buf) |
| 194 | + info, err := src.Stat() |
| 195 | + if err != nil { |
| 196 | + return fmt.Errorf("could not stat source file: %w", err) |
| 197 | + } |
| 198 | + |
| 199 | + // Add file to tar |
| 200 | + header := &tar.Header{ |
| 201 | + Name: info.Name(), |
| 202 | + Size: info.Size(), |
| 203 | + Mode: int64(info.Mode()), |
| 204 | + } |
| 205 | + if err := tw.WriteHeader(header); err != nil { |
| 206 | + return fmt.Errorf("could not write tar header: %w", err) |
| 207 | + } |
| 208 | + if _, err := io.Copy(tw, src); err != nil { |
| 209 | + return fmt.Errorf("could not write file to tar archive: %w", err) |
| 210 | + } |
| 211 | + tw.Close() |
| 212 | + |
| 213 | + // Copy the tar archive to the container |
| 214 | + err = dc.cli.CopyToContainer(ctx, containerID, targetPath, &buf, container.CopyToContainerOptions{ |
| 215 | + AllowOverwriteDirWithFile: true, |
| 216 | + }) |
| 217 | + if err != nil { |
| 218 | + return fmt.Errorf("could not copy file to container: %w", err) |
| 219 | + } |
| 220 | + return nil |
| 221 | +} |
0 commit comments