Beispiel #1
0
// getAppName returns the app name to enter
// If one was supplied in the flags then it's simply returned
// If the PM contains a single app, that app's name is returned
// If the PM has multiple apps, the names are printed and an error is returned
func getAppName(p *pkgPod.Pod) (*types.ACName, error) {
	if flagAppName != "" {
		return types.NewACName(flagAppName)
	}

	// figure out the app name, or show a list if multiple are present
	_, m, err := p.PodManifest()
	if err != nil {
		return nil, errwrap.Wrap(errors.New("error reading pod manifest"), err)
	}

	switch len(m.Apps) {
	case 0:
		return nil, fmt.Errorf("pod contains zero apps")
	case 1:
		return &m.Apps[0].Name, nil
	default:
	}

	stderr.Print("pod contains multiple apps:")
	for _, ra := range m.Apps {
		stderr.Printf("\t%v", ra.Name)
	}

	return nil, fmt.Errorf("specify app using \"rkt enter --app= ...\"")
}
Beispiel #2
0
func (pl *portList) Set(s string) error {
	parts := strings.SplitN(s, ":", 3)
	if len(parts) < 2 {
		return fmt.Errorf("%q is not in name:[ip:]port format", s)
	}

	name, err := types.NewACName(parts[0])
	if err != nil {
		return errwrap.Wrap(fmt.Errorf("%q is not a valid port name", parts[0]), err)
	}

	portStr := parts[1]
	var ip net.IP
	if len(parts) == 3 {
		portStr = parts[2]
		ip = net.ParseIP(parts[1])
		if ip == nil {
			return fmt.Errorf("%q is not a valid IP", parts[1])
		}
	}

	port, err := strconv.ParseUint(portStr, 10, 16)
	if err != nil {
		return fmt.Errorf("%q is not a valid port number", parts[1])
	}

	p := types.ExposedPort{
		Name:     *name,
		HostPort: uint(port),
		HostIP:   ip,
	}

	*pl = append(*pl, p)
	return nil
}
Beispiel #3
0
// getApp returns the app to export
// If one was supplied in the flags then it's returned if present
// If the PM contains a single app, that app is returned
// If the PM has multiple apps, the names are printed and an error is returned
func getApp(p *pod) (*schema.RuntimeApp, error) {
	apps, err := p.getApps()
	if err != nil {
		return nil, errwrap.Wrap(errors.New("problem getting the pod's app list"), err)
	}

	if flagExportAppName != "" {
		exportAppName, err := types.NewACName(flagExportAppName)
		if err != nil {
			return nil, err
		}
		for _, ra := range apps {
			if *exportAppName == ra.Name {
				return &ra, nil
			}
		}
		return nil, fmt.Errorf("app %s is not present in pod", flagExportAppName)
	}

	switch len(apps) {
	case 0:
		return nil, fmt.Errorf("pod contains zero apps")
	case 1:
		return &apps[0], nil
	default:
	}

	stderr.Print("pod contains multiple apps:")
	for _, ra := range apps {
		stderr.Printf("\t%v", ra.Name)
	}

	return nil, fmt.Errorf("specify app using \"rkt export --app= ...\"")
}
Beispiel #4
0
// AddMount will add a mount point with the given name and path to the untarred
// ACI stored at a.CurrentACIPath. If the mount point already exists its value
// will be updated to the new value. readOnly signifies whether or not the
// mount point should be read only.
func (a *ACBuild) AddMount(name, path string, readOnly bool) (err error) {
	if err = a.lock(); err != nil {
		return err
	}
	defer func() {
		if err1 := a.unlock(); err == nil {
			err = err1
		}
	}()

	acn, err := types.NewACName(name)
	if err != nil {
		return err
	}

	fn := func(s *schema.ImageManifest) error {
		removeMount(*acn)(s)
		if s.App == nil {
			s.App = newManifestApp()
		}
		s.App.MountPoints = append(s.App.MountPoints,
			types.MountPoint{
				Name:     *acn,
				Path:     path,
				ReadOnly: readOnly,
			})
		return nil
	}
	return util.ModifyManifest(fn, a.CurrentACIPath)
}
Beispiel #5
0
func handleAppAnnotations(w http.ResponseWriter, r *http.Request, pm *schema.PodManifest, im *schema.ImageManifest) {
	defer r.Body.Close()

	n := mux.Vars(r)["app"]
	an, err := types.NewACName(n)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		fmt.Fprintf(w, "App name %q is not a valid AC Name", n)
		return
	}

	anno := mergeAppAnnotations(im, pm, an)
	out, err := anno.MarshalJSON()

	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		fmt.Fprint(w, err.Error())
		return
	}

	w.Header().Add("Content-Type", "application/json")
	w.WriteHeader(http.StatusOK)
	w.Write(out)

}
Beispiel #6
0
// AddPort will add a port with the given name, protocol, port, and count to
// the untarred ACI stored at a.CurrentACIPath. If the port already exists its
// value will be updated to the new value. socketActivated signifies whether or
// not the application will be socket activated via this port.
func (a *ACBuild) AddPort(name, protocol string, port, count uint, socketActivated bool) (err error) {
	if err = a.lock(); err != nil {
		return err
	}
	defer func() {
		if err1 := a.unlock(); err == nil {
			err = err1
		}
	}()

	acn, err := types.NewACName(name)
	if err != nil {
		return err
	}

	fn := func(s *schema.ImageManifest) error {
		if s.App == nil {
			s.App = newManifestApp()
		}
		removePort(*acn)(s)
		s.App.Ports = append(s.App.Ports,
			types.Port{
				Name:            *acn,
				Protocol:        protocol,
				Port:            port,
				Count:           count,
				SocketActivated: socketActivated,
			})
		return nil
	}
	return util.ModifyManifest(fn, a.CurrentACIPath)
}
Beispiel #7
0
// getAppName returns the app name to enter
// If one was supplied in the flags then it's simply returned
// If the PM contains a single app, that app's name is returned
// If the PM has multiple apps, the names are printed and an error is returned
func getAppName(p *pod) (*types.ACName, error) {
	if flagAppName != "" {
		return types.NewACName(flagAppName)
	}

	// figure out the app name, or show a list if multiple are present
	b, err := ioutil.ReadFile(common.PodManifestPath(p.path()))
	if err != nil {
		return nil, errwrap.Wrap(errors.New("error reading pod manifest"), err)
	}

	m := schema.PodManifest{}
	if err = m.UnmarshalJSON(b); err != nil {
		return nil, errwrap.Wrap(errors.New("invalid pod manifest"), err)
	}

	switch len(m.Apps) {
	case 0:
		return nil, fmt.Errorf("pod contains zero apps")
	case 1:
		return &m.Apps[0].Name, nil
	default:
	}

	stderr.Print("pod contains multiple apps:")
	for _, ra := range m.Apps {
		stderr.Printf("\t%v", ra.Name)
	}

	return nil, fmt.Errorf("specify app using \"rkt enter --app= ...\"")
}
Beispiel #8
0
func handleAppAnnotation(w http.ResponseWriter, r *http.Request, pm *schema.PodManifest, im *schema.ImageManifest) {
	defer r.Body.Close()

	n := mux.Vars(r)["name"]
	k, err := types.NewACIdentifier(n)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		fmt.Fprintf(w, "App annotation name %q is not a valid AC Identifier", n)
		return
	}

	n = mux.Vars(r)["app"]
	an, err := types.NewACName(n)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		fmt.Fprintf(w, "App name %q is not a valid AC Name", n)
		return
	}

	merged := mergeAppAnnotations(im, pm, an)

	v, ok := merged.Get(k.String())
	if !ok {
		w.WriteHeader(http.StatusNotFound)
		fmt.Fprintf(w, "App annotation %q not found", k)
		return
	}

	w.Header().Add("Content-Type", "text/plain")
	w.WriteHeader(http.StatusOK)
	w.Write([]byte(v))
}
Beispiel #9
0
func main() {
	flag.Parse()

	stage1initcommon.InitDebug(debug)

	log, diag, _ = rktlog.NewLogSet("app-start", debug)
	if !debug {
		diag.SetOutput(ioutil.Discard)
	}

	appName, err := types.NewACName(flagApp)
	if err != nil {
		log.FatalE("invalid app name", err)
	}

	enterCmd := stage1common.PrepareEnterCmd(false)

	args := enterCmd
	args = append(args, "/usr/bin/systemctl")
	args = append(args, "start")
	args = append(args, appName.String())

	cmd := exec.Cmd{
		Path: args[0],
		Args: args,
	}

	if out, err := cmd.CombinedOutput(); err != nil {
		log.Fatalf("%q failed to start:\n%s", appName, out)
	}

	os.Exit(0)
}
Beispiel #10
0
// Entry point of oci2aci,
// First convert oci layout to aci layout, then build aci layout to image.
func RunOCI2ACI(args []string, flagDebug bool, flagName string) error {
	var srcPath, dstPath string

	srcPath = args[0]
	if len(args) == 1 {
		dstPath = ""
	} else {
		dstPath = args[1]
		ext := filepath.Ext(dstPath)
		if ext != schema.ACIExtension {
			errStr := fmt.Sprintf("Extension must be %s (given %s)", schema.ACIExtension, ext)
			err := errors.New(errStr)
			return err
		}
	}

	if flagDebug {
		logrus.SetLevel(logrus.DebugLevel)
	} else {
		logrus.SetLevel(logrus.InfoLevel)
	}

	manifestName = flagName
	_, err := types.NewACName(manifestName)
	if err != nil {
		return err
	}

	if bValidate := validateOCIProc(srcPath); bValidate != true {
		logrus.Infof("Conversion stop.")
		return nil
	}

	dirWork := createWorkDir()
	// First, convert layout
	manifestPath, err := convertLayout(srcPath, dirWork)
	if err != nil {
		logrus.Debugf("Conversion from oci to aci layout failed: %v", err)
	} else {
		logrus.Debugf("Manifest:%v generated successfully.", manifestPath)
	}
	// Second, build image
	imgPath, err := buildACI(dirWork)
	if err != nil {
		logrus.Debugf("Generate aci image failed:%v", err)
	} else {
		logrus.Debugf("Image:%v generated successfully.", imgPath)
	}
	// Save aci image to the path user specified
	if dstPath != "" {
		if err = run(exec.Command("cp", imgPath, dstPath)); err != nil {
			logrus.Debugf("Store aci image failed:%v", err)
		} else {
			logrus.Debugf("Image:%v generated successfully", dstPath)
		}
	}

	return nil
}
Beispiel #11
0
func runAppStart(cmd *cobra.Command, args []string) (exit int) {
	if len(args) < 1 {
		stderr.Print("must provide the pod UUID")
		return 1
	}

	if flagAppName == "" {
		stderr.Print("must provide the app to start")
		return 1
	}

	p, err := pkgPod.PodFromUUIDString(getDataDir(), args[0])
	if err != nil {
		stderr.PrintE("problem retrieving pod", err)
		return 1
	}
	defer p.Close()

	if p.State() != pkgPod.Running {
		stderr.Printf("pod %q isn't currently running", p.UUID)
		return 1
	}

	appName, err := types.NewACName(flagAppName)
	if err != nil {
		stderr.PrintE("invalid app name", err)
	}

	podPID, err := p.ContainerPid1()
	if err != nil {
		stderr.PrintE(fmt.Sprintf("unable to determine the pid for pod %q", p.UUID), err)
		return 1
	}

	cfg := stage0.CommonConfig{
		DataDir: getDataDir(),
		UUID:    p.UUID,
		Debug:   globalFlags.Debug,
	}

	scfg := stage0.StartConfig{
		CommonConfig: &cfg,
		PodPath:      p.Path(),
		AppName:      appName,
		PodPID:       podPID,
	}

	if globalFlags.Debug {
		stage0.InitDebug()
	}

	err = stage0.StartApp(scfg)
	if err != nil {
		stderr.PrintE("error starting app", err)
		return 1
	}

	return 0
}
Beispiel #12
0
func (aci *Aci) buildTestAci() (string, error) {
	manifest, err := common.ExtractManifestFromAci(aci.target + common.PathImageAci)
	if err != nil {
		return "", errs.WithEF(err, aci.fields.WithField("file", aci.target+common.PathImageAci), "Failed to extract manifest from aci")
	}

	name := prefixTest + manifest.Name.String()
	if version, ok := manifest.Labels.Get("version"); ok {
		name += ":" + version
	}

	fullname := common.NewACFullName(name)
	resultMountName, _ := types.NewACName(mountAcname)

	aciManifest := &common.AciManifest{
		Builder: aci.manifest.Tester.Builder,
		Aci: common.AciDefinition{
			App: common.DgrApp{
				Exec:              aci.manifest.Aci.App.Exec,
				MountPoints:       []types.MountPoint{{Path: pathTestsResult, Name: *resultMountName}},
				WorkingDirectory:  aci.manifest.Aci.App.WorkingDirectory,
				User:              aci.manifest.Aci.App.User,
				Group:             aci.manifest.Aci.App.Group,
				SupplementaryGIDs: aci.manifest.Aci.App.SupplementaryGIDs,
				Environment:       aci.manifest.Aci.App.Environment,
				Ports:             aci.manifest.Aci.App.Ports,
				Isolators:         aci.manifest.Aci.App.Isolators,
			},
			Dependencies:  append(aci.manifest.Tester.Aci.Dependencies, *common.NewACFullName(name[len(prefixTest):])),
			Annotations:   aci.manifest.Aci.Annotations,
			PathWhitelist: aci.manifest.Aci.PathWhitelist,
		},
		NameAndVersion: *fullname,
	}

	content, err := yaml.Marshal(aciManifest)
	if err != nil {
		return "", errs.WithEF(err, aci.fields, "Failed to marshall manifest for test aci")
	}

	testAci, err := NewAciWithManifest(aci.path, aci.args, string(content), aci.checkWg)
	if err != nil {
		return "", errs.WithEF(err, aci.fields, "Failed to prepare test's build aci")
	}

	testAci.FullyResolveDep = false // this is required to run local tests without discovery
	testAci.target = aci.target + pathTestsTarget

	if err := testAci.CleanAndBuild(); err != nil {
		return "", errs.WithEF(err, aci.fields, "Build of test aci failed")
	}
	hash, err := Home.Rkt.Fetch(aci.target + pathTestsTarget + pathImageAci)
	if err != nil {
		return "", errs.WithEF(err, aci.fields, "fetch of test aci failed")
	}
	return hash, nil
}
Beispiel #13
0
func (mf *MountsFlag) Set(val string) error {
	mnt := schema.Mount{}
	pieces := strings.SplitN(val, ":", 2)
	if name, err := types.NewACName(pieces[0]); err != nil {
		return err
	} else {
		mnt.Volume = *name
	}
	if len(pieces) == 1 {
		mnt.MountPoint = mnt.Volume
	} else if name, err := types.NewACName(pieces[1]); err != nil {
		return err
	} else {
		mnt.MountPoint = *name
	}
	*mf = append(*mf, mnt)
	return nil
}
Beispiel #14
0
func (p *Pod) processAci(e common.RuntimeApp) (*schema.RuntimeApp, error) {
	aci, err := p.buildAci(e)
	if err != nil {
		return nil, err
	}

	name, err := types.NewACName(e.Name)
	if err != nil {
		return nil, errs.WithEF(err, p.fields.WithField("name", e.Name), "Invalid name format")
	}

	sum, err := Sha512sum(aci.target + pathImageAci)
	if err != nil {
		return nil, errs.WithEF(err, p.fields.WithField("file", aci.target+pathImageAci), "Failed to calculate sha512 of aci")
	}

	tmp, _ := types.NewHash("sha512-" + sum)

	labels := types.Labels{}
	labels = append(labels, types.Label{Name: "version", Value: aci.manifest.NameAndVersion.Version()})
	identifier, _ := types.NewACIdentifier(aci.manifest.NameAndVersion.Name())
	ttmp := schema.RuntimeImage{Name: identifier, ID: *tmp, Labels: labels}

	e.App.Group = aci.manifest.Aci.App.Group
	e.App.User = aci.manifest.Aci.App.User
	if e.App.User == "" {
		e.App.User = "******"
	}
	if e.App.Group == "" {
		e.App.Group = "0"
	}

	isolators, err := common.ToAppcIsolators(e.App.Isolators)
	if err != nil {
		return nil, errs.WithEF(err, p.fields, "Failed to prepare isolators")
	}

	return &schema.RuntimeApp{
		Name:  *name,
		Image: ttmp,
		App: &types.App{
			Exec:              e.App.Exec,
			User:              e.App.User,
			Group:             e.App.Group,
			WorkingDirectory:  e.App.WorkingDirectory,
			SupplementaryGIDs: e.App.SupplementaryGIDs,
			Environment:       e.App.Environment,
			MountPoints:       e.App.MountPoints,
			Ports:             e.App.Ports,
			Isolators:         isolators,
		},
		Mounts:      e.Mounts,
		Annotations: e.Annotations}, nil
}
Beispiel #15
0
func (apl *appPortList) Set(s string) error {
	parts := strings.SplitN(s, ":", 5)
	if len(parts) != 5 {
		return fmt.Errorf("--port invalid format")
	}

	// parsey parsey
	name, err := types.NewACName(parts[0])
	if err != nil {
		return err
	}

	proto := parts[1]
	switch proto {
	case "tcp", "udp":
	default:
		return fmt.Errorf("invalid protocol %q", proto)
	}

	p, err := strconv.ParseUint(parts[2], 10, 16)
	if err != nil {
		return err
	}
	podPortNo := uint(p)

	ip := net.ParseIP(parts[3])
	if ip == nil {
		return fmt.Errorf("could not parse IP %q", ip)
	}

	p, err = strconv.ParseUint(parts[4], 10, 16)
	if err != nil {
		return err
	}
	hostPortNo := uint(p)

	podSide := types.Port{
		Name:            *name,
		Protocol:        proto,
		Port:            podPortNo,
		Count:           1,
		SocketActivated: false,
	}

	hostSide := types.ExposedPort{
		Name:     *name,
		HostPort: hostPortNo,
		HostIP:   ip,
		PodPort:  &podSide,
	}

	*apl = append(*apl, hostSide)
	return nil
}
Beispiel #16
0
func (p *Pod) processAci() []schema.RuntimeApp {
	apps := []schema.RuntimeApp{}
	for _, e := range p.manifest.Pod.Apps {

		aciName := p.buildAciIfNeeded(e)
		// TODO: support not FS override by only storing info pod manifest
		//		if aciName == nil {
		//			aciName = &e.Image
		//		}

		name, _ := types.NewACName(e.Name)

		sum, err := utils.Sha512sum(p.path + "/" + e.Name + "/target/image.aci")
		if err != nil {
			log.Get().Panic(err)
		}

		tmp, _ := types.NewHash("sha512-" + sum)

		labels := types.Labels{}
		labels = append(labels, types.Label{Name: "version", Value: aciName.Version()})
		identifier, _ := types.NewACIdentifier(aciName.Name())
		ttmp := schema.RuntimeImage{Name: identifier, ID: *tmp, Labels: labels}

		if e.App.User == "" {
			e.App.User = "******"
		}
		if e.App.Group == "" {
			e.App.Group = "0"
		}

		apps = append(apps, schema.RuntimeApp{
			Name:  *name,
			Image: ttmp,
			App: &types.App{
				Exec:             e.App.Exec,
				EventHandlers:    e.App.EventHandlers,
				User:             e.App.User,
				Group:            e.App.Group,
				WorkingDirectory: e.App.WorkingDirectory,
				Environment:      e.App.Environment,
				MountPoints:      e.App.MountPoints,
				Ports:            e.App.Ports,
				Isolators:        e.App.Isolators,
			},
			Mounts:      e.Mounts,
			Annotations: e.Annotations})

	}

	return apps
}
Beispiel #17
0
func (p *Pod) processAci() []schema.RuntimeApp {
	apps := []schema.RuntimeApp{}
	for _, e := range p.manifest.Pod.Apps {

		aci := p.buildAci(e)

		name, _ := types.NewACName(e.Name)

		sum, err := utils.Sha512sum(aci.target + "/image.aci")
		if err != nil {
			panic(err)
		}

		tmp, _ := types.NewHash("sha512-" + sum)

		labels := types.Labels{}
		labels = append(labels, types.Label{Name: "version", Value: aci.manifest.NameAndVersion.Version()})
		identifier, _ := types.NewACIdentifier(aci.manifest.NameAndVersion.Name())
		ttmp := schema.RuntimeImage{Name: identifier, ID: *tmp, Labels: labels}

		if e.App.User == "" {
			e.App.User = "******"
		}
		if e.App.Group == "" {
			e.App.Group = "0"
		}

		apps = append(apps, schema.RuntimeApp{
			Name:  *name,
			Image: ttmp,
			App: &types.App{
				Exec:             e.App.Exec,
				User:             e.App.User,
				Group:            e.App.Group,
				WorkingDirectory: e.App.WorkingDirectory,
				Environment:      e.App.Environment,
				MountPoints:      e.App.MountPoints,
				Ports:            e.App.Ports,
				Isolators:        e.App.Isolators,
			},
			Mounts:      e.Mounts,
			Annotations: e.Annotations})
	}

	return apps
}
Beispiel #18
0
func (cnt *Img) prepareTestAci() (*Img, error) {
	files, err := ioutil.ReadDir(cnt.path + PATH_TESTS)
	if err != nil {
		return nil, err
	}

	utils.CopyDir(cnt.path+PATH_TESTS+PATH_FILES, cnt.target+PATH_TESTS+PATH_FILES)
	utils.CopyDir(cnt.path+PATH_TESTS+PATH_ATTRIBUTES, cnt.target+PATH_TESTS+PATH_ATTRIBUTES)
	utils.CopyDir(cnt.path+PATH_TESTS+PATH_CONFD, cnt.target+PATH_TESTS+PATH_CONFD)
	utils.CopyDir(cnt.path+PATH_TESTS+PATH_RUNLEVELS, cnt.target+PATH_TESTS+PATH_RUNLEVELS)

	os.MkdirAll(cnt.target+PATH_TESTS+PATH_FILES+PATH_TESTS, 0777)
	for _, f := range files {
		if !f.IsDir() {
			if err := utils.CopyFile(cnt.path+PATH_TESTS+"/"+f.Name(), cnt.target+PATH_TESTS+PATH_FILES+PATH_TESTS+"/"+f.Name()); err != nil {
				panic(err)
			}
		}
	}

	ExecScript := strings.Replace(TEST_INIT_SCRIPT, "%%COMMAND%%", "'"+strings.Join(cnt.manifest.Aci.App.Exec, "' '")+"'", 1)
	ExecScript = strings.Replace(ExecScript, "%%CWD%%", "'"+cnt.manifest.Aci.App.WorkingDirectory+"'", 2)

	ioutil.WriteFile(cnt.target+PATH_TESTS+PATH_FILES+"/init.sh", []byte(ExecScript), 0777)

	fullname, err := spec.NewACFullName(cnt.manifest.NameAndVersion.Name() + "_test:" + cnt.manifest.NameAndVersion.Version())
	if err != nil {
		panic(err)
	}

	resultMountName, _ := types.NewACName("result")
	testAci, err := NewAciWithManifest(cnt.target+PATH_TESTS, cnt.args, spec.AciManifest{
		Aci: spec.AciDefinition{
			App: &spec.CntApp{
				Exec:        []string{"/init.sh"},
				MountPoints: []types.MountPoint{{Path: PATH_RESULT, Name: *resultMountName}},
			},
			Dependencies: []spec.ACFullname{BATS_ACI, cnt.manifest.NameAndVersion},
		},
		NameAndVersion: *fullname,
	}, nil)
	if err != nil {
		panic("Cannot build test aci" + err.Error())
	}
	return testAci, nil
}
Beispiel #19
0
// RemoveMount will remove the mount point with the given name from the
// untarred ACI stored at a.CurrentACIPath
func (a *ACBuild) RemoveMount(name string) (err error) {
	if err = a.lock(); err != nil {
		return err
	}
	defer func() {
		if err1 := a.unlock(); err == nil {
			err = err1
		}
	}()

	acn, err := types.NewACName(name)
	if err != nil {
		return err
	}

	return util.ModifyManifest(removeMount(*acn), a.CurrentACIPath)
}
Beispiel #20
0
// AppImageManifest returns an ImageManifest for the app.
func (p *Pod) AppImageManifest(appName string) (*schema.ImageManifest, error) {
	appACName, err := types.NewACName(appName)
	if err != nil {
		return nil, err
	}
	imb, err := ioutil.ReadFile(common.AppImageManifestPath(p.Path(), *appACName))
	if err != nil {
		return nil, err
	}

	aim := &schema.ImageManifest{}
	if err := aim.UnmarshalJSON(imb); err != nil {
		return nil, errwrap.Wrap(fmt.Errorf("invalid image manifest for app %q", appName), err)
	}

	return aim, nil
}
Beispiel #21
0
func handleAppAnnotations(w http.ResponseWriter, r *http.Request, pm *schema.PodManifest, im *schema.ImageManifest) {
	defer r.Body.Close()

	n := mux.Vars(r)["app"]
	an, err := types.NewACName(n)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		fmt.Fprintf(w, "App name %q is not a valid AC Name", n)
		return
	}

	w.Header().Add("Content-Type", "text/plain")
	w.WriteHeader(http.StatusOK)

	for _, annot := range mergeAppAnnotations(im, pm, an) {
		fmt.Fprintln(w, string(annot.Name))
	}
}
Beispiel #22
0
func cmdWrapPodMaybeApp(cmd func(*jetpack.Pod, types.ACName, []string) error) func([]string) error {
	return func(args []string) error {
		if len(args) == 0 {
			return ErrUsage
		}
		pieces := strings.SplitN(args[0], ":", 2)
		if pod, err := getPod(args[0]); err != nil {
			return errors.Trace(err)
		} else {
			if len(pieces) == 1 {
				return cmd(pod, acutil.ACNoName, args[1:])
			} else if appName, err := types.NewACName(pieces[1]); err != nil {
				return errors.Trace(err)
			} else {
				return cmd(pod, *appName, args)
			}
		}
	}
}
Beispiel #23
0
func (epfl *ExposedPortsFlag) Set(val string) error {
	ep := types.ExposedPort{}
	pieces := strings.SplitN(val, "=", 2)
	if name, err := types.NewACName(pieces[0]); err != nil {
		return err
	} else {
		ep.Name = *name
	}
	if len(pieces) == 2 {
		if hp, err := strconv.ParseUint(pieces[1], 10, 0); err != nil {
			return err
		} else {
			ep.HostPort = uint(hp)
		}
	}
	// TODO: check for duplicates? Or do we validate that later (by
	// serializing & reparsing JSON)?
	*epfl = append(*epfl, ep)
	return nil
}
Beispiel #24
0
func handleAppID(w http.ResponseWriter, r *http.Request, pm *schema.PodManifest, im *schema.ImageManifest) {
	defer r.Body.Close()

	n := mux.Vars(r)["app"]
	an, err := types.NewACName(n)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		fmt.Fprintf(w, "App name %q is not a valid AC Name", n)
		return
	}

	w.Header().Add("Content-Type", "text/plain")
	w.WriteHeader(http.StatusOK)
	app := pm.Apps.Get(*an)
	if app == nil {
		// This is impossiple as we have already checked that
		// the image manifest is not nil in the parent function.
		panic("could not find app in manifest!")
	}
	w.Write([]byte(app.Image.ID.String()))
}
Beispiel #25
0
func cmdWrapPodMaybeApp(cmd func(*jetpack.Pod, *jetpack.App, []string) error) func([]string) error {
	return func(args []string) error {
		if len(args) == 0 {
			return ErrUsage
		}
		pieces := strings.SplitN(args[0], ":", 2)
		if pod, err := getPod(pieces[0]); err != nil {
			return errors.Trace(err)
		} else {
			if len(pieces) == 1 {
				return cmd(pod, nil, args[1:])
			} else if appName, err := types.NewACName(pieces[1]); err != nil {
				return errors.Trace(err)
			} else if app := pod.App(*appName); app == nil {
				return jetpack.ErrNotFound
			} else {
				return cmd(pod, app, args[1:])
			}
		}
	}
}
Beispiel #26
0
func (al *appMount) Set(s string) error {
	mount := schema.Mount{}

	// this is intentionally made similar to types.VolumeFromString()
	// TODO(iaguis) use MakeQueryString() when appc/spec#520 is merged
	m, err := url.ParseQuery(strings.Replace(s, ",", "&", -1))
	if err != nil {
		return err
	}

	for key, val := range m {
		if len(val) > 1 {
			return fmt.Errorf("label %s with multiple values %q", key, val)
		}
		switch key {
		case "volume":
			mv, err := types.NewACName(val[0])
			if err != nil {
				return errwrap.Wrap(fmt.Errorf("invalid volume name %q in --mount flag %q", val[0], s), err)
			}
			mount.Volume = *mv
		case "target":
			mount.Path = val[0]
		default:
			return fmt.Errorf("unknown mount parameter %q", key)
		}
	}

	as := (*apps.Apps)(al)
	if as.Count() == 0 {
		as.Mounts = append(as.Mounts, mount)
	} else {
		app := as.Last()
		app.Mounts = append(app.Mounts, mount)
	}

	return nil
}
Beispiel #27
0
// TODO use named flags instead of positional
func main() {
	flag.Parse()

	stage1initcommon.InitDebug(debug)

	log, diag, _ = rktlog.NewLogSet("stage1", debug)
	if !debug {
		diag.SetOutput(ioutil.Discard)
	}

	appName, err := types.NewACName(flag.Arg(1))
	if err != nil {
		log.PrintE("invalid app name", err)
		os.Exit(254)
	}

	enterEP := flag.Arg(2)

	args := []string{enterEP}

	args = append(args, fmt.Sprintf("--pid=%s", flag.Arg(3)))
	args = append(args, "/usr/bin/systemctl")
	args = append(args, "stop")
	args = append(args, appName.String())

	cmd := exec.Cmd{
		Path: args[0],
		Args: args,
	}

	if err := cmd.Run(); err != nil {
		log.PrintE(fmt.Sprintf("error stopping app %q", appName.String()), err)
		os.Exit(254)
	}

	os.Exit(0)
}
Beispiel #28
0
func (pl *portList) Set(s string) error {
	parts := strings.SplitN(s, ":", 2)
	if len(parts) != 2 {
		return fmt.Errorf("%q is not in name:port format", s)
	}

	name, err := types.NewACName(parts[0])
	if err != nil {
		return errwrap.Wrap(fmt.Errorf("%q is not a valid port name", parts[0]), err)
	}

	port, err := strconv.ParseUint(parts[1], 10, 16)
	if err != nil {
		return fmt.Errorf("%q is not a valid port number", parts[1])
	}

	p := types.ExposedPort{
		Name:     *name,
		HostPort: uint(port),
	}

	*pl = append(*pl, p)
	return nil
}
Beispiel #29
0
// makePodManifest transforms a kubelet pod spec to the rkt pod manifest.
// TODO(yifan): Use the RunContainerOptions generated by GenerateRunContainerOptions().
func (r *runtime) makePodManifest(pod *api.Pod) (*appcschema.PodManifest, error) {
	var globalPortMappings []kubecontainer.PortMapping
	manifest := appcschema.BlankPodManifest()

	for _, c := range pod.Spec.Containers {
		imgManifest, err := r.getImageManifest(c.Image)
		if err != nil {
			return nil, err
		}

		if imgManifest.App == nil {
			return nil, fmt.Errorf("no app section in image manifest for image: %q", c.Image)
		}

		img, err := r.getImageByName(c.Image)
		if err != nil {
			return nil, err
		}
		hash, err := appctypes.NewHash(img.id)
		if err != nil {
			return nil, err
		}

		opts, err := r.generator.GenerateRunContainerOptions(pod, &c)
		if err != nil {
			return nil, err
		}

		globalPortMappings = append(globalPortMappings, opts.PortMappings...)

		if err := setApp(imgManifest.App, &c, opts); err != nil {
			return nil, err
		}

		manifest.Apps = append(manifest.Apps, appcschema.RuntimeApp{
			// TODO(yifan): We should allow app name to be different with
			// image name. See https://github.com/coreos/rkt/pull/640.
			Name:  imgManifest.Name,
			Image: appcschema.RuntimeImage{ID: *hash},
			App:   imgManifest.App,
		})
	}

	volumeMap, ok := r.volumeGetter.GetVolumes(pod.UID)
	if !ok {
		return nil, fmt.Errorf("cannot get the volumes for pod %q", kubecontainer.GetPodFullName(pod))
	}

	// Set global volumes.
	for name, volume := range volumeMap {
		volName, err := appctypes.NewACName(name)
		if err != nil {
			return nil, fmt.Errorf("cannot use the volume's name %q as ACName: %v", name, err)
		}
		manifest.Volumes = append(manifest.Volumes, appctypes.Volume{
			Name:   *volName,
			Kind:   "host",
			Source: volume.GetPath(),
		})
	}

	// Set global ports.
	for _, port := range globalPortMappings {
		name, err := appctypes.SanitizeACName(port.Name)
		if err != nil {
			return nil, fmt.Errorf("cannot use the port's name %q as ACName: %v", port.Name, err)
		}
		portName := appctypes.MustACName(name)
		manifest.Ports = append(manifest.Ports, appctypes.ExposedPort{
			Name:     *portName,
			HostPort: uint(port.HostPort),
		})
	}
	// TODO(yifan): Set pod-level isolators once it's supported in kubernetes.
	return manifest, nil
}
Beispiel #30
0
// setApp overrides the app's fields if any of them are specified in the
// container's spec.
func setApp(app *appctypes.App, c *api.Container, opts *kubecontainer.RunContainerOptions) error {
	// Override the exec.
	// TOOD(yifan): Revisit this for the overriding rule.
	if len(c.Command) > 0 || len(c.Args) > 0 {
		app.Exec = append(c.Command, c.Args...)
	}

	// TODO(yifan): Use non-root user in the future, see:
	// https://github.com/coreos/rkt/issues/820
	app.User, app.Group = "0", "0"

	// Override the working directory.
	if len(c.WorkingDir) > 0 {
		app.WorkingDirectory = c.WorkingDir
	}

	// Override the environment.
	if len(opts.Envs) > 0 {
		app.Environment = []appctypes.EnvironmentVariable{}
	}
	for _, env := range c.Env {
		app.Environment = append(app.Environment, appctypes.EnvironmentVariable{
			Name:  env.Name,
			Value: env.Value,
		})
	}

	// Override the mount points.
	if len(opts.Mounts) > 0 {
		app.MountPoints = []appctypes.MountPoint{}
	}
	for _, m := range opts.Mounts {
		mountPointName, err := appctypes.NewACName(m.Name)
		if err != nil {
			return err
		}
		app.MountPoints = append(app.MountPoints, appctypes.MountPoint{
			Name:     *mountPointName,
			Path:     m.ContainerPath,
			ReadOnly: m.ReadOnly,
		})
	}

	// Override the ports.
	if len(opts.PortMappings) > 0 {
		app.Ports = []appctypes.Port{}
	}
	for _, p := range opts.PortMappings {
		name, err := appctypes.SanitizeACName(p.Name)
		if err != nil {
			return err
		}
		portName := appctypes.MustACName(name)
		app.Ports = append(app.Ports, appctypes.Port{
			Name:     *portName,
			Protocol: string(p.Protocol),
			Port:     uint(p.ContainerPort),
		})
	}

	// Override isolators.
	return setIsolators(app, c)
}