|  | @@ -58,9 +58,10 @@ type DryRunKey struct{}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  // DryRunClient implements APIClient by delegating to implementation functions. This allows lazy init and per-method overrides
 | 
	
		
			
				|  |  |  type DryRunClient struct {
 | 
	
		
			
				|  |  | -	apiClient client.APIClient
 | 
	
		
			
				|  |  | -	execs     sync.Map
 | 
	
		
			
				|  |  | -	resolver  *imagetools.Resolver
 | 
	
		
			
				|  |  | +	apiClient  client.APIClient
 | 
	
		
			
				|  |  | +	containers []moby.Container
 | 
	
		
			
				|  |  | +	execs      sync.Map
 | 
	
		
			
				|  |  | +	resolver   *imagetools.Resolver
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  type execDetails struct {
 | 
	
	
		
			
				|  | @@ -79,9 +80,10 @@ func NewDryRunClient(apiClient client.APIClient, cli *command.DockerCli) (*DryRu
 | 
	
		
			
				|  |  |  		return nil, err
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  	return &DryRunClient{
 | 
	
		
			
				|  |  | -		apiClient: apiClient,
 | 
	
		
			
				|  |  | -		execs:     sync.Map{},
 | 
	
		
			
				|  |  | -		resolver:  imagetools.New(configFile),
 | 
	
		
			
				|  |  | +		apiClient:  apiClient,
 | 
	
		
			
				|  |  | +		containers: []moby.Container{},
 | 
	
		
			
				|  |  | +		execs:      sync.Map{},
 | 
	
		
			
				|  |  | +		resolver:   imagetools.New(configFile),
 | 
	
		
			
				|  |  |  	}, nil
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -99,15 +101,36 @@ func (d *DryRunClient) ContainerAttach(ctx context.Context, container string, op
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  func (d *DryRunClient) ContainerCreate(ctx context.Context, config *containerType.Config, hostConfig *containerType.HostConfig,
 | 
	
		
			
				|  |  |  	networkingConfig *network.NetworkingConfig, platform *specs.Platform, containerName string) (containerType.CreateResponse, error) {
 | 
	
		
			
				|  |  | -	return containerType.CreateResponse{ID: "dryRunId"}, nil
 | 
	
		
			
				|  |  | +	d.containers = append(d.containers, moby.Container{
 | 
	
		
			
				|  |  | +		ID:     containerName,
 | 
	
		
			
				|  |  | +		Names:  []string{containerName},
 | 
	
		
			
				|  |  | +		Labels: config.Labels,
 | 
	
		
			
				|  |  | +		HostConfig: struct {
 | 
	
		
			
				|  |  | +			NetworkMode string `json:",omitempty"`
 | 
	
		
			
				|  |  | +		}{},
 | 
	
		
			
				|  |  | +	})
 | 
	
		
			
				|  |  | +	return containerType.CreateResponse{ID: containerName}, nil
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  func (d *DryRunClient) ContainerInspect(ctx context.Context, container string) (moby.ContainerJSON, error) {
 | 
	
		
			
				|  |  |  	containerJSON, err := d.apiClient.ContainerInspect(ctx, container)
 | 
	
		
			
				|  |  |  	if err != nil {
 | 
	
		
			
				|  |  | +		id := "dryRunId"
 | 
	
		
			
				|  |  | +		for _, c := range d.containers {
 | 
	
		
			
				|  |  | +			if c.ID == container {
 | 
	
		
			
				|  |  | +				id = container
 | 
	
		
			
				|  |  | +			}
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  |  		return moby.ContainerJSON{
 | 
	
		
			
				|  |  |  			ContainerJSONBase: &moby.ContainerJSONBase{
 | 
	
		
			
				|  |  | -				ID: "dryRunId",
 | 
	
		
			
				|  |  | +				ID:   id,
 | 
	
		
			
				|  |  | +				Name: container,
 | 
	
		
			
				|  |  | +				State: &moby.ContainerState{
 | 
	
		
			
				|  |  | +					Status: "running", // needed for --wait option
 | 
	
		
			
				|  |  | +					Health: &moby.Health{
 | 
	
		
			
				|  |  | +						Status: moby.Healthy, // needed for healthcheck control
 | 
	
		
			
				|  |  | +					},
 | 
	
		
			
				|  |  | +				},
 | 
	
		
			
				|  |  |  			},
 | 
	
		
			
				|  |  |  			Mounts:          nil,
 | 
	
		
			
				|  |  |  			Config:          &containerType.Config{},
 | 
	
	
		
			
				|  | @@ -121,6 +144,21 @@ func (d *DryRunClient) ContainerKill(ctx context.Context, container, signal stri
 | 
	
		
			
				|  |  |  	return nil
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +func (d *DryRunClient) ContainerList(ctx context.Context, options moby.ContainerListOptions) ([]moby.Container, error) {
 | 
	
		
			
				|  |  | +	caller := getCallingFunction()
 | 
	
		
			
				|  |  | +	switch caller {
 | 
	
		
			
				|  |  | +	case "start":
 | 
	
		
			
				|  |  | +		return d.containers, nil
 | 
	
		
			
				|  |  | +	case "getContainers":
 | 
	
		
			
				|  |  | +		if len(d.containers) == 0 {
 | 
	
		
			
				|  |  | +			var err error
 | 
	
		
			
				|  |  | +			d.containers, err = d.apiClient.ContainerList(ctx, options)
 | 
	
		
			
				|  |  | +			return d.containers, err
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +	return d.apiClient.ContainerList(ctx, options)
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  func (d *DryRunClient) ContainerPause(ctx context.Context, container string) error {
 | 
	
		
			
				|  |  |  	return nil
 | 
	
		
			
				|  |  |  }
 | 
	
	
		
			
				|  | @@ -246,7 +284,13 @@ func (d *DryRunClient) NetworkRemove(ctx context.Context, networkName string) er
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  func (d *DryRunClient) VolumeCreate(ctx context.Context, options volume.CreateOptions) (volume.Volume, error) {
 | 
	
		
			
				|  |  | -	return volume.Volume{}, ErrNotImplemented
 | 
	
		
			
				|  |  | +	return volume.Volume{
 | 
	
		
			
				|  |  | +		ClusterVolume: nil,
 | 
	
		
			
				|  |  | +		Driver:        options.Driver,
 | 
	
		
			
				|  |  | +		Labels:        options.Labels,
 | 
	
		
			
				|  |  | +		Name:          options.Name,
 | 
	
		
			
				|  |  | +		Options:       options.DriverOpts,
 | 
	
		
			
				|  |  | +	}, nil
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  func (d *DryRunClient) VolumeRemove(ctx context.Context, volumeID string, force bool) error {
 | 
	
	
		
			
				|  | @@ -324,10 +368,6 @@ func (d *DryRunClient) ContainerInspectWithRaw(ctx context.Context, container st
 | 
	
		
			
				|  |  |  	return d.apiClient.ContainerInspectWithRaw(ctx, container, getSize)
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -func (d *DryRunClient) ContainerList(ctx context.Context, options moby.ContainerListOptions) ([]moby.Container, error) {
 | 
	
		
			
				|  |  | -	return d.apiClient.ContainerList(ctx, options)
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  func (d *DryRunClient) ContainerLogs(ctx context.Context, container string, options moby.ContainerLogsOptions) (io.ReadCloser, error) {
 | 
	
		
			
				|  |  |  	return d.apiClient.ContainerLogs(ctx, container, options)
 | 
	
		
			
				|  |  |  }
 |