func (p *LinuxResourcePool) setupRootfs(spec garden.ContainerSpec, id string, resources *linux_backend.Resources, pLog lager.Logger) (string, process.Env, error) { rootFSURL, err := url.Parse(spec.RootFSPath) if err != nil { pLog.Error("parse-rootfs-path-failed", err, lager.Data{ "RootFSPath": spec.RootFSPath, }) return "", nil, err } rootFSSpec := rootfs_provider.Spec{ RootFS: rootFSURL, Namespaced: resources.RootUID != 0, QuotaSize: int64(spec.Limits.Disk.ByteHard), QuotaScope: rootfs_provider.QuotaScope(spec.Limits.Disk.Scope), } pLog.Debug("provide-rootfs-starting") rootFSPath, rootFSEnvVars, err := p.rootFSProvider.Create(pLog, id, rootFSSpec) if err != nil { pLog.Error("provide-rootfs-failed", err) return "", nil, err } pLog.Debug("provide-rootfs-ended") rootFSProcessEnv, err := process.NewEnv(rootFSEnvVars) if err != nil { pLog.Error("rootfs-env-malformed", err) return "", nil, err } return rootFSPath, rootFSProcessEnv, nil }
func (c *LinuxContainer) Run(spec garden.ProcessSpec, processIO garden.ProcessIO) (garden.Process, error) { wshPath := path.Join(c.ContainerPath, "bin", "wsh") sockPath := path.Join(c.ContainerPath, "run", "wshd.sock") if spec.User == "" { c.logger.Error("linux_container: Run:", errors.New("linux_container: Run: A User for the process to run as must be specified.")) return nil, errors.New("A User for the process to run as must be specified.") } args := []string{"--socket", sockPath, "--readSignals", "--user", spec.User} specEnv, err := process.NewEnv(spec.Env) if err != nil { return nil, err } procEnv, err := process.NewEnv(c.Env) if err != nil { return nil, err } processEnv := procEnv.Merge(specEnv) for _, envVar := range processEnv.Array() { args = append(args, "--env", envVar) } if spec.Dir != "" { args = append(args, "--dir", spec.Dir) } processID := c.processIDPool.Next() c.logger.Info("next pid", lager.Data{"pid": processID}) if c.Version.Compare(MissingVersion) == 0 { pidfile := path.Join(c.ContainerPath, "processes", fmt.Sprintf("%d.pid", processID)) args = append(args, "--pidfile", pidfile) } args = append(args, spec.Path) wsh := exec.Command(wshPath, append(args, spec.Args...)...) setRLimitsEnv(wsh, spec.Limits) return c.processTracker.Run(fmt.Sprintf("%d", processID), wsh, processIO, spec.TTY, c.processSignaller()) }
func (p *LinuxResourcePool) Acquire(spec garden.ContainerSpec) (linux_backend.LinuxContainerSpec, error) { id := <-p.containerIDs containerPath := path.Join(p.depotPath, id) pLog := p.logger.Session(id) pLog.Info("creating") resources, err := p.acquirePoolResources(spec, id) if err != nil { return linux_backend.LinuxContainerSpec{}, err } defer cleanup(&err, func() { p.releasePoolResources(resources) }) pLog.Info("acquired-pool-resources") handle := getHandle(spec.Handle, id) var quota int64 = int64(spec.Limits.Disk.ByteHard) if quota == 0 { quota = math.MaxInt64 } containerRootFSPath, rootFSEnv, err := p.acquireSystemResources(id, handle, containerPath, spec.RootFSPath, resources, spec.BindMounts, quota, pLog) if err != nil { return linux_backend.LinuxContainerSpec{}, err } pLog.Info("created") specEnv, err := process.NewEnv(spec.Env) if err != nil { p.tryReleaseSystemResources(p.logger, id) return linux_backend.LinuxContainerSpec{}, err } pLog.Debug("calculate-environment", lager.Data{ "rootfs-env": rootFSEnv, }) spec.Env = rootFSEnv.Merge(specEnv).Array() spec.Handle = handle return linux_backend.LinuxContainerSpec{ ID: id, ContainerPath: containerPath, ContainerRootFSPath: containerRootFSPath, Resources: resources, Events: []string{}, Version: p.currentContainerVersion, State: linux_backend.StateBorn, ContainerSpec: spec, }, nil }
func filterEnv(env []string, logger lager.Logger) process.Env { var filtered []string for _, e := range env { segs := strings.SplitN(e, "=", 2) if len(segs) != 2 { // malformed docker image metadata? logger.Info("Unrecognised environment variable", lager.Data{"e": e}) continue } filtered = append(filtered, e) } filteredWithNoDups, err := process.NewEnv(filtered) if err != nil { logger.Error("Invalid environment", err) } return filteredWithNoDups }
func createEnvironment(specEnv []string, usr parsedUser) (process.Env, error) { env, err := process.NewEnv(specEnv) if err != nil { return process.Env{}, fmt.Errorf("invalid environment %v: %s", specEnv, err) } env["USER"] = usr.username _, hasHome := env["HOME"] if !hasHome { env["HOME"] = usr.homeDir } _, hasPath := env["PATH"] if !hasPath { if usr.uid == 0 { env["PATH"] = DefaultRootPATH } else { env["PATH"] = DefaultUserPath } } return env, nil }
func (p *LinuxResourcePool) Acquire(spec garden.ContainerSpec) (linux_backend.LinuxContainerSpec, error) { id := <-p.containerIDs containerPath := path.Join(p.depotPath, id) handle := getHandle(spec.Handle, id) pLog := p.logger.Session("acquire", lager.Data{"handle": handle}) iptablesCh := make(chan error, 1) go func(iptablesCh chan error) { pLog.Debug("setup-iptables-starting") if err := p.filterProvider.ProvideFilter(id).Setup(handle); err != nil { pLog.Error("setup-iptables-failed", err) iptablesCh <- fmt.Errorf("resource_pool: set up filter: %v", err) } else { pLog.Debug("setup-iptables-ended") iptablesCh <- nil } }(iptablesCh) pLog.Info("creating") resources, err := p.acquirePoolResources(spec, id, pLog) if err != nil { return linux_backend.LinuxContainerSpec{}, err } defer cleanup(&err, func() { p.releasePoolResources(resources, pLog) }) pLog.Info("acquired-pool-resources") pLog.Info("running-graph-cleanup") if err := p.rootFSProvider.GC(pLog); err != nil { pLog.Error("graph-cleanup-failed", err) } containerRootFSPath, rootFSEnv, err := p.acquireSystemResources( spec, id, resources, pLog, ) if err != nil { return linux_backend.LinuxContainerSpec{}, err } err = <-iptablesCh if err != nil { p.tryReleaseSystemResources(p.logger, id) return linux_backend.LinuxContainerSpec{}, err } pLog.Info("created") specEnv, err := process.NewEnv(spec.Env) if err != nil { p.tryReleaseSystemResources(p.logger, id) return linux_backend.LinuxContainerSpec{}, err } spec.Env = rootFSEnv.Merge(specEnv).Array() spec.Handle = handle return linux_backend.LinuxContainerSpec{ ID: id, ContainerPath: containerPath, ContainerRootFSPath: containerRootFSPath, Resources: resources, Events: []string{}, Version: p.currentContainerVersion, State: linux_backend.StateBorn, ContainerSpec: spec, }, nil }
Context("when the file is empty", func() { It("returns an empty env", func() { cwd, err := os.Getwd() Expect(err).ToNot(HaveOccurred()) pathToTestFile := filepath.Join(cwd, "test-assets", "empty") result, err := process.EnvFromFile(pathToTestFile) Expect(err).ToNot(HaveOccurred()) Expect(result).To(Equal(process.Env{})) }) }) }) Context("when using the constructor", func() { It("can be constructed from an array", func() { env, err := process.NewEnv([]string{ "HOME=/home/alice", "USER=alice", }) Expect(err).ToNot(HaveOccurred()) Expect(env.Array()).To(ConsistOf( "HOME=/home/alice", "USER=alice", )) }) It("removes duplicate entries (last one wins)", func() { env, err := process.NewEnv([]string{ "HOME=/home/wrong", "HOME=/home/alice", }) Expect(err).ToNot(HaveOccurred())