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