diff --git a/cmd/ctr/commands/containers/containers.go b/cmd/ctr/commands/containers/containers.go index 9e40b6aa7..fa0201064 100644 --- a/cmd/ctr/commands/containers/containers.go +++ b/cmd/ctr/commands/containers/containers.go @@ -124,7 +124,7 @@ var listCommand = cli.Command{ w := tabwriter.NewWriter(os.Stdout, 4, 8, 4, ' ', 0) fmt.Fprintln(w, "CONTAINER\tIMAGE\tRUNTIME\t") for _, c := range containers { - info, err := c.Info(ctx) + info, err := c.Info(ctx, containerd.WithoutRefreshedMetadata) if err != nil { return err } @@ -261,7 +261,7 @@ var infoCommand = cli.Command{ if err != nil { return err } - info, err := container.Info(ctx) + info, err := container.Info(ctx, containerd.WithoutRefreshedMetadata) if err != nil { return err } diff --git a/container.go b/container.go index 2073d40b4..9bc43604e 100644 --- a/container.go +++ b/container.go @@ -49,7 +49,7 @@ type Container interface { // ID identifies the container ID() string // Info returns the underlying container record type - Info(context.Context) (containers.Container, error) + Info(context.Context, ...InfoOpts) (containers.Container, error) // Delete removes the container Delete(context.Context, ...DeleteOpts) error // NewTask creates a new task based on the container metadata @@ -80,16 +80,18 @@ type Container interface { func containerFromRecord(client *Client, c containers.Container) *container { return &container{ - client: client, - id: c.ID, + client: client, + id: c.ID, + metadata: c, } } var _ = (Container)(&container{}) type container struct { - client *Client - id string + client *Client + id string + metadata containers.Container } // ID returns the container's unique id @@ -97,8 +99,22 @@ func (c *container) ID() string { return c.id } -func (c *container) Info(ctx context.Context) (containers.Container, error) { - return c.get(ctx) +func (c *container) Info(ctx context.Context, opts ...InfoOpts) (containers.Container, error) { + i := &InfoConfig{ + // default to refreshing the container's local metadata + Refresh: true, + } + for _, o := range opts { + o(i) + } + if i.Refresh { + metadata, err := c.get(ctx) + if err != nil { + return c.metadata, err + } + c.metadata = metadata + } + return c.metadata, nil } func (c *container) Extensions(ctx context.Context) (map[string]prototypes.Any, error) { diff --git a/container_opts.go b/container_opts.go index 1ce989432..25b8f9730 100644 --- a/container_opts.go +++ b/container_opts.go @@ -41,6 +41,15 @@ type NewContainerOpts func(ctx context.Context, client *Client, c *containers.Co // UpdateContainerOpts allows the caller to set additional options when updating a container type UpdateContainerOpts func(ctx context.Context, client *Client, c *containers.Container) error +// InfoOpts controls how container metadata is fetched and returned +type InfoOpts func(*InfoConfig) + +// InfoConfig specifies how container metadata is fetched +type InfoConfig struct { + // Refresh will to a fetch of the latest container metadata + Refresh bool +} + // WithRuntime allows a user to specify the runtime name and additional options that should // be used to create tasks for the container func WithRuntime(name string, options interface{}) NewContainerOpts { @@ -235,3 +244,8 @@ func WithSpec(s *oci.Spec, opts ...oci.SpecOpts) NewContainerOpts { return err } } + +// WithoutRefreshedMetadata will use the current metadata attached to the container object +func WithoutRefreshedMetadata(i *InfoConfig) { + i.Refresh = false +}