Skip to content

Commit

Permalink
Use acirenderer for squashing
Browse files Browse the repository at this point in the history
This commit leverages acirenderer from the spec repository to implement
squashing. This has the benefit of reusing the same code rocket uses for
resolving ACI dependencies.

We create a conversion store that implements the ACIRegistry
interface so we can use the rendering functions.

Resolves appc#10.
  • Loading branch information
iaguis committed Mar 6, 2015
1 parent e8645fe commit 91ae378
Show file tree
Hide file tree
Showing 2 changed files with 194 additions and 135 deletions.
99 changes: 99 additions & 0 deletions lib/conversion_store.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package docker2aci

import (
"fmt"
"hash"
"io"
"io/ioutil"
"os"

"github.com/appc/spec/aci"
"github.com/appc/spec/schema"
"github.com/appc/spec/schema/types"
)

const (
hashPrefix = "sha512-"
)

type aciInfo struct {
path string
key string
ImageManifest *schema.ImageManifest
}

// ConversionStore is an simple implementation of the acirenderer.ACIRegistry
// interface. It stores the Docker layers converted to ACI so we can take
// advantage of acirenderer to generate a squashed ACI Image.
type ConversionStore struct {
acis map[string]*aciInfo
}

func NewConversionStore() *ConversionStore {
return &ConversionStore{acis: make(map[string]*aciInfo)}
}

func (ms *ConversionStore) WriteACI(path string) (string, error) {
data, err := ioutil.ReadFile(path)
if err != nil {
return "", err
}

f, err := os.Open(path)
if err != nil {
return "", err
}
defer f.Close()

imageID := types.NewHashSHA512(data)

im, err := aci.ManifestFromImage(f)
if err != nil {
return "", err
}

key := imageID.String()
ms.acis[key] = &aciInfo{path: path, key: key, ImageManifest: im}
return key, nil
}

func (ms *ConversionStore) GetImageManifest(key string) (*schema.ImageManifest, error) {
aci, ok := ms.acis[key]
if !ok {
return nil, fmt.Errorf("aci with key: %s not found", key)
}
return aci.ImageManifest, nil
}

func (ms *ConversionStore) GetACI(name types.ACName, labels types.Labels) (string, error) {
for _, aci := range ms.acis {
// we implement this function to comply with the interface so don't
// bother implementing a proper label check
if aci.ImageManifest.Name.String() == name.String() {
return aci.key, nil
}
}
return "", fmt.Errorf("aci not found")
}

func (ms *ConversionStore) ReadStream(key string) (io.ReadCloser, error) {
aci, ok := ms.acis[key]
if !ok {
return nil, fmt.Errorf("stream for key: %s not found", key)
}
f, err := os.Open(aci.path)
if err != nil {
return nil, fmt.Errorf("error opening aci: %s", aci.path)
}

return f, nil
}

func (ms *ConversionStore) ResolveKey(key string) (string, error) {
return key, nil
}

func (ms *ConversionStore) HashToKey(h hash.Hash) string {
s := h.Sum(nil)
return fmt.Sprintf("%s%x", hashPrefix, s)
}
Loading

0 comments on commit 91ae378

Please sign in to comment.