// 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= ...\"") }
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 }
// 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= ...\"") }
// 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) }
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) }
// 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) }
// 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= ...\"") }
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)) }
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) }
// 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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
// 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) }
// 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 }
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)) } }
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) } } } }
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 }
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())) }
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:]) } } } }
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 }
// 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) }
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 }
// 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 }
// 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) }