Implement client interface for transfer service

Signed-off-by: Derek McGowan <derek@mcg.dev>
This commit is contained in:
Derek McGowan 2022-06-27 11:06:55 -07:00
parent 81afd9c36e
commit e506cd103f
No known key found for this signature in database
GPG Key ID: F58C5D0A4405ACDB
2 changed files with 122 additions and 49 deletions

View File

@ -18,16 +18,8 @@ package images
import ( import (
"fmt" "fmt"
"time"
"github.com/containerd/containerd"
"github.com/containerd/containerd/cmd/ctr/commands" "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" "github.com/urfave/cli"
) )
@ -87,57 +79,64 @@ command. As part of this process, we do the following:
} }
defer done(ctx) defer done(ctx)
config, err := content.NewFetchConfig(ctx, context) // TODO: Handle this locally via transfer config
if err != nil { //config, err := content.NewFetchConfig(ctx, context)
// if err != nil {
// return err
//}
if err := client.Transfer(ctx, nil, nil); err != nil {
return err return err
} }
img, err := content.Fetch(ctx, client, ref, config) /*
if err != nil { img, err := content.Fetch(ctx, client, ref, config)
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"))
if err != nil { if err != nil {
return err 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 { if err != nil {
return err return err
} }
chainID := identity.ChainID(diffIDs).String() if context.Bool("print-chainid") {
fmt.Printf("image chain ID: %s\n", 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 return nil
}, },
} }

74
transfer.go Normal file
View File

@ -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)
}