Merge lp:~wallyworld/golxc/support-cmd-env into lp:golxc

Proposed by Ian Booth
Status: Merged
Approved by: Ian Booth
Approved revision: 15
Merged at revision: 13
Proposed branch: lp:~wallyworld/golxc/support-cmd-env
Merge into: lp:golxc
Diff against target: 812 lines (+203/-160)
4 files modified
golxc.go (+18/-15)
golxc_test.go (+181/-141)
network.go (+3/-3)
package_test.go (+1/-1)
To merge this branch: bzr merge lp:~wallyworld/golxc/support-cmd-env
Reviewer Review Type Date Requested Status
Andrew Wilkins (community) Approve
Review via email: mp+242438@code.launchpad.net

Commit message

Add support for passing environment variables to the container Create command. This can potentially be added to other commands too, but for now is just needed for Create().

Also, the gocheck import was out of date, so was updated.

Description of the change

Add support for passing environment variables to the container Create command. This can potentially be added to other commands too, but for now is just needed for Create().

Also, the gocheck import was out of date, so was updated.

To post a comment you must log in.
Revision history for this message
Andrew Wilkins (axwalk) wrote :

LGTM with comments addressed.

review: Approve
Revision history for this message
Ian Booth (wallyworld) :
lp:~wallyworld/golxc/support-cmd-env updated
14. By Ian Booth

Enahnce test

15. By Ian Booth

Improve comment

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'golxc.go'
--- golxc.go 2014-07-30 01:57:14 +0000
+++ golxc.go 2014-11-21 03:15:57 +0000
@@ -70,7 +70,9 @@
70 Name() string70 Name() string
7171
72 // Create creates a new container based on the given template.72 // Create creates a new container based on the given template.
73 Create(configFile, template string, extraArgs []string, templateArgs []string) error73 // envArgs, if not nil, are assigned to the environment of the process, otherwise the
74 // environment of the current process is used.
75 Create(configFile, template string, extraArgs []string, templateArgs []string, envArgs []string) error
7476
75 // Start runs the container as a daemon.77 // Start runs the container as a daemon.
76 Start(configFile, consoleFile string) error78 Start(configFile, consoleFile string) error
@@ -157,7 +159,7 @@
157159
158// List returns all the existing containers on the system.160// List returns all the existing containers on the system.
159func (factory *containerFactory) List() ([]Container, error) {161func (factory *containerFactory) List() ([]Container, error) {
160 out, err := run("lxc-ls", "-1")162 out, err := run("lxc-ls", nil, "-1")
161 if err != nil {163 if err != nil {
162 return nil, err164 return nil, err
163 }165 }
@@ -192,7 +194,7 @@
192}194}
193195
194// Create creates a new container based on the given template.196// Create creates a new container based on the given template.
195func (c *container) Create(configFile, template string, extraArgs []string, templateArgs []string) error {197func (c *container) Create(configFile, template string, extraArgs []string, templateArgs []string, envArgs []string) error {
196 if c.IsConstructed() {198 if c.IsConstructed() {
197 return fmt.Errorf("container %q is already created", c.Name())199 return fmt.Errorf("container %q is already created", c.Name())
198 }200 }
@@ -212,7 +214,7 @@
212 args = append(args, "--")214 args = append(args, "--")
213 args = append(args, templateArgs...)215 args = append(args, templateArgs...)
214 }216 }
215 _, err := run("lxc-create", args...)217 _, err := run("lxc-create", envArgs, args...)
216 if err != nil {218 if err != nil {
217 return err219 return err
218 }220 }
@@ -238,11 +240,11 @@
238 if consoleFile != "" {240 if consoleFile != "" {
239 startArgs = append(args, "--console-log", consoleFile)241 startArgs = append(args, "--console-log", consoleFile)
240 }242 }
241 _, err := run("lxc-start", startArgs...)243 _, err := run("lxc-start", nil, startArgs...)
242 // We may need to fallback to the older --console arg name.244 // We may need to fallback to the older --console arg name.
243 if err != nil && consoleFile != "" {245 if err != nil && consoleFile != "" {
244 startArgs = append(args, "--console", consoleFile)246 startArgs = append(args, "--console", consoleFile)
245 _, err = run("lxc-start", startArgs...)247 _, err = run("lxc-start", nil, startArgs...)
246 }248 }
247 if err != nil {249 if err != nil {
248 return err250 return err
@@ -271,7 +273,7 @@
271 if c.logFile != "" {273 if c.logFile != "" {
272 args = append(args, "--logfile", c.logFile, "--logpriority", string(c.logLevel))274 args = append(args, "--logfile", c.logFile, "--logpriority", string(c.logLevel))
273 }275 }
274 _, err := run("lxc-stop", args...)276 _, err := run("lxc-stop", nil, args...)
275 if err != nil {277 if err != nil {
276 return err278 return err
277 }279 }
@@ -306,7 +308,7 @@
306 args = append(args, "--")308 args = append(args, "--")
307 args = append(args, templateArgs...)309 args = append(args, templateArgs...)
308 }310 }
309 _, err := run("lxc-clone", args...)311 _, err := run("lxc-clone", nil, args...)
310 if err != nil {312 if err != nil {
311 return nil, err313 return nil, err
312 }314 }
@@ -327,7 +329,7 @@
327 if c.logFile != "" {329 if c.logFile != "" {
328 args = append(args, "--logfile", c.logFile, "--logpriority", string(c.logLevel))330 args = append(args, "--logfile", c.logFile, "--logpriority", string(c.logLevel))
329 }331 }
330 _, err := run("lxc-freeze", args...)332 _, err := run("lxc-freeze", nil, args...)
331 if err != nil {333 if err != nil {
332 return err334 return err
333 }335 }
@@ -348,7 +350,7 @@
348 if c.logFile != "" {350 if c.logFile != "" {
349 args = append(args, "--logfile", c.logFile, "--logpriority", string(c.logLevel))351 args = append(args, "--logfile", c.logFile, "--logpriority", string(c.logLevel))
350 }352 }
351 _, err := run("lxc-unfreeze", args...)353 _, err := run("lxc-unfreeze", nil, args...)
352 if err != nil {354 if err != nil {
353 return err355 return err
354 }356 }
@@ -363,7 +365,7 @@
363 if err := c.Stop(); err != nil {365 if err := c.Stop(); err != nil {
364 return err366 return err
365 }367 }
366 _, err := run("lxc-destroy", "-n", c.name)368 _, err := run("lxc-destroy", nil, "-n", c.name)
367 if err != nil {369 if err != nil {
368 return err370 return err
369 }371 }
@@ -380,7 +382,7 @@
380 stateStrs[i] = string(state)382 stateStrs[i] = string(state)
381 }383 }
382 waitStates := strings.Join(stateStrs, "|")384 waitStates := strings.Join(stateStrs, "|")
383 _, err := run("lxc-wait", "--name", c.name, "--state", waitStates)385 _, err := run("lxc-wait", nil, "--name", c.name, "--state", waitStates)
384 if err != nil {386 if err != nil {
385 return err387 return err
386 }388 }
@@ -389,7 +391,7 @@
389391
390// Info returns the status and the process id of the container.392// Info returns the status and the process id of the container.
391func (c *container) Info() (State, int, error) {393func (c *container) Info() (State, int, error) {
392 out, err := run("lxc-info", "--name", c.name)394 out, err := run("lxc-info", nil, "--name", c.name)
393 if err != nil {395 if err != nil {
394 return StateUnknown, -1, err396 return StateUnknown, -1, err
395 }397 }
@@ -441,10 +443,11 @@
441}443}
442444
443// run executes the passed command and returns the out.445// run executes the passed command and returns the out.
444func run(name string, args ...string) (string, error) {446func run(name string, env []string, args ...string) (string, error) {
445 logger := loggo.GetLogger(fmt.Sprintf("golxc.run.%s", name))447 logger := loggo.GetLogger(fmt.Sprintf("golxc.run.%s", name))
446 logger.Tracef("run: %s %v", name, args)448 logger.Tracef("run: %s %v", name, args)
447 cmd := exec.Command(name, args...)449 cmd := exec.Command(name, args...)
450 cmd.Env = env
448 // LXC tools do not use stdout and stderr in a predictable451 // LXC tools do not use stdout and stderr in a predictable
449 // way; based on experimentation, the most convenient452 // way; based on experimentation, the most convenient
450 // solution is to combine them and leave the client to453 // solution is to combine them and leave the client to
@@ -510,7 +513,7 @@
510// GetDefaultLXCContainerDir returns the current lxc.lxcpath value otherwise513// GetDefaultLXCContainerDir returns the current lxc.lxcpath value otherwise
511// the const DefaultLXCDir is returned.514// the const DefaultLXCDir is returned.
512func GetDefaultLXCContainerDir() string {515func GetDefaultLXCContainerDir() string {
513 result, err := run("lxc-config", "lxc.lxcpath")516 result, err := run("lxc-config", nil, "lxc.lxcpath")
514517
515 if err != nil {518 if err != nil {
516 return DefaultLXCDir519 return DefaultLXCDir
517520
=== modified file 'golxc_test.go'
--- golxc_test.go 2014-07-30 01:57:14 +0000
+++ golxc_test.go 2014-11-21 03:15:57 +0000
@@ -11,7 +11,7 @@
1111
12 "github.com/juju/testing"12 "github.com/juju/testing"
13 jc "github.com/juju/testing/checkers"13 jc "github.com/juju/testing/checkers"
14 . "launchpad.net/gocheck"14 gc "gopkg.in/check.v1"
1515
16 "launchpad.net/golxc"16 "launchpad.net/golxc"
17)17)
@@ -52,154 +52,154 @@
5252
53type ConfigSuite struct{}53type ConfigSuite struct{}
5454
55var _ = Suite(&ConfigSuite{})55var _ = gc.Suite(&ConfigSuite{})
5656
57func (s *ConfigSuite) TestReadConf(c *C) {57func (s *ConfigSuite) TestReadConf(c *gc.C) {
58 // Test reading the configuration.58 // Test reading the configuration.
59 cf := filepath.Join(c.MkDir(), "lxc-test")59 cf := filepath.Join(c.MkDir(), "lxc-test")
60 c.Assert(ioutil.WriteFile(cf, []byte(lxcfile), 0555), IsNil)60 c.Assert(ioutil.WriteFile(cf, []byte(lxcfile), 0555), gc.IsNil)
6161
62 defer golxc.SetConfPath(golxc.SetConfPath(cf))62 defer golxc.SetConfPath(golxc.SetConfPath(cf))
6363
64 conf, err := golxc.ReadConf()64 conf, err := golxc.ReadConf()
65 c.Assert(err, IsNil)65 c.Assert(err, gc.IsNil)
66 c.Assert(conf, DeepEquals, lxcconf)66 c.Assert(conf, gc.DeepEquals, lxcconf)
67}67}
6868
69func (s *ConfigSuite) TestReadNotExistingDefaultEnvironment(c *C) {69func (s *ConfigSuite) TestReadNotExistingDefaultEnvironment(c *gc.C) {
70 // Test reading a not existing environment.70 // Test reading a not existing environment.
71 defer golxc.SetConfPath(golxc.SetConfPath(filepath.Join(c.MkDir(), "foo")))71 defer golxc.SetConfPath(golxc.SetConfPath(filepath.Join(c.MkDir(), "foo")))
7272
73 _, err := golxc.ReadConf()73 _, err := golxc.ReadConf()
74 c.Assert(err, ErrorMatches, "open .*: no such file or directory")74 c.Assert(err, gc.ErrorMatches, "open .*: no such file or directory")
75}75}
7676
77func (s *ConfigSuite) TestNetworkAttributes(c *C) {77func (s *ConfigSuite) TestNetworkAttributes(c *gc.C) {
78 // Test reading the network attribute form an environment.78 // Test reading the network attribute form an environment.
79 cf := filepath.Join(c.MkDir(), "lxc-test")79 cf := filepath.Join(c.MkDir(), "lxc-test")
80 c.Assert(ioutil.WriteFile(cf, []byte(lxcfile), 0555), IsNil)80 c.Assert(ioutil.WriteFile(cf, []byte(lxcfile), 0555), gc.IsNil)
8181
82 defer golxc.SetConfPath(golxc.SetConfPath(cf))82 defer golxc.SetConfPath(golxc.SetConfPath(cf))
8383
84 addr, bridge, err := golxc.NetworkAttributes()84 addr, bridge, err := golxc.NetworkAttributes()
85 c.Assert(err, IsNil)85 c.Assert(err, gc.IsNil)
86 c.Assert(addr, Equals, "10.0.9.1")86 c.Assert(addr, gc.Equals, "10.0.9.1")
87 c.Assert(bridge, Equals, "lxcbr9")87 c.Assert(bridge, gc.Equals, "lxcbr9")
88}88}
8989
90type NetworkSuite struct{}90type NetworkSuite struct{}
9191
92var _ = Suite(&NetworkSuite{})92var _ = gc.Suite(&NetworkSuite{})
9393
94func (s *NetworkSuite) SetUpSuite(c *C) {94func (s *NetworkSuite) SetUpSuite(c *gc.C) {
95 u, err := user.Current()95 u, err := user.Current()
96 c.Assert(err, IsNil)96 c.Assert(err, gc.IsNil)
97 if u.Uid != "0" {97 if u.Uid != "0" {
98 // Has to be run as root!98 // Has to be run as root!
99 c.Skip("tests must run as root")99 c.Skip("tests must run as root")
100 }100 }
101}101}
102102
103func (s *NetworkSuite) TestStartStopNetwork(c *C) {103func (s *NetworkSuite) TestStartStopNetwork(c *gc.C) {
104 // Test starting and stoping of the LXC network.104 // Test starting and stoping of the LXC network.
105 initialRunning, err := golxc.IsNetworkRunning()105 initialRunning, err := golxc.IsNetworkRunning()
106 c.Assert(err, IsNil)106 c.Assert(err, gc.IsNil)
107 defer func() {107 defer func() {
108 if initialRunning {108 if initialRunning {
109 c.Assert(golxc.StartNetwork(), IsNil)109 c.Assert(golxc.StartNetwork(), gc.IsNil)
110 }110 }
111 }()111 }()
112 c.Assert(golxc.StartNetwork(), IsNil)112 c.Assert(golxc.StartNetwork(), gc.IsNil)
113 running, err := golxc.IsNetworkRunning()113 running, err := golxc.IsNetworkRunning()
114 c.Assert(err, IsNil)114 c.Assert(err, gc.IsNil)
115 c.Assert(running, Equals, true)115 c.Assert(running, gc.Equals, true)
116 c.Assert(golxc.StopNetwork(), IsNil)116 c.Assert(golxc.StopNetwork(), gc.IsNil)
117 running, err = golxc.IsNetworkRunning()117 running, err = golxc.IsNetworkRunning()
118 c.Assert(err, IsNil)118 c.Assert(err, gc.IsNil)
119 c.Assert(running, Equals, false)119 c.Assert(running, gc.Equals, false)
120}120}
121121
122func (s *NetworkSuite) TestNotExistingNetworkAttributes(c *C) {122func (s *NetworkSuite) TestNotExistingNetworkAttributes(c *gc.C) {
123 // Test reading of network attributes from a not existing environment.123 // Test reading of network attributes from a not existing environment.
124 defer golxc.SetConfPath(golxc.SetConfPath(filepath.Join(c.MkDir(), "foo")))124 defer golxc.SetConfPath(golxc.SetConfPath(filepath.Join(c.MkDir(), "foo")))
125125
126 _, _, err := golxc.NetworkAttributes()126 _, _, err := golxc.NetworkAttributes()
127 c.Assert(err, ErrorMatches, "open .*: no such file or directory")127 c.Assert(err, gc.ErrorMatches, "open .*: no such file or directory")
128}128}
129129
130type LXCSuite struct {130type LXCSuite struct {
131 factory golxc.ContainerFactory131 factory golxc.ContainerFactory
132}132}
133133
134var _ = Suite(&LXCSuite{golxc.Factory()})134var _ = gc.Suite(&LXCSuite{golxc.Factory()})
135135
136func (s *LXCSuite) SetUpSuite(c *C) {136func (s *LXCSuite) SetUpSuite(c *gc.C) {
137 u, err := user.Current()137 u, err := user.Current()
138 c.Assert(err, IsNil)138 c.Assert(err, gc.IsNil)
139 if u.Uid != "0" {139 if u.Uid != "0" {
140 // Has to be run as root!140 // Has to be run as root!
141 c.Skip("tests must run as root")141 c.Skip("tests must run as root")
142 }142 }
143}143}
144144
145func (s *LXCSuite) createContainer(c *C) golxc.Container {145func (s *LXCSuite) createContainer(c *gc.C) golxc.Container {
146 container := s.factory.New("golxc")146 container := s.factory.New("golxc")
147 c.Assert(container.IsConstructed(), Equals, false)147 c.Assert(container.IsConstructed(), gc.Equals, false)
148 err := container.Create("", "ubuntu", nil, nil)148 err := container.Create("", "ubuntu", nil, nil, nil)
149 c.Assert(err, IsNil)149 c.Assert(err, gc.IsNil)
150 c.Assert(container.IsConstructed(), Equals, true)150 c.Assert(container.IsConstructed(), gc.Equals, true)
151 return container151 return container
152}152}
153153
154func (s *LXCSuite) TestCreateDestroy(c *C) {154func (s *LXCSuite) TestCreateDestroy(c *gc.C) {
155 // Test clean creation and destroying of a container.155 // Test clean creation and destroying of a container.
156 lc := s.factory.New("golxc")156 lc := s.factory.New("golxc")
157 c.Assert(lc.IsConstructed(), Equals, false)157 c.Assert(lc.IsConstructed(), gc.Equals, false)
158 home := golxc.ContainerHome(lc)158 home := golxc.ContainerHome(lc)
159 _, err := os.Stat(home)159 _, err := os.Stat(home)
160 c.Assert(err, ErrorMatches, "stat .*: no such file or directory")160 c.Assert(err, gc.ErrorMatches, "stat .*: no such file or directory")
161 err = lc.Create("", "ubuntu", nil, nil)161 err = lc.Create("", "ubuntu", nil, nil, nil)
162 c.Assert(err, IsNil)162 c.Assert(err, gc.IsNil)
163 c.Assert(lc.IsConstructed(), Equals, true)163 c.Assert(lc.IsConstructed(), gc.Equals, true)
164 defer func() {164 defer func() {
165 err = lc.Destroy()165 err = lc.Destroy()
166 c.Assert(err, IsNil)166 c.Assert(err, gc.IsNil)
167 _, err = os.Stat(home)167 _, err = os.Stat(home)
168 c.Assert(err, ErrorMatches, "stat .*: no such file or directory")168 c.Assert(err, gc.ErrorMatches, "stat .*: no such file or directory")
169 }()169 }()
170 fi, err := os.Stat(golxc.ContainerHome(lc))170 fi, err := os.Stat(golxc.ContainerHome(lc))
171 c.Assert(err, IsNil)171 c.Assert(err, gc.IsNil)
172 c.Assert(fi.IsDir(), Equals, true)172 c.Assert(fi.IsDir(), gc.Equals, true)
173}173}
174174
175func (s *LXCSuite) TestCreateTwice(c *C) {175func (s *LXCSuite) TestCreateTwice(c *gc.C) {
176 // Test that a container cannot be created twice.176 // Test that a container cannot be created twice.
177 lc1 := s.createContainer(c)177 lc1 := s.createContainer(c)
178 c.Assert(lc1.IsConstructed(), Equals, true)178 c.Assert(lc1.IsConstructed(), gc.Equals, true)
179 defer func() {179 defer func() {
180 c.Assert(lc1.Destroy(), IsNil)180 c.Assert(lc1.Destroy(), gc.IsNil)
181 }()181 }()
182 lc2 := s.factory.New("golxc")182 lc2 := s.factory.New("golxc")
183 err := lc2.Create("", "ubuntu", nil, nil)183 err := lc2.Create("", "ubuntu", nil, nil, nil)
184 c.Assert(err, ErrorMatches, "container .* is already created")184 c.Assert(err, gc.ErrorMatches, "container .* is already created")
185}185}
186186
187func (s *LXCSuite) TestCreateIllegalTemplate(c *C) {187func (s *LXCSuite) TestCreateIllegalTemplate(c *gc.C) {
188 // Test that a container creation fails correctly in188 // Test that a container creation fails correctly in
189 // case of an illegal template.189 // case of an illegal template.
190 lc := s.factory.New("golxc")190 lc := s.factory.New("golxc")
191 c.Assert(lc.IsConstructed(), Equals, false)191 c.Assert(lc.IsConstructed(), gc.Equals, false)
192 err := lc.Create("", "name-of-a-not-existing-template-for-golxc", nil, nil)192 err := lc.Create("", "name-of-a-not-existing-template-for-golxc", nil, nil, nil)
193 c.Assert(err, ErrorMatches, `error executing "lxc-create": .*bad template.*`)193 c.Assert(err, gc.ErrorMatches, `error executing "lxc-create": .*bad template.*`)
194 c.Assert(lc.IsConstructed(), Equals, false)194 c.Assert(lc.IsConstructed(), gc.Equals, false)
195}195}
196196
197func (s *LXCSuite) TestDestroyNotCreated(c *C) {197func (s *LXCSuite) TestDestroyNotCreated(c *gc.C) {
198 // Test that a non-existing container can't be destroyed.198 // Test that a non-existing container can't be destroyed.
199 lc := s.factory.New("golxc")199 lc := s.factory.New("golxc")
200 c.Assert(lc.IsConstructed(), Equals, false)200 c.Assert(lc.IsConstructed(), gc.Equals, false)
201 err := lc.Destroy()201 err := lc.Destroy()
202 c.Assert(err, ErrorMatches, "container .* is not yet created")202 c.Assert(err, gc.ErrorMatches, "container .* is not yet created")
203}203}
204204
205func contains(lcs []golxc.Container, lc golxc.Container) bool {205func contains(lcs []golxc.Container, lc golxc.Container) bool {
@@ -211,148 +211,148 @@
211 return false211 return false
212}212}
213213
214func (s *LXCSuite) TestList(c *C) {214func (s *LXCSuite) TestList(c *gc.C) {
215 // Test the listing of created containers.215 // Test the listing of created containers.
216 lcs, err := s.factory.List()216 lcs, err := s.factory.List()
217 oldLen := len(lcs)217 oldLen := len(lcs)
218 c.Assert(err, IsNil)218 c.Assert(err, gc.IsNil)
219 c.Assert(oldLen >= 0, Equals, true)219 c.Assert(oldLen >= 0, gc.Equals, true)
220 lc := s.createContainer(c)220 lc := s.createContainer(c)
221 defer func() {221 defer func() {
222 c.Assert(lc.Destroy(), IsNil)222 c.Assert(lc.Destroy(), gc.IsNil)
223 }()223 }()
224 lcs, _ = s.factory.List()224 lcs, _ = s.factory.List()
225 newLen := len(lcs)225 newLen := len(lcs)
226 c.Assert(newLen == oldLen+1, Equals, true)226 c.Assert(newLen == oldLen+1, gc.Equals, true)
227 c.Assert(contains(lcs, lc), Equals, true)227 c.Assert(contains(lcs, lc), gc.Equals, true)
228}228}
229229
230func (s *LXCSuite) TestClone(c *C) {230func (s *LXCSuite) TestClone(c *gc.C) {
231 // Test the cloning of an existing container.231 // Test the cloning of an existing container.
232 lc1 := s.createContainer(c)232 lc1 := s.createContainer(c)
233 defer func() {233 defer func() {
234 c.Assert(lc1.Destroy(), IsNil)234 c.Assert(lc1.Destroy(), gc.IsNil)
235 }()235 }()
236 lcs, _ := s.factory.List()236 lcs, _ := s.factory.List()
237 oldLen := len(lcs)237 oldLen := len(lcs)
238 lc2, err := lc1.Clone("golxcclone", nil, nil)238 lc2, err := lc1.Clone("golxcclone", nil, nil)
239 c.Assert(err, IsNil)239 c.Assert(err, gc.IsNil)
240 c.Assert(lc2.IsConstructed(), Equals, true)240 c.Assert(lc2.IsConstructed(), gc.Equals, true)
241 defer func() {241 defer func() {
242 c.Assert(lc2.Destroy(), IsNil)242 c.Assert(lc2.Destroy(), gc.IsNil)
243 }()243 }()
244 lcs, _ = s.factory.List()244 lcs, _ = s.factory.List()
245 newLen := len(lcs)245 newLen := len(lcs)
246 c.Assert(newLen == oldLen+1, Equals, true)246 c.Assert(newLen == oldLen+1, gc.Equals, true)
247 c.Assert(contains(lcs, lc1), Equals, true)247 c.Assert(contains(lcs, lc1), gc.Equals, true)
248 c.Assert(contains(lcs, lc2), Equals, true)248 c.Assert(contains(lcs, lc2), gc.Equals, true)
249}249}
250250
251func (s *LXCSuite) TestCloneNotCreated(c *C) {251func (s *LXCSuite) TestCloneNotCreated(c *gc.C) {
252 // Test the cloning of a non-existing container.252 // Test the cloning of a non-existing container.
253 lc := s.factory.New("golxc")253 lc := s.factory.New("golxc")
254 c.Assert(lc.IsConstructed(), Equals, false)254 c.Assert(lc.IsConstructed(), gc.Equals, false)
255 _, err := lc.Clone("golxcclone", nil, nil)255 _, err := lc.Clone("golxcclone", nil, nil)
256 c.Assert(err, ErrorMatches, "container .* is not yet created")256 c.Assert(err, gc.ErrorMatches, "container .* is not yet created")
257}257}
258258
259func (s *LXCSuite) TestStartStop(c *C) {259func (s *LXCSuite) TestStartStop(c *gc.C) {
260 // Test starting and stopping a container.260 // Test starting and stopping a container.
261 lc := s.createContainer(c)261 lc := s.createContainer(c)
262 defer func() {262 defer func() {
263 c.Assert(lc.Destroy(), IsNil)263 c.Assert(lc.Destroy(), gc.IsNil)
264 }()264 }()
265 c.Assert(lc.Start("", ""), IsNil)265 c.Assert(lc.Start("", ""), gc.IsNil)
266 c.Assert(lc.IsRunning(), Equals, true)266 c.Assert(lc.IsRunning(), gc.Equals, true)
267 c.Assert(lc.Stop(), IsNil)267 c.Assert(lc.Stop(), gc.IsNil)
268 c.Assert(lc.IsRunning(), Equals, false)268 c.Assert(lc.IsRunning(), gc.Equals, false)
269}269}
270270
271func (s *LXCSuite) TestStartNotCreated(c *C) {271func (s *LXCSuite) TestStartNotCreated(c *gc.C) {
272 // Test that a non-existing container can't be started.272 // Test that a non-existing container can't be started.
273 lc := s.factory.New("golxc")273 lc := s.factory.New("golxc")
274 c.Assert(lc.IsConstructed(), Equals, false)274 c.Assert(lc.IsConstructed(), gc.Equals, false)
275 c.Assert(lc.Start("", ""), ErrorMatches, "container .* is not yet created")275 c.Assert(lc.Start("", ""), gc.ErrorMatches, "container .* is not yet created")
276}276}
277277
278func (s *LXCSuite) TestStopNotRunning(c *C) {278func (s *LXCSuite) TestStopNotRunning(c *gc.C) {
279 // Test that a not running container can't be stopped.279 // Test that a not running container can't be stopped.
280 lc := s.createContainer(c)280 lc := s.createContainer(c)
281 defer func() {281 defer func() {
282 c.Assert(lc.Destroy(), IsNil)282 c.Assert(lc.Destroy(), gc.IsNil)
283 }()283 }()
284 c.Assert(lc.Stop(), IsNil)284 c.Assert(lc.Stop(), gc.IsNil)
285}285}
286286
287func (s *LXCSuite) TestWait(c *C) {287func (s *LXCSuite) TestWait(c *gc.C) {
288 // Test waiting for one of a number of states of a container.288 // Test waiting for one of a number of states of a container.
289 // ATTN: Using a not reached state blocks the test until timeout!289 // ATTN: Using a not reached state blocks the test until timeout!
290 lc := s.factory.New("golxc")290 lc := s.factory.New("golxc")
291 c.Assert(lc.IsConstructed(), Equals, false)291 c.Assert(lc.IsConstructed(), gc.Equals, false)
292 c.Assert(lc.Wait(), ErrorMatches, "no states specified")292 c.Assert(lc.Wait(), gc.ErrorMatches, "no states specified")
293 c.Assert(lc.Wait(golxc.StateStopped), IsNil)293 c.Assert(lc.Wait(golxc.StateStopped), gc.IsNil)
294 c.Assert(lc.Wait(golxc.StateStopped, golxc.StateRunning), IsNil)294 c.Assert(lc.Wait(golxc.StateStopped, golxc.StateRunning), gc.IsNil)
295 c.Assert(lc.Create("", "ubuntu", nil, nil), IsNil)295 c.Assert(lc.Create("", "ubuntu", nil, nil, nil), gc.IsNil)
296 defer func() {296 defer func() {
297 c.Assert(lc.Destroy(), IsNil)297 c.Assert(lc.Destroy(), gc.IsNil)
298 }()298 }()
299 go func() {299 go func() {
300 c.Assert(lc.Start("", ""), IsNil)300 c.Assert(lc.Start("", ""), gc.IsNil)
301 }()301 }()
302 c.Assert(lc.Wait(golxc.StateRunning), IsNil)302 c.Assert(lc.Wait(golxc.StateRunning), gc.IsNil)
303}303}
304304
305func (s *LXCSuite) TestFreezeUnfreeze(c *C) {305func (s *LXCSuite) TestFreezeUnfreeze(c *gc.C) {
306 // Test the freezing and unfreezing of a started container.306 // Test the freezing and unfreezing of a started container.
307 lc := s.createContainer(c)307 lc := s.createContainer(c)
308 defer func() {308 defer func() {
309 c.Assert(lc.Destroy(), IsNil)309 c.Assert(lc.Destroy(), gc.IsNil)
310 }()310 }()
311 c.Assert(lc.Start("", ""), IsNil)311 c.Assert(lc.Start("", ""), gc.IsNil)
312 defer func() {312 defer func() {
313 c.Assert(lc.Stop(), IsNil)313 c.Assert(lc.Stop(), gc.IsNil)
314 }()314 }()
315 c.Assert(lc.IsRunning(), Equals, true)315 c.Assert(lc.IsRunning(), gc.Equals, true)
316 c.Assert(lc.Freeze(), IsNil)316 c.Assert(lc.Freeze(), gc.IsNil)
317 c.Assert(lc.IsRunning(), Equals, false)317 c.Assert(lc.IsRunning(), gc.Equals, false)
318 c.Assert(lc.Unfreeze(), IsNil)318 c.Assert(lc.Unfreeze(), gc.IsNil)
319 c.Assert(lc.IsRunning(), Equals, true)319 c.Assert(lc.IsRunning(), gc.Equals, true)
320}320}
321321
322func (s *LXCSuite) TestFreezeNotStarted(c *C) {322func (s *LXCSuite) TestFreezeNotStarted(c *gc.C) {
323 // Test that a not running container can't be frozen.323 // Test that a not running container can't be frozen.
324 lc := s.createContainer(c)324 lc := s.createContainer(c)
325 defer func() {325 defer func() {
326 c.Assert(lc.Destroy(), IsNil)326 c.Assert(lc.Destroy(), gc.IsNil)
327 }()327 }()
328 c.Assert(lc.Freeze(), ErrorMatches, "container .* is not running")328 c.Assert(lc.Freeze(), gc.ErrorMatches, "container .* is not running")
329}329}
330330
331func (s *LXCSuite) TestFreezeNotCreated(c *C) {331func (s *LXCSuite) TestFreezeNotCreated(c *gc.C) {
332 // Test that a non-existing container can't be frozen.332 // Test that a non-existing container can't be frozen.
333 lc := s.factory.New("golxc")333 lc := s.factory.New("golxc")
334 c.Assert(lc.IsConstructed(), Equals, false)334 c.Assert(lc.IsConstructed(), gc.Equals, false)
335 c.Assert(lc.Freeze(), ErrorMatches, "container .* is not yet created")335 c.Assert(lc.Freeze(), gc.ErrorMatches, "container .* is not yet created")
336}336}
337337
338func (s *LXCSuite) TestUnfreezeNotCreated(c *C) {338func (s *LXCSuite) TestUnfreezeNotCreated(c *gc.C) {
339 // Test that a non-existing container can't be unfrozen.339 // Test that a non-existing container can't be unfrozen.
340 lc := s.factory.New("golxc")340 lc := s.factory.New("golxc")
341 c.Assert(lc.IsConstructed(), Equals, false)341 c.Assert(lc.IsConstructed(), gc.Equals, false)
342 c.Assert(lc.Unfreeze(), ErrorMatches, "container .* is not yet created")342 c.Assert(lc.Unfreeze(), gc.ErrorMatches, "container .* is not yet created")
343}343}
344344
345func (s *LXCSuite) TestUnfreezeNotFrozen(c *C) {345func (s *LXCSuite) TestUnfreezeNotFrozen(c *gc.C) {
346 // Test that a running container can't be unfrozen.346 // Test that a running container can't be unfrozen.
347 lc := s.createContainer(c)347 lc := s.createContainer(c)
348 defer func() {348 defer func() {
349 c.Assert(lc.Destroy(), IsNil)349 c.Assert(lc.Destroy(), gc.IsNil)
350 }()350 }()
351 c.Assert(lc.Start("", ""), IsNil)351 c.Assert(lc.Start("", ""), gc.IsNil)
352 defer func() {352 defer func() {
353 c.Assert(lc.Stop(), IsNil)353 c.Assert(lc.Stop(), gc.IsNil)
354 }()354 }()
355 c.Assert(lc.Unfreeze(), ErrorMatches, "container .* is not frozen")355 c.Assert(lc.Unfreeze(), gc.ErrorMatches, "container .* is not frozen")
356}356}
357357
358type commandArgs struct {358type commandArgs struct {
@@ -360,20 +360,20 @@
360 originalPath string360 originalPath string
361}361}
362362
363var _ = Suite(&commandArgs{})363var _ = gc.Suite(&commandArgs{})
364364
365func (s *commandArgs) SetUpSuite(c *C) {365func (s *commandArgs) SetUpSuite(c *gc.C) {
366 // lxc-create requires the PATH to be set.366 // lxc-create requires the PATH to be set.
367 s.originalPath = os.Getenv("PATH")367 s.originalPath = os.Getenv("PATH")
368 s.IsolationSuite.SetUpSuite(c)368 s.IsolationSuite.SetUpSuite(c)
369}369}
370370
371func (s *commandArgs) setupLxcStart(c *C) {371func (s *commandArgs) setupLxcStart(c *gc.C) {
372 dir := c.MkDir()372 dir := c.MkDir()
373 // Make the rootfs for the "test" container so it thinks it is created.373 // Make the rootfs for the "test" container so it thinks it is created.
374 rootfs := filepath.Join(dir, "test", "rootfs")374 rootfs := filepath.Join(dir, "test", "rootfs")
375 err := os.MkdirAll(rootfs, 0755)375 err := os.MkdirAll(rootfs, 0755)
376 c.Assert(err, IsNil)376 c.Assert(err, gc.IsNil)
377 c.Assert(rootfs, jc.IsDirectory)377 c.Assert(rootfs, jc.IsDirectory)
378378
379 s.PatchValue(&golxc.ContainerDir, dir)379 s.PatchValue(&golxc.ContainerDir, dir)
@@ -384,12 +384,12 @@
384 testing.PatchExecutable(c, s, "lxc-info", "#!/bin/sh\necho '"+info+"'\n")384 testing.PatchExecutable(c, s, "lxc-info", "#!/bin/sh\necho '"+info+"'\n")
385}385}
386386
387func (s *commandArgs) TestStartArgs(c *C) {387func (s *commandArgs) TestStartArgs(c *gc.C) {
388 s.setupLxcStart(c)388 s.setupLxcStart(c)
389 factory := golxc.Factory()389 factory := golxc.Factory()
390 container := factory.New("test")390 container := factory.New("test")
391 err := container.Start("config-file", "console-log")391 err := container.Start("config-file", "console-log")
392 c.Assert(err, IsNil)392 c.Assert(err, gc.IsNil)
393 testing.AssertEchoArgs(393 testing.AssertEchoArgs(
394 c, "lxc-start",394 c, "lxc-start",
395 "--daemon",395 "--daemon",
@@ -398,12 +398,12 @@
398 "--console-log", "console-log")398 "--console-log", "console-log")
399}399}
400400
401func (s *commandArgs) TestStartArgsNoConsoleLog(c *C) {401func (s *commandArgs) TestStartArgsNoConsoleLog(c *gc.C) {
402 s.setupLxcStart(c)402 s.setupLxcStart(c)
403 factory := golxc.Factory()403 factory := golxc.Factory()
404 container := factory.New("test")404 container := factory.New("test")
405 err := container.Start("config-file", "")405 err := container.Start("config-file", "")
406 c.Assert(err, IsNil)406 c.Assert(err, gc.IsNil)
407 testing.AssertEchoArgs(407 testing.AssertEchoArgs(
408 c, "lxc-start",408 c, "lxc-start",
409 "--daemon",409 "--daemon",
@@ -411,12 +411,12 @@
411 "--rcfile", "config-file")411 "--rcfile", "config-file")
412}412}
413413
414func (s *commandArgs) TestStartArgsFallback(c *C) {414func (s *commandArgs) TestStartArgsFallback(c *gc.C) {
415 dir := c.MkDir()415 dir := c.MkDir()
416 // Make the rootfs for the "test" container so it thinks it is created.416 // Make the rootfs for the "test" container so it thinks it is created.
417 rootfs := filepath.Join(dir, "test", "rootfs")417 rootfs := filepath.Join(dir, "test", "rootfs")
418 err := os.MkdirAll(rootfs, 0755)418 err := os.MkdirAll(rootfs, 0755)
419 c.Assert(err, IsNil)419 c.Assert(err, gc.IsNil)
420 c.Assert(rootfs, jc.IsDirectory)420 c.Assert(rootfs, jc.IsDirectory)
421421
422 s.PatchValue(&golxc.ContainerDir, dir)422 s.PatchValue(&golxc.ContainerDir, dir)
@@ -442,7 +442,7 @@
442 factory := golxc.Factory()442 factory := golxc.Factory()
443 container := factory.New("test")443 container := factory.New("test")
444 err = container.Start("config-file", "console-log")444 err = container.Start("config-file", "console-log")
445 c.Assert(err, IsNil)445 c.Assert(err, gc.IsNil)
446 testing.AssertEchoArgs(446 testing.AssertEchoArgs(
447 c, "lxc-start",447 c, "lxc-start",
448 "--daemon",448 "--daemon",
@@ -451,7 +451,7 @@
451 "--console", "console-log")451 "--console", "console-log")
452}452}
453453
454func (s *commandArgs) TestCreateArgs(c *C) {454func (s *commandArgs) TestCreateArgs(c *gc.C) {
455 s.PatchValue(&golxc.ContainerDir, c.MkDir())455 s.PatchValue(&golxc.ContainerDir, c.MkDir())
456 s.PatchEnvironment("PATH", s.originalPath)456 s.PatchEnvironment("PATH", s.originalPath)
457 testing.PatchExecutableAsEchoArgs(c, s, "lxc-create")457 testing.PatchExecutableAsEchoArgs(c, s, "lxc-create")
@@ -462,8 +462,9 @@
462 "config-file", "template",462 "config-file", "template",
463 []string{"extra-1", "extra-2"},463 []string{"extra-1", "extra-2"},
464 []string{"template-1", "template-2"},464 []string{"template-1", "template-2"},
465 nil,
465 )466 )
466 c.Assert(err, IsNil)467 c.Assert(err, gc.IsNil)
467 testing.AssertEchoArgs(468 testing.AssertEchoArgs(
468 c, "lxc-create",469 c, "lxc-create",
469 "-n", "test",470 "-n", "test",
@@ -473,7 +474,46 @@
473 "--", "template-1", "template-2")474 "--", "template-1", "template-2")
474}475}
475476
476func (s *commandArgs) TestCloneArgs(c *C) {477func (s *commandArgs) TestCreateWithEnv(c *gc.C) {
478 s.PatchValue(&golxc.ContainerDir, c.MkDir())
479 s.PatchEnvironment("PATH", s.originalPath)
480
481 EchoEnvHello := `#!/bin/bash
482name=` + "`basename $0`" + `
483argfile="$name.out"
484rm -f $argfile
485printf "%s" $name | tee -a $argfile
486printf " \"%s\"" "$HELLO" | tee -a $argfile
487if [ -n "$FOO" ]; then
488 printf " \"%s\"" "$FOO" | tee -a $argfile
489fi
490printf "\n" | tee -a $argfile
491`
492
493 testing.PatchExecutable(
494 c, s, "lxc-create", EchoEnvHello)
495 s.AddCleanup(func(*gc.C) {
496 os.Remove("lxc-create.out")
497 })
498
499 // Add an environment variable to the calling process
500 // to show that these don't get passed through.
501 s.PatchEnvironment("FOO", "BAR")
502 // Only the explicitly set env variables are propagated.
503 envArgs := []string{"HELLO=WORLD!"}
504 factory := golxc.Factory()
505 container := factory.New("test")
506 err := container.Create(
507 "config-file", "template",
508 []string{"extra-1", "extra-2"},
509 []string{"template-1", "template-2"},
510 envArgs,
511 )
512 c.Assert(err, gc.IsNil)
513 testing.AssertEchoArgs(c, "lxc-create", "WORLD!")
514}
515
516func (s *commandArgs) TestCloneArgs(c *gc.C) {
477 dir := c.MkDir()517 dir := c.MkDir()
478 s.PatchValue(&golxc.ContainerDir, dir)518 s.PatchValue(&golxc.ContainerDir, dir)
479 s.PatchEnvironment("PATH", s.originalPath)519 s.PatchEnvironment("PATH", s.originalPath)
@@ -486,7 +526,7 @@
486 // Make the rootfs for the "test" container so it thinks it is created.526 // Make the rootfs for the "test" container so it thinks it is created.
487 rootfs := filepath.Join(dir, "test", "rootfs")527 rootfs := filepath.Join(dir, "test", "rootfs")
488 err := os.MkdirAll(rootfs, 0755)528 err := os.MkdirAll(rootfs, 0755)
489 c.Assert(err, IsNil)529 c.Assert(err, gc.IsNil)
490 c.Assert(rootfs, jc.IsDirectory)530 c.Assert(rootfs, jc.IsDirectory)
491 c.Assert(container.IsConstructed(), jc.IsTrue)531 c.Assert(container.IsConstructed(), jc.IsTrue)
492 clone, err := container.Clone(532 clone, err := container.Clone(
@@ -494,29 +534,29 @@
494 []string{"extra-1", "extra-2"},534 []string{"extra-1", "extra-2"},
495 []string{"template-1", "template-2"},535 []string{"template-1", "template-2"},
496 )536 )
497 c.Assert(err, IsNil)537 c.Assert(err, gc.IsNil)
498 testing.AssertEchoArgs(538 testing.AssertEchoArgs(
499 c, "lxc-clone",539 c, "lxc-clone",
500 "-o", "test",540 "-o", "test",
501 "-n", "name",541 "-n", "name",
502 "extra-1", "extra-2",542 "extra-1", "extra-2",
503 "--", "template-1", "template-2")543 "--", "template-1", "template-2")
504 c.Assert(clone.Name(), Equals, "name")544 c.Assert(clone.Name(), gc.Equals, "name")
505}545}
506546
507type UtilsSuite struct {547type UtilsSuite struct {
508 testing.IsolationSuite548 testing.IsolationSuite
509}549}
510550
511var _ = Suite(&UtilsSuite{})551var _ = gc.Suite(&UtilsSuite{})
512552
513func (s *UtilsSuite) TestGetDefaultLXCContainerDirDefaultValue(c *C) {553func (s *UtilsSuite) TestGetDefaultLXCContainerDirDefaultValue(c *gc.C) {
514 testing.PatchExecutable(c, s, "lxc-config", "#!/bin/sh\nexit -1\n")554 testing.PatchExecutable(c, s, "lxc-config", "#!/bin/sh\nexit -1\n")
515 c.Assert(golxc.GetDefaultLXCContainerDir(), Equals, golxc.DefaultLXCDir)555 c.Assert(golxc.GetDefaultLXCContainerDir(), gc.Equals, golxc.DefaultLXCDir)
516}556}
517557
518func (s *UtilsSuite) TestGetDefaultLXCContainerDir(c *C) {558func (s *UtilsSuite) TestGetDefaultLXCContainerDir(c *gc.C) {
519 const path = "/var/lib/non-standard-lxc"559 const path = "/var/lib/non-standard-lxc"
520 testing.PatchExecutable(c, s, "lxc-config", "#!/bin/sh\necho '"+path+"'\n")560 testing.PatchExecutable(c, s, "lxc-config", "#!/bin/sh\necho '"+path+"'\n")
521 c.Assert(golxc.GetDefaultLXCContainerDir(), Equals, path)561 c.Assert(golxc.GetDefaultLXCContainerDir(), gc.Equals, path)
522}562}
523563
=== modified file 'network.go'
--- network.go 2014-07-03 21:37:49 +0000
+++ network.go 2014-11-21 03:15:57 +0000
@@ -20,7 +20,7 @@
20 return err20 return err
21 }21 }
22 if goal != "start" {22 if goal != "start" {
23 _, err := run("start", "lxc-net")23 _, err := run("start", nil, "lxc-net")
24 if err != nil {24 if err != nil {
25 return err25 return err
26 }26 }
@@ -35,7 +35,7 @@
35 return err35 return err
36 }36 }
37 if goal != "stop" {37 if goal != "stop" {
38 _, err := run("stop", "lxc-net")38 _, err := run("stop", nil, "lxc-net")
39 if err != nil {39 if err != nil {
40 return err40 return err
41 }41 }
@@ -73,7 +73,7 @@
7373
74// networkStatus returns the status of the lxc network subsystem.74// networkStatus returns the status of the lxc network subsystem.
75func networkStatus() (goal, status string, err error) {75func networkStatus() (goal, status string, err error) {
76 output, err := run("status", "lxc-net")76 output, err := run("status", nil, "lxc-net")
77 if err != nil {77 if err != nil {
78 return "", "", err78 return "", "", err
79 }79 }
8080
=== modified file 'package_test.go'
--- package_test.go 2014-03-11 00:34:54 +0000
+++ package_test.go 2014-11-21 03:15:57 +0000
@@ -6,7 +6,7 @@
6import (6import (
7 "testing"7 "testing"
88
9 gc "launchpad.net/gocheck"9 gc "gopkg.in/check.v1"
10)10)
1111
12func Test(t *testing.T) {12func Test(t *testing.T) {

Subscribers

People subscribed via source and target branches

to all changes: