Godeps: bump appc/spec to 0.5.0

This commit is contained in:
Jonathan Boulle
2015-03-24 18:49:48 -07:00
parent 46a7870d9f
commit 6ef34caf20
20 changed files with 324 additions and 166 deletions
+13 -13
View File
@@ -1,6 +1,6 @@
{
"ImportPath": "github.com/coreos/rocket",
"GoVersion": "go1.4.2",
"GoVersion": "go1.4.1",
"Packages": [
"./..."
],
@@ -25,33 +25,33 @@
},
{
"ImportPath": "github.com/appc/spec/aci",
"Comment": "v0.4.0-10-g24650793e48a",
"Rev": "24650793e48a5a7fd04bf680e25c5ae192e4241d"
"Comment": "v0.5.0",
"Rev": "cffea391f209199b873af3f8a71a98ac658f073e"
},
{
"ImportPath": "github.com/appc/spec/actool",
"Comment": "v0.4.0-10-g24650793e48a",
"Rev": "24650793e48a5a7fd04bf680e25c5ae192e4241d"
"Comment": "v0.5.0",
"Rev": "cffea391f209199b873af3f8a71a98ac658f073e"
},
{
"ImportPath": "github.com/appc/spec/discovery",
"Comment": "v0.4.0-10-g24650793e48a",
"Rev": "24650793e48a5a7fd04bf680e25c5ae192e4241d"
"Comment": "v0.5.0",
"Rev": "cffea391f209199b873af3f8a71a98ac658f073e"
},
{
"ImportPath": "github.com/appc/spec/pkg/acirenderer",
"Comment": "v0.4.0-10-g24650793e48a",
"Rev": "24650793e48a5a7fd04bf680e25c5ae192e4241d"
"Comment": "v0.5.0",
"Rev": "cffea391f209199b873af3f8a71a98ac658f073e"
},
{
"ImportPath": "github.com/appc/spec/pkg/tarheader",
"Comment": "v0.4.0-10-g24650793e48a",
"Rev": "24650793e48a5a7fd04bf680e25c5ae192e4241d"
"Comment": "v0.5.0",
"Rev": "cffea391f209199b873af3f8a71a98ac658f073e"
},
{
"ImportPath": "github.com/appc/spec/schema",
"Comment": "v0.4.0-10-g24650793e48a",
"Rev": "24650793e48a5a7fd04bf680e25c5ae192e4241d"
"Comment": "v0.5.0",
"Rev": "cffea391f209199b873af3f8a71a98ac658f073e"
},
{
"ImportPath": "github.com/camlistore/lock",
+3
View File
@@ -35,6 +35,9 @@ func BuildWalker(root string, aw ArchiveWriter) filepath.WalkFunc {
link := ""
var r io.Reader
switch info.Mode() & os.ModeType {
case os.ModeSocket:
return nil
case os.ModeNamedPipe:
case os.ModeCharDevice:
case os.ModeDevice:
case os.ModeDir:
+1 -1
View File
@@ -14,7 +14,7 @@ func newTestACI(usedotslash bool) (*os.File, error) {
return nil, err
}
manifestBody := `{"acKind":"ImageManifest","acVersion":"0.4.0","name":"example.com/app"}`
manifestBody := `{"acKind":"ImageManifest","acVersion":"0.5.0","name":"example.com/app"}`
gw := gzip.NewWriter(tf)
tw := tar.NewWriter(gw)
+2 -3
View File
@@ -60,8 +60,7 @@ func ValidateLayout(dir string) error {
if err != nil {
return err
}
name := filepath.Base(rpath)
switch name {
switch rpath {
case ".":
case ManifestFile:
im, err = os.Open(fpath)
@@ -85,7 +84,7 @@ func ValidateLayout(dir string) error {
return validate(imOK, im, rfsOK, flist)
}
// ValidateLayout takes a *tar.Reader and validates that the layout of the
// ValidateArchive takes a *tar.Reader and validates that the layout of the
// filesystem the reader encapsulates matches that expected by the
// Application Container Image format. If any errors are encountered during
// the validation, it will abort and return the first one.
+62
View File
@@ -0,0 +1,62 @@
package aci
import (
"io/ioutil"
"os"
"path"
"testing"
)
func newValidateLayoutTest() (string, error) {
td, err := ioutil.TempDir("", "")
if err != nil {
return "", err
}
if err := os.MkdirAll(path.Join(td, "rootfs"), 0755); err != nil {
return "", err
}
if err := os.MkdirAll(path.Join(td, "rootfs", "dir", "rootfs"), 0755); err != nil {
return "", err
}
evilManifestBody := "malformedManifest"
manifestBody := `{"acKind":"ImageManifest","acVersion":"0.3.0","name":"example.com/app"}`
evilManifestPath := "rootfs/manifest"
evilManifestPath = path.Join(td, evilManifestPath)
em, err := os.Create(evilManifestPath)
if err != nil {
return "", err
}
em.WriteString(evilManifestBody)
em.Close()
manifestPath := path.Join(td, "manifest")
m, err := os.Create(manifestPath)
if err != nil {
return "", err
}
m.WriteString(manifestBody)
m.Close()
return td, nil
}
func TestValidateLayout(t *testing.T) {
layoutPath, err := newValidateLayoutTest()
if err != nil {
t.Fatalf("newValidateLayoutTest: unexpected error: %v", err)
}
defer os.RemoveAll(layoutPath)
err = ValidateLayout(layoutPath)
if err != nil {
t.Fatalf("ValidateLayout: unexpected error: %v", err)
}
}
+2 -2
View File
@@ -123,8 +123,8 @@ func runValidate(args []string) (exit int) {
case "ImageManifest":
m := schema.ImageManifest{}
err = m.UnmarshalJSON(b)
case "ContainerRuntimeManifest":
m := schema.ContainerRuntimeManifest{}
case "PodManifest":
m := schema.PodManifest{}
err = m.UnmarshalJSON(b)
default:
// Should not get here; schema.Kind unmarshal should fail
+1
View File
@@ -21,6 +21,7 @@ var (
func init() {
t := &http.Transport{
Proxy: http.ProxyFromEnvironment,
Dial: func(n, a string) (net.Conn, error) {
return net.DialTimeout(n, a, defaultDialTimeout)
},
-111
View File
@@ -1,111 +0,0 @@
package schema
import (
"encoding/json"
"errors"
"github.com/coreos/rocket/Godeps/_workspace/src/github.com/appc/spec/schema/types"
)
const ContainerRuntimeManifestKind = types.ACKind("ContainerRuntimeManifest")
type ContainerRuntimeManifest struct {
ACVersion types.SemVer `json:"acVersion"`
ACKind types.ACKind `json:"acKind"`
UUID types.UUID `json:"uuid"`
Apps AppList `json:"apps"`
Volumes []types.Volume `json:"volumes"`
Isolators []types.Isolator `json:"isolators"`
Annotations types.Annotations `json:"annotations"`
}
// containerRuntimeManifest is a model to facilitate extra validation during the
// unmarshalling of the ContainerRuntimeManifest
type containerRuntimeManifest ContainerRuntimeManifest
func BlankContainerRuntimeManifest() *ContainerRuntimeManifest {
return &ContainerRuntimeManifest{ACKind: ContainerRuntimeManifestKind, ACVersion: AppContainerVersion}
}
func (cm *ContainerRuntimeManifest) UnmarshalJSON(data []byte) error {
c := containerRuntimeManifest(*cm)
err := json.Unmarshal(data, &c)
if err != nil {
return err
}
ncm := ContainerRuntimeManifest(c)
if err := ncm.assertValid(); err != nil {
return err
}
*cm = ncm
return nil
}
func (cm ContainerRuntimeManifest) MarshalJSON() ([]byte, error) {
if err := cm.assertValid(); err != nil {
return nil, err
}
return json.Marshal(containerRuntimeManifest(cm))
}
var cmKindError = types.InvalidACKindError(ContainerRuntimeManifestKind)
// assertValid performs extra assertions on an ContainerRuntimeManifest to
// ensure that fields are set appropriately, etc. It is used exclusively when
// marshalling and unmarshalling an ContainerRuntimeManifest. Most
// field-specific validation is performed through the individual types being
// marshalled; assertValid() should only deal with higher-level validation.
func (cm *ContainerRuntimeManifest) assertValid() error {
if cm.ACKind != ContainerRuntimeManifestKind {
return cmKindError
}
return nil
}
type AppList []RuntimeApp
// Get retrieves an app by the specified name from the AppList; if there is
// no such app, nil is returned. The returned *RuntimeApp MUST be considered
// read-only.
func (al AppList) Get(name types.ACName) *RuntimeApp {
for _, a := range al {
if name.Equals(a.Name) {
aa := a
return &aa
}
}
return nil
}
// Mount describes the mapping between a volume and an apps
// MountPoint that will be fulfilled at runtime.
type Mount struct {
Volume types.ACName `json:"volume"`
MountPoint types.ACName `json:"mountPoint"`
}
func (r Mount) assertValid() error {
if r.Volume.Empty() {
return errors.New("volume must be set")
}
if r.MountPoint.Empty() {
return errors.New("mountPoint must be set")
}
return nil
}
// RuntimeApp describes an application referenced in a ContainerRuntimeManifest
type RuntimeApp struct {
Name types.ACName `json:"name"`
Image RuntimeImage `json:"image"`
App *types.App `json:"app,omitempty"`
Mounts []Mount `json:"mounts"`
Annotations types.Annotations `json:"annotations"`
}
// RuntimeImage describes an image referenced in a RuntimeApp
type RuntimeImage struct {
Name types.ACName `json:"name"`
ID types.Hash `json:"id"`
Labels types.Labels `json:"labels"`
}
-19
View File
@@ -1,19 +0,0 @@
package schema
import "testing"
func TestContainerRuntimeManifestMerge(t *testing.T) {
cmj := `{}`
cm := &ContainerRuntimeManifest{}
if cm.UnmarshalJSON([]byte(cmj)) == nil {
t.Fatal("Manifest JSON without acKind and acVersion unmarshalled successfully")
}
cm = BlankContainerRuntimeManifest()
err := cm.UnmarshalJSON([]byte(cmj))
if err != nil {
t.Errorf("unexpected error: %v", err)
}
}
+1 -1
View File
@@ -2,7 +2,7 @@
// manifests in the App Container Specification. The manifests are canonically
// represented in their respective structs:
// - `ImageManifest`
// - `ContainerRuntimeManifest`
// - `PodManifest`
//
// Validation is performed through serialization: if a blob of JSON data will
// unmarshal to one of the *Manifests, it is considered a valid implementation
+1 -1
View File
@@ -6,7 +6,7 @@ func TestEmptyApp(t *testing.T) {
imj := `
{
"acKind": "ImageManifest",
"acVersion": "0.4.0",
"acVersion": "0.5.0",
"name": "example.com/test"
}
`
+147
View File
@@ -0,0 +1,147 @@
package schema
import (
"encoding/json"
"errors"
"fmt"
"github.com/coreos/rocket/Godeps/_workspace/src/github.com/appc/spec/schema/types"
)
const PodManifestKind = types.ACKind("PodManifest")
type PodManifest struct {
ACVersion types.SemVer `json:"acVersion"`
ACKind types.ACKind `json:"acKind"`
UUID types.UUID `json:"uuid"`
Apps AppList `json:"apps"`
Volumes []types.Volume `json:"volumes"`
Isolators []types.Isolator `json:"isolators"`
Annotations types.Annotations `json:"annotations"`
Ports []types.ExposedPort `json:"ports"`
}
// podManifest is a model to facilitate extra validation during the
// unmarshalling of the PodManifest
type podManifest PodManifest
func BlankPodManifest() *PodManifest {
return &PodManifest{ACKind: PodManifestKind, ACVersion: AppContainerVersion}
}
func (pm *PodManifest) UnmarshalJSON(data []byte) error {
p := podManifest(*pm)
err := json.Unmarshal(data, &p)
if err != nil {
return err
}
npm := PodManifest(p)
if err := npm.assertValid(); err != nil {
return err
}
*pm = npm
return nil
}
func (pm PodManifest) MarshalJSON() ([]byte, error) {
if err := pm.assertValid(); err != nil {
return nil, err
}
return json.Marshal(podManifest(pm))
}
var pmKindError = types.InvalidACKindError(PodManifestKind)
// assertValid performs extra assertions on an PodManifest to
// ensure that fields are set appropriately, etc. It is used exclusively when
// marshalling and unmarshalling an PodManifest. Most
// field-specific validation is performed through the individual types being
// marshalled; assertValid() should only deal with higher-level validation.
func (pm *PodManifest) assertValid() error {
if pm.ACKind != PodManifestKind {
return pmKindError
}
return nil
}
type AppList []RuntimeApp
type appList AppList
func (al *AppList) UnmarshalJSON(data []byte) error {
a := appList{}
err := json.Unmarshal(data, &a)
if err != nil {
return err
}
nal := AppList(a)
if err := nal.assertValid(); err != nil {
return err
}
*al = nal
return nil
}
func (al AppList) MarshalJSON() ([]byte, error) {
if err := al.assertValid(); err != nil {
return nil, err
}
return json.Marshal(appList(al))
}
func (al AppList) assertValid() error {
seen := map[types.ACName]bool{}
for _, a := range al {
if _, ok := seen[a.Name]; ok {
return fmt.Errorf(`duplicate apps of name %q`, a.Name)
}
seen[a.Name] = true
}
return nil
}
// Get retrieves an app by the specified name from the AppList; if there is
// no such app, nil is returned. The returned *RuntimeApp MUST be considered
// read-only.
func (al AppList) Get(name types.ACName) *RuntimeApp {
for _, a := range al {
if name.Equals(a.Name) {
aa := a
return &aa
}
}
return nil
}
// Mount describes the mapping between a volume and an apps
// MountPoint that will be fulfilled at runtime.
type Mount struct {
Volume types.ACName `json:"volume"`
MountPoint types.ACName `json:"mountPoint"`
}
func (r Mount) assertValid() error {
if r.Volume.Empty() {
return errors.New("volume must be set")
}
if r.MountPoint.Empty() {
return errors.New("mountPoint must be set")
}
return nil
}
// RuntimeApp describes an application referenced in a PodManifest
type RuntimeApp struct {
Name types.ACName `json:"name"`
Image RuntimeImage `json:"image"`
App *types.App `json:"app,omitempty"`
Mounts []Mount `json:"mounts,omitempty"`
Annotations types.Annotations `json:"annotations,omitempty"`
}
// RuntimeImage describes an image referenced in a RuntimeApp
type RuntimeImage struct {
Name *types.ACName `json:"name,omitempty"`
ID types.Hash `json:"id"`
Labels types.Labels `json:"labels,omitempty"`
}
+59
View File
@@ -0,0 +1,59 @@
package schema
import (
"testing"
"github.com/coreos/rocket/Godeps/_workspace/src/github.com/appc/spec/schema/types"
)
func TestPodManifestMerge(t *testing.T) {
pmj := `{}`
pm := &PodManifest{}
if pm.UnmarshalJSON([]byte(pmj)) == nil {
t.Fatal("Manifest JSON without acKind and acVersion unmarshalled successfully")
}
pm = BlankPodManifest()
err := pm.UnmarshalJSON([]byte(pmj))
if err != nil {
t.Errorf("unexpected error: %v", err)
}
}
func TestAppList(t *testing.T) {
ri := RuntimeImage{
ID: *types.NewHashSHA512([]byte{}),
}
al := AppList{
RuntimeApp{
Name: "foo",
Image: ri,
},
RuntimeApp{
Name: "bar",
Image: ri,
},
}
if _, err := al.MarshalJSON(); err != nil {
t.Errorf("want err=nil, got %v", err)
}
dal := AppList{
RuntimeApp{
Name: "foo",
Image: ri,
},
RuntimeApp{
Name: "bar",
Image: ri,
},
RuntimeApp{
Name: "foo",
Image: ri,
},
}
if _, err := dal.MarshalJSON(); err == nil {
t.Errorf("want err, got nil")
}
}
+1 -1
View File
@@ -21,7 +21,7 @@ func (a ACKind) String() string {
func (a ACKind) assertValid() error {
s := a.String()
switch s {
case "ImageManifest", "ContainerRuntimeManifest":
case "ImageManifest", "PodManifest":
return nil
case "":
return ErrNoACKind
+3 -3
View File
@@ -31,7 +31,7 @@ func TestACKindMarshalBad(t *testing.T) {
func TestACKindMarshalGood(t *testing.T) {
for i, in := range []string{
"ImageManifest",
"ContainerRuntimeManifest",
"PodManifest",
} {
a := ACKind(in)
b, err := json.Marshal(a)
@@ -64,8 +64,8 @@ func TestACKindUnmarshalBad(t *testing.T) {
func TestACKindUnmarshalGood(t *testing.T) {
tests := map[string]ACKind{
`"ContainerRuntimeManifest"`: ACKind("ContainerRuntimeManifest"),
`"ImageManifest"`: ACKind("ImageManifest"),
`"PodManifest"`: ACKind("PodManifest"),
`"ImageManifest"`: ACKind("ImageManifest"),
}
for in, w := range tests {
var a ACKind
+1 -1
View File
@@ -16,7 +16,7 @@ type App struct {
Environment Environment `json:"environment,omitempty"`
MountPoints []MountPoint `json:"mountPoints,omitempty"`
Ports []Port `json:"ports,omitempty"`
Isolators []Isolator `json:"isolators,omitempty"`
Isolators Isolators `json:"isolators,omitempty"`
}
// app is a model to facilitate extra validation during the
+5
View File
@@ -6,3 +6,8 @@ type Port struct {
Port uint `json:"port"`
SocketActivated bool `json:"socketActivated"`
}
type ExposedPort struct {
Name ACName `json:"name"`
HostPort uint `json:"hostPort"`
}
+4 -4
View File
@@ -11,7 +11,7 @@ import (
)
// Volume encapsulates a volume which should be mounted into the filesystem
// of all apps in a ContainerRuntimeManifest
// of all apps in a PodManifest
type Volume struct {
Name ACName `json:"name"`
Kind string `json:"kind"`
@@ -19,7 +19,7 @@ type Volume struct {
// currently used only by "host"
// TODO(jonboulle): factor out?
Source string `json:"source,omitempty"`
ReadOnly bool `json:"readOnly,omitempty"`
ReadOnly *bool `json:"readOnly,omitempty"`
}
type volume Volume
@@ -69,7 +69,7 @@ func (v Volume) MarshalJSON() ([]byte, error) {
}
func (v Volume) String() string {
s := fmt.Sprintf("%s,kind=%s,readOnly=%t", v.Name, v.Kind, v.ReadOnly)
s := fmt.Sprintf("%s,kind=%s,readOnly=%t", v.Name, v.Kind, *v.ReadOnly)
if v.Source != "" {
s = s + fmt.Sprintf("source=%s", v.Source)
}
@@ -110,7 +110,7 @@ func VolumeFromString(vp string) (*Volume, error) {
if err != nil {
return nil, err
}
vol.ReadOnly = ro
vol.ReadOnly = &ro
default:
return nil, fmt.Errorf("unknown volume parameter %q", key)
}
+17 -5
View File
@@ -6,6 +6,8 @@ import (
)
func TestVolumeFromString(t *testing.T) {
trueVar := true
falseVar := false
tests := []struct {
s string
v Volume
@@ -16,7 +18,16 @@ func TestVolumeFromString(t *testing.T) {
Name: "foobar",
Kind: "host",
Source: "/tmp",
ReadOnly: false,
ReadOnly: nil,
},
},
{
"foobar,kind=host,source=/tmp,readOnly=false",
Volume{
Name: "foobar",
Kind: "host",
Source: "/tmp",
ReadOnly: &falseVar,
},
},
{
@@ -25,14 +36,15 @@ func TestVolumeFromString(t *testing.T) {
Name: "foobar",
Kind: "host",
Source: "/tmp",
ReadOnly: true,
ReadOnly: &trueVar,
},
},
{
"foobar,kind=empty",
Volume{
Name: "foobar",
Kind: "empty",
Name: "foobar",
Kind: "empty",
ReadOnly: nil,
},
},
{
@@ -40,7 +52,7 @@ func TestVolumeFromString(t *testing.T) {
Volume{
Name: "foobar",
Kind: "empty",
ReadOnly: true,
ReadOnly: &trueVar,
},
},
}
+1 -1
View File
@@ -8,7 +8,7 @@ const (
// version represents the canonical version of the appc spec and tooling.
// For now, the schema and tooling is coupled with the spec itself, so
// this must be kept in sync with the VERSION file in the root of the repo.
version string = "0.4.0+git"
version string = "0.5.0"
)
var (