 12c0daa9c9
			
		
	
	12c0daa9c9
	
	
	
		
			
			To simplify use of types, we have consolidate the packages for the mount and descriptor protobuf types into a single Go package. We also drop the versioning from the type packages, as these types will remain the same between versions. Signed-off-by: Stephen J Day <stephen.day@docker.com>
		
			
				
	
	
		
			116 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			116 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // +build !windows
 | |
| 
 | |
| package containerd
 | |
| 
 | |
| import (
 | |
| 	"context"
 | |
| 	"encoding/json"
 | |
| 	"fmt"
 | |
| 	"io/ioutil"
 | |
| 
 | |
| 	"github.com/containerd/containerd/api/services/containers/v1"
 | |
| 	"github.com/containerd/containerd/api/services/tasks/v1"
 | |
| 	"github.com/containerd/containerd/api/types"
 | |
| 	"github.com/containerd/containerd/content"
 | |
| 	"github.com/containerd/containerd/images"
 | |
| 	"github.com/containerd/containerd/snapshot"
 | |
| 	protobuf "github.com/gogo/protobuf/types"
 | |
| 	digest "github.com/opencontainers/go-digest"
 | |
| 	"github.com/opencontainers/image-spec/identity"
 | |
| 	"github.com/opencontainers/image-spec/specs-go/v1"
 | |
| 	specs "github.com/opencontainers/runtime-spec/specs-go"
 | |
| )
 | |
| 
 | |
| func WithCheckpoint(desc v1.Descriptor, rootfsID string) NewContainerOpts {
 | |
| 	// set image and rw, and spec
 | |
| 	return func(ctx context.Context, client *Client, c *containers.Container) error {
 | |
| 		id := desc.Digest
 | |
| 		store := client.ContentStore()
 | |
| 		index, err := decodeIndex(ctx, store, id)
 | |
| 		if err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 		var rw *v1.Descriptor
 | |
| 		for _, m := range index.Manifests {
 | |
| 			switch m.MediaType {
 | |
| 			case v1.MediaTypeImageLayer:
 | |
| 				fk := m
 | |
| 				rw = &fk
 | |
| 			case images.MediaTypeDockerSchema2Manifest:
 | |
| 				config, err := images.Config(ctx, store, m)
 | |
| 				if err != nil {
 | |
| 					return err
 | |
| 				}
 | |
| 				diffIDs, err := images.RootFS(ctx, store, config)
 | |
| 				if err != nil {
 | |
| 					return err
 | |
| 				}
 | |
| 				if _, err := client.SnapshotService().Prepare(ctx, rootfsID, identity.ChainID(diffIDs).String()); err != nil {
 | |
| 					if !snapshot.IsExist(err) {
 | |
| 						return err
 | |
| 					}
 | |
| 				}
 | |
| 				c.Image = index.Annotations["image.name"]
 | |
| 			case images.MediaTypeContainerd1CheckpointConfig:
 | |
| 				r, err := store.Reader(ctx, m.Digest)
 | |
| 				if err != nil {
 | |
| 					return err
 | |
| 				}
 | |
| 				data, err := ioutil.ReadAll(r)
 | |
| 				r.Close()
 | |
| 				if err != nil {
 | |
| 					return err
 | |
| 				}
 | |
| 				c.Spec = &protobuf.Any{
 | |
| 					TypeUrl: specs.Version,
 | |
| 					Value:   data,
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 		if rw != nil {
 | |
| 			// apply the rw snapshot to the new rw layer
 | |
| 			mounts, err := client.SnapshotService().Mounts(ctx, rootfsID)
 | |
| 			if err != nil {
 | |
| 				return err
 | |
| 			}
 | |
| 			if _, err := client.DiffService().Apply(ctx, *rw, mounts); err != nil {
 | |
| 				return err
 | |
| 			}
 | |
| 		}
 | |
| 		c.RootFS = rootfsID
 | |
| 		return nil
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func WithTaskCheckpoint(desc v1.Descriptor) NewTaskOpts {
 | |
| 	return func(ctx context.Context, c *Client, r *tasks.CreateTaskRequest) error {
 | |
| 		id := desc.Digest
 | |
| 		index, err := decodeIndex(ctx, c.ContentStore(), id)
 | |
| 		if err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 		for _, m := range index.Manifests {
 | |
| 			if m.MediaType == images.MediaTypeContainerd1Checkpoint {
 | |
| 				r.Checkpoint = &types.Descriptor{
 | |
| 					MediaType: m.MediaType,
 | |
| 					Size_:     m.Size,
 | |
| 					Digest:    m.Digest,
 | |
| 				}
 | |
| 				return nil
 | |
| 			}
 | |
| 		}
 | |
| 		return fmt.Errorf("checkpoint not found in index %s", id)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func decodeIndex(ctx context.Context, store content.Store, id digest.Digest) (*v1.Index, error) {
 | |
| 	var index v1.Index
 | |
| 	r, err := store.Reader(ctx, id)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	err = json.NewDecoder(r).Decode(&index)
 | |
| 	r.Close()
 | |
| 	return &index, err
 | |
| }
 |