// setupImage attempts to load the image by the given hash from the store, // verifies that the image matches the given hash and extracts the image // into a directory in the given dir. // It returns the AppManifest that the image contains func setupImage(cfg Config, img types.Hash, dir string) (*schema.AppManifest, error) { log.Println("Loading image", img.String()) rs, err := cfg.Store.ReadStream(img.String()) if err != nil { return nil, err } ad := rktpath.AppImagePath(dir, img) err = os.MkdirAll(ad, 0776) if err != nil { return nil, fmt.Errorf("error creating image directory: %v", err) } hash := sha256.New() r := io.TeeReader(rs, hash) if err := ptar.ExtractTar(tar.NewReader(r), ad); err != nil { return nil, fmt.Errorf("error extracting ACI: %v", err) } // Tar does not necessarily read the complete file, so ensure we read the entirety into the hash if _, err := io.Copy(ioutil.Discard, r); err != nil { return nil, fmt.Errorf("error reading ACI: %v", err) } if id := fmt.Sprintf("%x", hash.Sum(nil)); id != img.Val { if err := os.RemoveAll(ad); err != nil { fmt.Fprintf(os.Stderr, "error cleaning up directory: %v\n", err) } return nil, fmt.Errorf("image hash does not match expected (%v != %v)", id, img.Val) } err = os.MkdirAll(filepath.Join(ad, "rootfs/tmp"), 0777) if err != nil { return nil, fmt.Errorf("error creating tmp directory: %v", err) } mpath := rktpath.AppManifestPath(dir, img) f, err := os.Open(mpath) if err != nil { return nil, fmt.Errorf("error opening app manifest: %v", err) } b, err := ioutil.ReadAll(f) if err != nil { return nil, fmt.Errorf("error reading app manifest: %v", err) } var am schema.AppManifest if err := json.Unmarshal(b, &am); err != nil { return nil, fmt.Errorf("error unmarshaling app manifest: %v", err) } return &am, nil }
// RelAppImagePath returns the path of an application image relative to the // stage1 chroot func RelAppImagePath(imageID types.Hash) string { return filepath.Join(stage2Dir, imageID.String()) }
// AppImagePath returns the path where an app image (i.e. unpacked ACI) is rooted (i.e. // where its contents are extracted during stage0), based on the app image ID. func AppImagePath(root string, imageID types.Hash) string { return filepath.Join(root, Stage1Dir, stage2Dir, imageID.String()) }
// SocketUnitName returns a systemd socket unit name for the given imageID func SocketUnitName(imageID types.Hash) string { return imageID.String() + ".socket" }
// ServiceUnitName returns a systemd service unit name for the given imageID func ServiceUnitName(imageID types.Hash) string { return imageID.String() + ".service" }