8000 Replace `docker.Xxx` helpers with functions on `command.Command` by michaeldwan · Pull Request #2288 · replicate/cog · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Replace docker.Xxx helpers with functions on command.Command #2288

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 8000 GitHub? Sign in to your account

Merged
merged 10 commits into from
May 2, 2025

Conversation

michaeldwan
Copy link
Member
@michaeldwan michaeldwan commented Apr 29, 2025

The TLDR is:

  1. Consolidate package functions that shell out to the docker CLI into functions on the docker.DockerClient struct
  2. Add them to the command.Command interface (which'll get renamed to something like docker.Client shortly) so I can add the direct engine client without changing build logic
  3. Upgrade github.com/docker/docker and github.com/docker/cli packages. Unfortunately there was an irreconcilable conflict with a far flung goreleaser dependency, so I removed it from go tools.
  4. add integration tests for the docker client that directly hit a docker daemon and registry.

Since this one is big (though mostly benign) I split each logical chunk into a commit for easier review.

This PR moves the following operations to command.Command:

  • Inspect
  • ContainerInspect
  • ContainerStop
  • ContainerLogs
  • Pull

I'll knock the chonky ones out in subsequent PRs, like Build and Run.

@michaeldwan michaeldwan force-pushed the md/docker-client branch 2 times, most recently from 8ff9f08 to 9bf34df Compare April 29, 2025 22:22
DockerCommand.exec will write the underlying command stdout and stderr to the provided io.Writer. This allows callers to either capture the entire output or allow long running commands to stream output to a writer that isn't os.Stdout or os.Stderr
github.com/docker/docker needed an upgrade, but this wasn't compatible with a dependency of goreleaser, so I removed it from go tools
…ation

Several helper functions in the `docker` package (`ImageInspect`, `ImageExists`, `ContainerInspect`, `ContainerLogsFollow`, and `Pull`) invisibly shelled out to the docker CLI, often with slightly different logic than was the `DockerCommand` struct was doing.

This PR moves them to functions on the `DockerCommand` struct as well as adds them to the `command.Command` interface so they can be swapped out with the upcoming engine client.
@michaeldwan michaeldwan changed the title WIP: Replace docker.Xxx helpers with functions on command.Command Replace docker.Xxx helpers with functions on command.Command Apr 30, 2025
test harness for running integration tests against an actual docker daemon and local registry
different errors are returned when working with a docker registry and OCI registry. This maps both of them to the not found error
@michaeldwan michaeldwan marked this pull request as ready for review May 2, 2025 16:02
@michaeldwan michaeldwan requested review from Copilot and a team May 2, 2025 16:05
Copy link
Contributor
@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR migrates legacy docker helper functions into methods on the command.Command interface and updates their usage throughout the codebase. Key changes include:

  • Consolidating docker CLI calls into the DockerCommand type and updating the Command interface.
  • Removing legacy functions (e.g. Stop, Pull, Logs, Inspect, ImageExists, ContainerInspect) from the docker package.
  • Updating usage in the CLI commands (train and predict) and test suites to leverage the new DockerCommand methods.

Reviewed Changes

Copilot reviewed 21 out of 24 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
pkg/image/openapi_schema.go Updated GetOpenAPISchema to use a dockerClient parameter and manifest data.
pkg/image/config.go Renamed config function and updated error messages with friendly names.
pkg/docker/stop.go, pkg/docker/pull.go, pkg/docker/logs.go, pkg/docker/image_inspect.go, pkg/docker/image_exists.go Removed legacy implementations.
pkg/docker/dockertest/mock_command.go Updated Inspect signature and added stubs for other methods.
pkg/docker/docker_command.go Consolidated docker CLI commands into DockerCommand methods with enhanced debug logging and error wrapping.
pkg/docker/command/errors.go & pkg/docker/command/command.go Introduced NotFoundError and updated the Command interface methods.
pkg/cli/train.go & pkg/cli/predict.go Updated to use DockerCommand; integrated error wrapping for image inspection.
pkg/docker/docker_client_test.go Updated tests to work with the new DockerCommand implementations.
Files not reviewed (3)
  • Makefile: Language not supported
  • go.mod: Language not supported
  • pkg/docker/dockertest/testdata/create-image-fixtures.sh: Language not supported

@@ -112,17 +115,18 @@ func cmdPredict(cmd *cobra.Command, args []string) error {
return fmt.Errorf("Invalid image name '%s'. Did you forget `-i`?", imageName)
}

exists, err := docker.ImageExists(ctx, imageName)
manifest, err := dockerCommand.Inspect(ctx, imageName)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a quicker way to get an existance check than an inspect call here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes! command.Command.ImageExists.

Though I just pushed up a fix to the copilot issue that added an inspect step to pull that'll replace the need to do repeated inspect calls. Now pull will always return an inspect response, and there's an option to either use it or fetch and return the updated inspect response via the force flag.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just realized you reviewed before I pushed up the changes to Pull that I mentioned. Here's the commit if you're curious: 9e0b967

There's a few places in the code where we check for a local image, and if not found begin a pull, then carry on. I had a bug that allowed pull failures to be swallowed and stale inspect responses to be passed to predict+train.

This fixes the issue by ensuring that Pull returns the inspect response of the image that was just pulled, or to skip pulling if the image already exists using a force flag.
@michaeldwan michaeldwan requested a review from Copilot May 2, 2025 17:42
Copy link
Contributor
@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR refactors Docker CLI helper functions by migrating them to methods on the command.Command interface, while consolidating operations (Inspect, ContainerInspect, ContainerStop, ContainerLogs, and Pull) into a unified client. Key changes include replacing direct calls to docker.Xxx helpers with command.Command methods, updating method signatures to return enriched responses, and removing legacy docker package files.

Reviewed Changes

Copilot reviewed 22 out of 25 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
pkg/image/config.go Updates GetConfig to CogConfigFromManifest and error message tweaks
pkg/dockerfile/fast_generator.go Adjusted Pull call to include a force flag and expect an inspect response
pkg/docker/* (various files) Removed legacy docker helper files, consolidating functionality
pkg/docker/dockertest/mock_command.go Updated mock interface with new signatures and non-implemented stubs
pkg/docker/docker_command.go Refactored methods (Pull, Inspect, ContainerStop, etc.) with enhanced logging and error handling
pkg/cli/train.go & pkg/cli/predict.go Updated usage of docker client methods to align with new signatures
Files not reviewed (3)
  • Makefile: Language not supported
  • go.mod: Language not supported
  • pkg/docker/dockertest/testdata/create-image-fixtures.sh: Language not supported
Comments suppressed due to low confidence (1)

pkg/docker/dockertest/mock_command.go:81

  • [nitpick] In the mock implementations, instead of using panic for unimplemented methods (e.g. ImageExists, ContainerLogs, etc.), consider returning a descriptive error to avoid abrupt test failures if these paths are inadvertently invoked.
func (c *MockCommand) ImageExists(ctx context.Context, ref string) (bool, error) { panic("not implemented") }

Comment on lines +21 to +42
// TODO[md]: find the tag/ref and return that in the error instead of the ID
return nil, fmt.Errorf("Image %s does not appear to be a Cog model", friendlyName(manifest))
}
conf := new(config.Config)
if err := json.Unmarshal([]byte(configString), conf); err != nil {
return nil, fmt.Errorf("Failed to parse config from %s: %w", imageName, err)
// TODO[md]: find the tag/ref and return that in the error instead of the ID
return nil, fmt.Errorf("Failed to parse config from %s: %w", friendlyName(manifest), err)
}
return conf, nil
}

func friendlyName(manifest *image.InspectResponse) string {
// this appears to get the base image name, which we don't really want
// name := manifest.Config.Labels["org.opencontainers.image.title"]
// if name != "" {
// return name
// }

if len(manifest.RepoTags) > 0 {
return manifest.RepoTags[0]
}

Copy link
Preview
Copilot AI May 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider updating the error message to include a more descriptive tag or reference (instead of relying solely on friendlyName) once that information is available. Removing the TODO comments when this is addressed will improve clarity in error reporting.

Copilot uses AI. Check for mistakes.

return "", err
}

return aptTarFile, nil
}

func (c *DockerCommand) Inspect(ctx context.Context, image string) (*command.Manifest, error) {
func (c *DockerCommand) Inspect(ctx context.Context, ref string) (*image.InspectResponse, error) {
console.Debugf("=== DockerCommand.Inspect %s", ref)
Copy link
Preview
Copilot AI May 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The Inspect method logs the debug information using a nearly identical message both before executing and after capturing output, which could be confusing. Consider differentiating the log messages (for example, one for the input reference and another for the returned output) to improve traceability.

Suggested change
console.Debugf("=== DockerCommand.Inspect %s", ref)
console.Debugf("=== DockerCommand.Inspect: Inspecting reference %s", ref)

Copilot uses AI. Check for mistakes.

@michaeldwan michaeldwan merged commit 28411cf into main May 2, 2025
21 checks passed
@michaeldwan michaeldwan deleted the md/docker-client branch May 2, 2025 17:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants
0