diff --git a/cmd/ctr/commands/images/pull.go b/cmd/ctr/commands/images/pull.go index c93bdaac2..0bfe3f8f4 100644 --- a/cmd/ctr/commands/images/pull.go +++ b/cmd/ctr/commands/images/pull.go @@ -18,16 +18,8 @@ package images import ( "fmt" - "time" - "github.com/containerd/containerd" "github.com/containerd/containerd/cmd/ctr/commands" - "github.com/containerd/containerd/cmd/ctr/commands/content" - "github.com/containerd/containerd/images" - "github.com/containerd/containerd/log" - "github.com/containerd/containerd/platforms" - "github.com/opencontainers/image-spec/identity" - ocispec "github.com/opencontainers/image-spec/specs-go/v1" "github.com/urfave/cli" ) @@ -87,57 +79,64 @@ command. As part of this process, we do the following: } defer done(ctx) - config, err := content.NewFetchConfig(ctx, context) - if err != nil { + // TODO: Handle this locally via transfer config + //config, err := content.NewFetchConfig(ctx, context) + // if err != nil { + // return err + //} + + if err := client.Transfer(ctx, nil, nil); err != nil { return err } - img, err := content.Fetch(ctx, client, ref, config) - if err != nil { - return err - } - - log.G(ctx).WithField("image", ref).Debug("unpacking") - - // TODO: Show unpack status - - var p []ocispec.Platform - if context.Bool("all-platforms") { - p, err = images.Platforms(ctx, client.ContentStore(), img.Target) - if err != nil { - return fmt.Errorf("unable to resolve image platforms: %w", err) - } - } else { - for _, s := range context.StringSlice("platform") { - ps, err := platforms.Parse(s) - if err != nil { - return fmt.Errorf("unable to parse platform %s: %w", s, err) - } - p = append(p, ps) - } - } - if len(p) == 0 { - p = append(p, platforms.DefaultSpec()) - } - - start := time.Now() - for _, platform := range p { - fmt.Printf("unpacking %s %s...\n", platforms.Format(platform), img.Target.Digest) - i := containerd.NewImageWithPlatform(client, img, platforms.Only(platform)) - err = i.Unpack(ctx, context.String("snapshotter")) + /* + img, err := content.Fetch(ctx, client, ref, config) if err != nil { return err } - if context.Bool("print-chainid") { - diffIDs, err := i.RootFS(ctx) + + log.G(ctx).WithField("image", ref).Debug("unpacking") + + // TODO: Show unpack status + + var p []ocispec.Platform + if context.Bool("all-platforms") { + p, err = images.Platforms(ctx, client.ContentStore(), img.Target) + if err != nil { + return fmt.Errorf("unable to resolve image platforms: %w", err) + } + } else { + for _, s := range context.StringSlice("platform") { + ps, err := platforms.Parse(s) + if err != nil { + return fmt.Errorf("unable to parse platform %s: %w", s, err) + } + p = append(p, ps) + } + } + if len(p) == 0 { + p = append(p, platforms.DefaultSpec()) + } + + start := time.Now() + for _, platform := range p { + fmt.Printf("unpacking %s %s...\n", platforms.Format(platform), img.Target.Digest) + i := containerd.NewImageWithPlatform(client, img, platforms.Only(platform)) + err = i.Unpack(ctx, context.String("snapshotter")) if err != nil { return err } - chainID := identity.ChainID(diffIDs).String() - fmt.Printf("image chain ID: %s\n", chainID) + if context.Bool("print-chainid") { + diffIDs, err := i.RootFS(ctx) + if err != nil { + return err + } + chainID := identity.ChainID(diffIDs).String() + fmt.Printf("image chain ID: %s\n", chainID) + } } - } - fmt.Printf("done: %s\t\n", time.Since(start)) + fmt.Printf("done: %s\t\n", time.Since(start)) + */ return nil }, } diff --git a/transfer.go b/transfer.go new file mode 100644 index 000000000..61fb7e88e --- /dev/null +++ b/transfer.go @@ -0,0 +1,74 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package containerd + +import ( + "context" + + transferapi "github.com/containerd/containerd/api/services/transfer/v1" + "github.com/containerd/containerd/pkg/streaming" + "github.com/containerd/containerd/pkg/transfer" + "github.com/containerd/typeurl" + "google.golang.org/protobuf/types/known/anypb" +) + +func (c *Client) Transfer(ctx context.Context, src interface{}, dst interface{}, opts ...transfer.Opt) error { + // Conver Options + // Convert Source + // Convert Destinations + // Get Stream Manager + + asrc, err := c.toAny(ctx, src) + if err != nil { + return err + } + + adst, err := c.toAny(ctx, dst) + if err != nil { + return err + } + + _, err = transferapi.NewTransferClient(c.conn).Transfer(ctx, &transferapi.TransferRequest{ + Source: &anypb.Any{ + TypeUrl: asrc.GetTypeUrl(), + Value: asrc.GetValue(), + }, + Destination: &anypb.Any{ + TypeUrl: adst.GetTypeUrl(), + Value: adst.GetValue(), + }, + }) + return err +} + +func (c *Client) toAny(ctx context.Context, i interface{}) (a typeurl.Any, err error) { + switch v := i.(type) { + case toAny: + //Get stream manager + a, err = v.ToAny(ctx, nil) + case typeurl.Any: + a = v + default: + a, err = typeurl.MarshalAny(i) + } + + return +} + +type toAny interface { + ToAny(context.Context, streaming.StreamManager) (typeurl.Any, error) +}