Example #1
0
func (a *ACBuild) writeEmptyManifest() error {
	acid, err := types.NewACIdentifier("acbuild-unnamed")
	if err != nil {
		return err
	}

	archlabel, err := types.NewACIdentifier("arch")
	if err != nil {
		return err
	}

	oslabel, err := types.NewACIdentifier("os")
	if err != nil {
		return err
	}

	manifest := &schema.ImageManifest{
		ACKind:    schema.ImageManifestKind,
		ACVersion: schema.AppContainerVersion,
		Name:      *acid,
		Labels: types.Labels{
			types.Label{
				*archlabel,
				runtime.GOARCH,
			},
			types.Label{
				*oslabel,
				runtime.GOOS,
			},
		},
	}

	manblob, err := manifest.MarshalJSON()
	if err != nil {
		return err
	}

	manfile, err := os.Create(path.Join(a.CurrentACIPath, aci.ManifestFile))
	if err != nil {
		return err
	}

	_, err = manfile.Write(manblob)
	if err != nil {
		return err
	}

	err = manfile.Close()
	if err != nil {
		return err
	}

	return nil
}
Example #2
0
// NewAppFromString takes a command line app parameter and returns a map of labels.
//
// Example app parameters:
// 	example.com/reduce-worker:1.0.0
// 	example.com/reduce-worker,channel=alpha,label=value
// 	example.com/reduce-worker:1.0.0,label=value
//
// As can be seen in above examples - colon, comma and equal sign have
// special meaning. If any of them has to be a part of a label's value
// then consider writing your own string to App parser.
func NewAppFromString(app string) (*App, error) {
	var (
		name   string
		labels map[types.ACIdentifier]string
	)

	preparedApp, err := prepareAppString(app)
	if err != nil {
		return nil, err
	}
	v, err := url.ParseQuery(preparedApp)
	if err != nil {
		return nil, err
	}
	labels = make(map[types.ACIdentifier]string, 0)
	for key, val := range v {
		if len(val) > 1 {
			return nil, fmt.Errorf("label %s with multiple values %q", key, val)
		}
		if key == "name" {
			name = val[0]
			continue
		}
		labelName, err := types.NewACIdentifier(key)
		if err != nil {
			return nil, err
		}
		labels[*labelName] = val[0]
	}
	a, err := NewApp(name, labels)
	if err != nil {
		return nil, err
	}
	return a, nil
}
Example #3
0
// AddLabel will add a label with the given name and value to the untarred ACI
// stored at a.CurrentACIPath. If the label already exists its value will be updated to
// the new value.
func (a *ACBuild) AddLabel(name, value string) (err error) {
	if err = a.lock(); err != nil {
		return err
	}
	defer func() {
		if err1 := a.unlock(); err == nil {
			err = err1
		}
	}()

	acid, err := types.NewACIdentifier(name)
	if err != nil {
		return err
	}

	fn := func(s *schema.ImageManifest) {
		removeLabelFromMan(*acid)(s)
		s.Labels = append(s.Labels,
			types.Label{
				Name:  *acid,
				Value: value,
			})
	}
	return util.ModifyManifest(fn, a.CurrentACIPath)
}
Example #4
0
// AddDependency will add a dependency with the given name, id, labels, and size
// to the untarred ACI stored at acipath. If the dependency already exists its
// fields will be updated to the new values.
func AddDependency(acipath, imageName, imageId string, labels types.Labels, size uint) error {
	acid, err := types.NewACIdentifier(imageName)
	if err != nil {
		return err
	}

	var hash *types.Hash
	if imageId != "" {
		var err error
		hash, err = types.NewHash(imageId)
		if err != nil {
			return err
		}
	}

	fn := func(s *schema.ImageManifest) {
		removeDep(*acid)(s)
		s.Dependencies = append(s.Dependencies,
			types.Dependency{
				ImageName: *acid,
				ImageID:   hash,
				Labels:    labels,
				Size:      size,
			})
	}
	return util.ModifyManifest(fn, acipath)
}
Example #5
0
// NewAppFromString takes a command line app parameter and returns a map of labels.
//
// Example app parameters:
// 	example.com/reduce-worker:1.0.0
// 	example.com/reduce-worker,channel=alpha,label=value
func NewAppFromString(app string) (*App, error) {
	var (
		name   string
		labels map[types.ACIdentifier]string
	)

	app = strings.Replace(app, ":", ",version=", -1)
	app = "name=" + app
	v, err := url.ParseQuery(strings.Replace(app, ",", "&", -1))
	if err != nil {
		return nil, err
	}
	labels = make(map[types.ACIdentifier]string, 0)
	for key, val := range v {
		if len(val) > 1 {
			return nil, fmt.Errorf("label %s with multiple values %q", key, val)
		}
		if key == "name" {
			name = val[0]
			continue
		}
		labelName, err := types.NewACIdentifier(key)
		if err != nil {
			return nil, err
		}
		labels[*labelName] = val[0]
	}
	a, err := NewApp(name, labels)
	if err != nil {
		return nil, err
	}
	return a, nil
}
Example #6
0
func (a *ACBuild) AddIsolator(name string, value []byte) (err error) {
	if err = a.lock(); err != nil {
		return err
	}
	defer func() {
		if err1 := a.unlock(); err == nil {
			err = err1
		}
	}()

	acid, err := types.NewACIdentifier(name)
	if err != nil {
		return err
	}
	rawMsg := json.RawMessage(value)

	fn := func(s *schema.ImageManifest) error {
		if s.App == nil {
			s.App = newManifestApp()
		}
		removeIsolatorFromMan(*acid)(s)
		s.App.Isolators = append(s.App.Isolators,
			types.Isolator{
				Name:     *acid,
				ValueRaw: &rawMsg,
			})
		return nil
	}
	return util.ModifyManifest(fn, a.CurrentACIPath)
}
Example #7
0
// RemoveDependency will remove the dependency with the given name from the
// untarred ACI stored at acipath
func RemoveDependency(acipath, imageName string) error {
	acid, err := types.NewACIdentifier(imageName)
	if err != nil {
		return err
	}

	return util.ModifyManifest(removeDep(*acid), acipath)
}
Example #8
0
// RemoveAnnotation will remove the annotation with the given name from the
// untarred ACI stored at acipath
func RemoveAnnotation(acipath, name string) error {
	acid, err := types.NewACIdentifier(name)
	if err != nil {
		return err
	}

	return util.ModifyManifest(removeAnnotation(*acid), acipath)
}
Example #9
0
// AddAnnotation will add an annotation with the given name and value to the
// untarred ACI stored at acipath. If the annotation already exists its value
// will be updated to the new value.
func AddAnnotation(acipath, name, value string) error {
	acid, err := types.NewACIdentifier(name)
	if err != nil {
		return err
	}

	fn := func(s *schema.ImageManifest) {
		s.Annotations.Set(*acid, value)
	}
	return util.ModifyManifest(fn, acipath)
}
Example #10
0
func NewApp(name string, labels map[types.ACIdentifier]string) (*App, error) {
	if labels == nil {
		labels = make(map[types.ACIdentifier]string, 0)
	}
	acn, err := types.NewACIdentifier(name)
	if err != nil {
		return nil, err
	}
	return &App{
		Name:   *acn,
		Labels: labels,
	}, nil
}
Example #11
0
// SetName sets the name for the untarred ACI stored at acipath
func SetName(acipath, name string) error {
	if name == "" {
		return fmt.Errorf("name cannot be empty")
	}
	acid, err := types.NewACIdentifier(name)
	if err != nil {
		return err
	}

	fn := func(s *schema.ImageManifest) {
		s.Name = *acid
	}
	return util.ModifyManifest(fn, acipath)
}
Example #12
0
func (ls *labellist) Set(input string) error {
	parts := strings.SplitN(input, "=", 2)
	if len(parts) != 2 {
		return fmt.Errorf("no '=' character in %q", input)
	}
	acid, err := types.NewACIdentifier(parts[0])
	if err != nil {
		return err
	}
	*ls = append(*ls, types.Label{
		Name:  *acid,
		Value: parts[1],
	})
	return nil
}
Example #13
0
// AddLabel will add a label with the given name and value to the untarred ACI
// stored at acipath. If the label already exists its value will be updated to
// the new value.
func AddLabel(acipath, name, value string) error {
	acid, err := types.NewACIdentifier(name)
	if err != nil {
		return err
	}

	fn := func(s *schema.ImageManifest) {
		removeLabelFromMan(*acid)(s)
		s.Labels = append(s.Labels,
			types.Label{
				Name:  *acid,
				Value: value,
			})
	}
	return util.ModifyManifest(fn, acipath)
}
Example #14
0
// RemoveAnnotation will remove the annotation with the given name from the
// untarred ACI stored at a.CurrentACIPath
func (a *ACBuild) RemoveAnnotation(name string) (err error) {
	if err = a.lock(); err != nil {
		return err
	}
	defer func() {
		if err1 := a.unlock(); err == nil {
			err = err1
		}
	}()

	acid, err := types.NewACIdentifier(name)
	if err != nil {
		return err
	}

	return util.ModifyManifest(removeAnnotation(*acid), a.CurrentACIPath)
}
Example #15
0
// AddAnnotation will add an annotation with the given name and value to the
// untarred ACI stored at a.CurrentACIPath. If the annotation already exists
// its value will be updated to the new value.
func (a *ACBuild) AddAnnotation(name, value string) (err error) {
	if err = a.lock(); err != nil {
		return err
	}
	defer func() {
		if err1 := a.unlock(); err == nil {
			err = err1
		}
	}()

	acid, err := types.NewACIdentifier(name)
	if err != nil {
		return err
	}

	fn := func(s *schema.ImageManifest) {
		s.Annotations.Set(*acid, value)
	}
	return util.ModifyManifest(fn, a.CurrentACIPath)
}
Example #16
0
// SetName sets the name for the untarred ACI stored at a.CurrentACIPath
func (a *ACBuild) SetName(name string) (err error) {
	if err = a.lock(); err != nil {
		return err
	}
	defer func() {
		if err1 := a.unlock(); err == nil {
			err = err1
		}
	}()

	if name == "" {
		return fmt.Errorf("name cannot be empty")
	}
	acid, err := types.NewACIdentifier(name)
	if err != nil {
		return err
	}

	fn := func(s *schema.ImageManifest) {
		s.Name = *acid
	}
	return util.ModifyManifest(fn, a.CurrentACIPath)
}
Example #17
0
// AddDependency will add a dependency with the given name, id, labels, and size
// to the untarred ACI stored at a.CurrentACIPath. If the dependency already
// exists its fields will be updated to the new values.
func (a *ACBuild) AddDependency(imageName, imageId string, labels types.Labels, size uint) (err error) {
	if err = a.lock(); err != nil {
		return err
	}
	defer func() {
		if err1 := a.unlock(); err == nil {
			err = err1
		}
	}()

	acid, err := types.NewACIdentifier(imageName)
	if err != nil {
		return err
	}

	var hash *types.Hash
	if imageId != "" {
		var err error
		hash, err = types.NewHash(imageId)
		if err != nil {
			return err
		}
	}

	fn := func(s *schema.ImageManifest) error {
		removeDep(*acid)(s)
		s.Dependencies = append(s.Dependencies,
			types.Dependency{
				ImageName: *acid,
				ImageID:   hash,
				Labels:    labels,
				Size:      size,
			})
		return nil
	}
	return util.ModifyManifest(fn, a.CurrentACIPath)
}
Example #18
0
// Begin will start a new build, storing the untarred ACI the build operates on
// at a.CurrentACIPath. If start is the empty string, the build will begin with
// an empty ACI, otherwise the ACI stored at start will be used at the starting
// point.
func (a *ACBuild) Begin(start string, insecure bool) (err error) {
	_, err = os.Stat(a.ContextPath)
	switch {
	case os.IsNotExist(err):
		break
	case err != nil:
		return err
	default:
		return fmt.Errorf("build already in progress in this working dir")
	}

	err = os.MkdirAll(a.ContextPath, 0755)
	if err != nil {
		return err
	}

	if err = a.lock(); err != nil {
		return err
	}
	defer func() {
		if err1 := a.unlock(); err == nil {
			err = err1
		}
	}()

	defer func() {
		// If there was an error while beginning, we don't want to produce an
		// unexpected build context
		if err != nil {
			os.RemoveAll(a.ContextPath)
		}
	}()

	if start != "" {
		err = os.MkdirAll(a.CurrentACIPath, 0755)
		if err != nil {
			return err
		}
		if start[0] == '.' || start[0] == '/' {
			return a.beginFromLocalImage(start)
		} else {
			return a.beginFromRemoteImage(start, insecure)
		}
	}

	err = os.MkdirAll(path.Join(a.CurrentACIPath, aci.RootfsDir), 0755)
	if err != nil {
		return err
	}

	acid, err := types.NewACIdentifier("acbuild-unnamed")
	if err != nil {
		return err
	}

	archlabel, err := types.NewACIdentifier("arch")
	if err != nil {
		return err
	}

	oslabel, err := types.NewACIdentifier("os")
	if err != nil {
		return err
	}

	manifest := &schema.ImageManifest{
		ACKind:    schema.ImageManifestKind,
		ACVersion: schema.AppContainerVersion,
		Name:      *acid,
		Labels: types.Labels{
			types.Label{
				*archlabel,
				runtime.GOARCH,
			},
			types.Label{
				*oslabel,
				runtime.GOOS,
			},
		},
	}

	manblob, err := manifest.MarshalJSON()
	if err != nil {
		return err
	}

	manfile, err := os.Create(path.Join(a.CurrentACIPath, aci.ManifestFile))
	if err != nil {
		return err
	}

	_, err = manfile.Write(manblob)
	if err != nil {
		return err
	}

	err = manfile.Close()
	if err != nil {
		return err
	}

	return nil
}
Example #19
0
// Begin will start a new build, storing the untarred ACI the build operates on
// at tmpaci. If start is the empty string, the build will begin with an empty
// ACI, otherwise the ACI stored at start will be used at the starting point.
func Begin(tmpaci, start string) error {
	ex, err := util.Exists(tmpaci)
	if err != nil {
		return err
	}
	if ex {
		return fmt.Errorf("build already in progress? path exists: %s", tmpaci)
	}

	err = os.MkdirAll(path.Join(tmpaci, aci.RootfsDir), 0755)
	if err != nil {
		return err
	}

	if start != "" {
		ex, err := util.Exists(start)
		if err != nil {
			return err
		}
		if !ex {
			return fmt.Errorf("start aci doesn't exist: %s", start)
		}

		err = util.UnTar(start, tmpaci, nil)
		if err != nil {
			return err
		}

		return nil
	}

	acid, err := types.NewACIdentifier("acbuild-unnamed")
	if err != nil {
		return err
	}

	manifest := &schema.ImageManifest{
		ACKind:    schema.ImageManifestKind,
		ACVersion: schema.AppContainerVersion,
		Name:      *acid,
		App: &types.App{
			Exec:  placeholderexec,
			User:  "******",
			Group: "0",
		},
	}

	manblob, err := manifest.MarshalJSON()
	if err != nil {
		return err
	}

	manfile, err := os.Create(path.Join(tmpaci, aci.ManifestFile))
	if err != nil {
		return err
	}

	_, err = manfile.Write(manblob)
	if err != nil {
		return err
	}

	err = manfile.Close()
	if err != nil {
		return err
	}

	return nil
}
Example #20
0
// Begin will start a new build, storing the untarred ACI the build operates on
// at a.CurrentACIPath. If start is the empty string, the build will begin with
// an empty ACI, otherwise the ACI stored at start will be used at the starting
// point.
func (a *ACBuild) Begin(start string, insecure bool) (err error) {
	ex, err := util.Exists(a.ContextPath)
	if err != nil {
		return err
	}
	if ex {
		return fmt.Errorf("build already in progress in this working dir")
	}

	err = os.MkdirAll(a.ContextPath, 0755)
	if err != nil {
		return err
	}

	if err = a.lock(); err != nil {
		return err
	}
	defer func() {
		if err1 := a.unlock(); err == nil {
			err = err1
		}
	}()

	if start != "" {
		err = os.MkdirAll(a.CurrentACIPath, 0755)
		if err != nil {
			return err
		}
		return a.beginFromImage(start, insecure)
	}

	err = os.MkdirAll(path.Join(a.CurrentACIPath, aci.RootfsDir), 0755)
	if err != nil {
		return err
	}

	acid, err := types.NewACIdentifier("acbuild-unnamed")
	if err != nil {
		return err
	}

	manifest := &schema.ImageManifest{
		ACKind:    schema.ImageManifestKind,
		ACVersion: schema.AppContainerVersion,
		Name:      *acid,
		App: &types.App{
			Exec:  nil,
			User:  "******",
			Group: "0",
		},
	}

	manblob, err := manifest.MarshalJSON()
	if err != nil {
		return err
	}

	manfile, err := os.Create(path.Join(a.CurrentACIPath, aci.ManifestFile))
	if err != nil {
		return err
	}

	_, err = manfile.Write(manblob)
	if err != nil {
		return err
	}

	err = manfile.Close()
	if err != nil {
		return err
	}

	return nil
}