Skip to content

fix: use docker cli client everywhere #43

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 16, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions wfsm/internal/builder/python/image_build.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,15 +81,15 @@ func EnsureContainerImage(ctx context.Context, img string, src source.AgentSourc
hashCode := calculateHash(workspacePath, baseImage)
img = fmt.Sprintf("%s:%s", img, hashCode)

client, err := dockerclient.NewClientWithOpts(dockerclient.FromEnv, dockerclient.WithAPIVersionNegotiation())
dockerCli, err := util.GetDockerCLI(ctx)
if err != nil {
return "", fmt.Errorf("failed to create runtime client: %w", err)
return "", fmt.Errorf("failed to initialize docker client: %v", err)
}
defer containerclient.Close(ctx, client)
defer dockerCli.Client().Close()

// check if image already exists unless forceBuild is set
if !forceBuild {
found, err := findImage(ctx, client, img)
found, err := findImage(ctx, dockerCli.Client(), img)
if err != nil {
return "", err
}
Expand All @@ -100,14 +100,14 @@ func EnsureContainerImage(ctx context.Context, img string, src source.AgentSourc
}

// find base image and pull it if not found
found, err := findImage(ctx, client, baseImage)
found, err := findImage(ctx, dockerCli.Client(), baseImage)
if err != nil {
return "", err
}
if !found {
log.Info().Str("image", baseImage).Msg("base image not found on container runtime host")
// image not available locally, see if it can be pulled from registry
err = pullImage(ctx, client, baseImage)
err = pullImage(ctx, dockerCli.Client(), baseImage)
if err != nil {
if !errdefs.IsNotFound(err) {
return "", fmt.Errorf("base image not found %s: %w", baseImage, err)
Expand All @@ -117,15 +117,15 @@ func EnsureContainerImage(ctx context.Context, img string, src source.AgentSourc
}

// build image
err = buildImage(ctx, client, img, workspacePath, inputSpec, agentSourceDir, assets.AgentBuilderDockerfile, baseImage)
err = buildImage(ctx, dockerCli.Client(), img, workspacePath, inputSpec, agentSourceDir, assets.AgentBuilderDockerfile, baseImage)
if err != nil {
return "", fmt.Errorf("failed to build image %s: %w", img, err)
}

return img, nil
}

func findImage(ctx context.Context, client *dockerclient.Client, img string) (bool, error) {
func findImage(ctx context.Context, client dockerclient.ImageAPIClient, img string) (bool, error) {
log := zerolog.Ctx(ctx)
imageList, err := client.ImageList(ctx, image.ListOptions{
Filters: filters.NewArgs(filters.KeyValuePair{
Expand All @@ -148,7 +148,7 @@ func findImage(ctx context.Context, client *dockerclient.Client, img string) (bo
return false, nil
}

func buildImage(ctx context.Context, client *dockerclient.Client, img string, workspacePath string, inputSpec internal.AgentSpec, agentSourceDir string, dockerFile []byte, baseImage string) error {
func buildImage(ctx context.Context, client dockerclient.ImageAPIClient, img string, workspacePath string, inputSpec internal.AgentSpec, agentSourceDir string, dockerFile []byte, baseImage string) error {
log := zerolog.Ctx(ctx)
log.Info().Str("image", img).Msg("building image")

Expand Down Expand Up @@ -220,7 +220,7 @@ func buildImage(ctx context.Context, client *dockerclient.Client, img string, wo
return nil
}

func pullImage(ctx context.Context, client *dockerclient.Client, img string) error {
func pullImage(ctx context.Context, client dockerclient.ImageAPIClient, img string) error {
log := zerolog.Ctx(ctx)
log.Info().Msgf("pulling image: %s", img)

Expand Down
88 changes: 2 additions & 86 deletions wfsm/internal/container_client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import (
dockerclient "github.com/docker/docker/client"
"github.com/docker/docker/pkg/archive"
"github.com/docker/docker/pkg/idtools"
imagespecv1 "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/rs/zerolog"
)

Expand All @@ -24,52 +23,16 @@ func CreateBuildContext(path string) (io.ReadCloser, error) {
})
}

func Close(ctx context.Context, client *dockerclient.Client) {
log := zerolog.Ctx(ctx)

if err := client.Close(); err != nil {
log.Error().Err(err).Msg("failed to close container_client runtime client")
}
log.Debug().Msg("closed container_client runtime client")
}

func CreateContainer(
ctx context.Context,
client *dockerclient.Client,
containerConfig *container.Config,
hostConfig *container.HostConfig,
platform *imagespecv1.Platform,
containerName string) (string, error) {
log := zerolog.Ctx(ctx).With().Str("container_name", containerName).Logger()

createResp, err := client.ContainerCreate(
ctx, containerConfig,
hostConfig,
nil,
platform,
containerName)
if err != nil {
return "", fmt.Errorf("failed to create container_client: %w", err)
}

if len(createResp.Warnings) == 0 {
log.Debug().Msg("created container_client")
} else {
log.Warn().Strs("warnings", createResp.Warnings).Msg("created container_client with warnings")
}
return createResp.ID, nil
}

// if the container is running, return the public port or 0 otherwise
func IsContainerRunning(
ctx context.Context,
client *dockerclient.Client,
cntClient dockerclient.ContainerAPIClient,
image string,
containerName string) (int, error) {

log := zerolog.Ctx(ctx).With().Str("container_name", containerName).Logger()

cList, err := client.ContainerList(ctx, container.ListOptions{
cList, err := cntClient.ContainerList(ctx, container.ListOptions{
All: true,
Filters: filters.NewArgs(filters.KeyValuePair{
Key: "name",
Expand Down Expand Up @@ -106,50 +69,3 @@ func getPublicPort(ports []container.Port) int {
}
return 0
}

func RemoveContainer(ctx context.Context, client *dockerclient.Client, containerID string) error {
log := zerolog.Ctx(ctx)

err := client.ContainerRemove(ctx, containerID, container.RemoveOptions{RemoveVolumes: true})
if err != nil {
return err
}
log.Debug().Msg("removed container_client")
return nil
}

func StartContainer(
ctx context.Context,
client *dockerclient.Client,
containerID string) error {
log := zerolog.Ctx(ctx)

err := client.ContainerStart(ctx, containerID, container.StartOptions{})
if err != nil {
return fmt.Errorf("failed to start container_client: %w", err)
}
log.Debug().Msg("started container_client")

return nil
}

func CopyToContainer(ctx context.Context, client *dockerclient.Client, containerID, src, dst string) error {
log := zerolog.Ctx(ctx)

appSrc, err := archive.Tar(src, archive.Uncompressed)
if err != nil {
return fmt.Errorf("failed to tar source dir: %w", err)
}
defer func() {
if err = appSrc.Close(); err != nil {
log.Error().Err(err).Msg("failed to close archived source reader")
}
}()

err = client.CopyToContainer(ctx, containerID, dst, appSrc, container.CopyToContainerOptions{})
if err != nil {
return fmt.Errorf("failed to archive to container_client: %w", err)
}

return nil
}
34 changes: 6 additions & 28 deletions wfsm/internal/platforms/docker_compose/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ import (
containerClient "github.com/cisco-eti/wfsm/internal/container_client"
"github.com/cisco-eti/wfsm/internal/util"
"github.com/compose-spec/compose-go/v2/types"
"github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/flags"
"github.com/docker/compose/v2/cmd/formatter"
"github.com/docker/compose/v2/pkg/api"
dockerClient "github.com/docker/docker/client"
Expand Down Expand Up @@ -52,11 +50,11 @@ func (r *runner) Deploy(ctx context.Context,
}
}

cli, err := dockerClient.NewClientWithOpts(dockerClient.FromEnv, dockerClient.WithAPIVersionNegotiation())
dockerCli, err := util.GetDockerCLI(ctx)
if err != nil {
return nil, fmt.Errorf("failed to create docker client: %v", err)
return nil, fmt.Errorf("failed to initialize docker client: %v", err)
}
defer containerClient.Close(ctx, cli)
defer dockerCli.Client().Close()

project := &types.Project{
Name: mainAgentName,
Expand All @@ -68,7 +66,7 @@ func (r *runner) Deploy(ctx context.Context,

port := externalPort
if port == 0 {
port, err = r.getMainAgentPublicPort(ctx, cli, mainAgentName, mainAgentSpec)
port, err = r.getMainAgentPublicPort(ctx, dockerCli.Client(), mainAgentName, mainAgentSpec)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -97,12 +95,6 @@ func (r *runner) Deploy(ctx context.Context,
project.Services[deploymentSpec.ServiceName] = *sc
}

dockerCli, err := getDockerCLI(ctx)
if err != nil {
return nil, fmt.Errorf("failed to initialize docker client: %v", err)
}
defer dockerCli.Client().Close()

composeFilePath := path.Join(r.hostStorageFolder, fmt.Sprintf("compose-%s.yaml", mainAgentName))
prjOpts := cmdcmp.ProjectOptions{
ConfigPaths: []string{
Expand Down Expand Up @@ -167,11 +159,11 @@ func calculateEnvVarPrefix(agName string) string {
return prefix + "_"
}

func (r *runner) getMainAgentPublicPort(ctx context.Context, cli *dockerClient.Client, mainAgentName string, mainAgentSpec internal.AgentDeploymentBuildSpec) (int, error) {
func (r *runner) getMainAgentPublicPort(ctx context.Context, cntClient dockerClient.ContainerAPIClient, mainAgentName string, mainAgentSpec internal.AgentDeploymentBuildSpec) (int, error) {
log := zerolog.Ctx(ctx)

containerName := strings.Join([]string{mainAgentName, mainAgentSpec.DeploymentName}, "-")
port, err := containerClient.IsContainerRunning(ctx, cli, mainAgentSpec.Image, containerName)
port, err := containerClient.IsContainerRunning(ctx, cntClient, mainAgentSpec.Image, containerName)
if err != nil {
return 0, fmt.Errorf("failed to check if agent is running: %v", err)
}
Expand Down Expand Up @@ -226,20 +218,6 @@ func (r *runner) createServiceConfig(projectName string, deploymentSpec internal
return &sc, nil
}

func getDockerCLI(ctx context.Context) (*command.DockerCli, error) {
dockerCli, err := command.NewDockerCli(command.WithBaseContext(ctx))
if err != nil {
return nil, fmt.Errorf("failed to create docker cli: %v", err)
}
clientOptions := flags.ClientOptions{
LogLevel: "debug",
TLS: false,
TLSVerify: false,
}
err = dockerCli.Initialize(&clientOptions)
return dockerCli, err
}

func getStringPtr(s string) *string {
return &s
}
Expand Down
7 changes: 4 additions & 3 deletions wfsm/internal/platforms/docker_compose/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"strings"

"github.com/cisco-eti/wfsm/internal"
"github.com/cisco-eti/wfsm/internal/util"
"github.com/docker/compose/v2/cmd/formatter"
"github.com/docker/compose/v2/pkg/api"
"github.com/docker/compose/v2/pkg/compose"
Expand All @@ -28,7 +29,7 @@ func NewDockerComposeRunner(hostStorageFolder string) internal.AgentDeploymentRu
}

func (r *runner) Remove(ctx context.Context, deploymentName string) error {
dockerCli, err := getDockerCLI(ctx)
dockerCli, err := util.GetDockerCLI(ctx)
if err != nil {
return fmt.Errorf("failed to initialize docker client: %v", err)
}
Expand All @@ -47,7 +48,7 @@ func (r *runner) Remove(ctx context.Context, deploymentName string) error {
}

func (r *runner) Logs(ctx context.Context, deploymentName string, agentNames []string) error {
dockerCli, err := getDockerCLI(ctx)
dockerCli, err := util.GetDockerCLI(ctx)
if err != nil {
return fmt.Errorf("failed to initialize docker client: %v", err)
}
Expand All @@ -71,7 +72,7 @@ func (r *runner) Logs(ctx context.Context, deploymentName string, agentNames []s
func (r *runner) List(ctx context.Context, deploymentName string) error {
log := zerolog.Ctx(ctx)

dockerCli, err := getDockerCLI(ctx)
dockerCli, err := util.GetDockerCLI(ctx)
if err != nil {
return fmt.Errorf("failed to initialize docker client: %v", err)
}
Expand Down
18 changes: 18 additions & 0 deletions wfsm/internal/util/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,14 @@
package util

import (
"context"
"fmt"
"net"
"os/user"
"runtime"

"github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/flags"
)

const OwnerCanReadWrite = 0777
Expand Down Expand Up @@ -39,3 +43,17 @@ func GetHomeDir() (string, error) {
}
return usr.HomeDir, nil
}

func GetDockerCLI(ctx context.Context) (*command.DockerCli, error) {
dockerCli, err := command.NewDockerCli(command.WithBaseContext(ctx))
if err != nil {
return nil, fmt.Errorf("failed to create docker cli: %v", err)
}
clientOptions := flags.ClientOptions{
LogLevel: "debug",
TLS: false,
TLSVerify: false,
}
err = dockerCli.Initialize(&clientOptions)
return dockerCli, err
}
Loading