github.com/georgethebeatle/containerd@v0.2.5/integration-test/bundle_utils_test.go (about)

     1  package main
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"os"
     7  	"os/exec"
     8  	"path/filepath"
     9  	"reflect"
    10  
    11  	utils "github.com/docker/containerd/testutils"
    12  	ocs "github.com/opencontainers/runtime-spec/specs-go"
    13  )
    14  
    15  type OciProcessArgs struct {
    16  	Cmd  string
    17  	Args []string
    18  }
    19  
    20  type Bundle struct {
    21  	Source string
    22  	Name   string
    23  	Spec   ocs.Spec
    24  	Path   string
    25  }
    26  
    27  var bundleMap map[string]Bundle
    28  
    29  // untarRootfs untars the given `source` tarPath into `destination/rootfs`
    30  func untarRootfs(source string, destination string) error {
    31  	destination = filepath.Join(destination, "rootfs")
    32  	if err := os.MkdirAll(destination, 0755); err != nil {
    33  		return nil
    34  	}
    35  	tar := exec.Command("tar", "-C", destination, "-xf", source)
    36  	return tar.Run()
    37  }
    38  
    39  // CreateBundleWithFilter generate a new oci-bundle named `name` from
    40  // the provide `source` rootfs. It starts from the default spec
    41  // generated by `runc spec`, overrides the `spec.Process.Args` value
    42  // with `args` and set `spec.Process.Terminal` to false. It then apply
    43  // `filter()` to the resulting spec if it is provided.
    44  func CreateBundleWithFilter(source, name string, args []string, filter func(spec *ocs.Spec)) error {
    45  	// Generate the spec
    46  	var spec ocs.Spec
    47  	f, err := os.Open(utils.RefOciSpecsPath)
    48  	if err != nil {
    49  		return fmt.Errorf("Failed to open default spec: %v", err)
    50  	}
    51  	if err := json.NewDecoder(f).Decode(&spec); err != nil {
    52  		return fmt.Errorf("Failed to load default spec: %v", err)
    53  	}
    54  	f.Close()
    55  
    56  	spec.Process.Args = args
    57  	spec.Process.Terminal = false
    58  	if filter != nil {
    59  		filter(&spec)
    60  	}
    61  
    62  	bundlePath := filepath.Join(utils.BundlesRoot, name)
    63  	nb := Bundle{source, name, spec, bundlePath}
    64  
    65  	// Check that we don't already have such a bundle
    66  	if b, ok := bundleMap[name]; ok {
    67  		if reflect.DeepEqual(b, nb) == false {
    68  			return fmt.Errorf("A bundle name named '%s' already exist but with different properties! %#v != %#v",
    69  				name, b, nb)
    70  		}
    71  		return nil
    72  	}
    73  
    74  	// Nothing should be there, but just in case
    75  	os.RemoveAll(bundlePath)
    76  
    77  	if err := untarRootfs(filepath.Join(utils.ArchivesDir, source+".tar"), bundlePath); err != nil {
    78  		return fmt.Errorf("Failed to untar %s.tar: %v", source, err)
    79  	}
    80  
    81  	// create a place for the io fifo
    82  	if err := os.Mkdir(filepath.Join(bundlePath, "io"), 0755); err != nil {
    83  		return fmt.Errorf("Failed to create bundle io directory: %v", err)
    84  	}
    85  
    86  	// Write the updated spec to the right location
    87  	config, e := os.Create(filepath.Join(bundlePath, "config.json"))
    88  	if e != nil {
    89  		return fmt.Errorf("Failed to create oci spec: %v", e)
    90  	}
    91  	defer config.Close()
    92  
    93  	if err := json.NewEncoder(config).Encode(&spec); err != nil {
    94  		return fmt.Errorf("Failed to encore oci spec: %v", e)
    95  	}
    96  
    97  	bundleMap[name] = nb
    98  	return nil
    99  }
   100  
   101  func GetBundle(name string) *Bundle {
   102  	bundle, ok := bundleMap[name]
   103  	if !ok {
   104  		return nil
   105  	}
   106  	return &bundle
   107  }
   108  
   109  func CreateBusyboxBundle(name string, args []string) error {
   110  	return CreateBundleWithFilter("busybox", name, args, nil)
   111  }