Merge lp:~frankban/juju-core/bug-1166224-service-deploy-panic into lp:~juju/juju-core/trunk

Proposed by Francesco Banconi
Status: Merged
Merged at revision: 1132
Proposed branch: lp:~frankban/juju-core/bug-1166224-service-deploy-panic
Merge into: lp:~juju/juju-core/trunk
Diff against target: 343 lines (+105/-31)
7 files modified
charm/repo.go (+11/-5)
charm/repo_test.go (+6/-6)
cmd/juju/main.go (+5/-19)
cmd/jujud/machine.go (+3/-0)
cmd/jujud/machine_test.go (+13/-1)
juju/conn.go (+19/-0)
juju/conn_test.go (+48/-0)
To merge this branch: bzr merge lp:~frankban/juju-core/bug-1166224-service-deploy-panic
Reviewer Review Type Date Requested Status
Juju Engineering Pending
Review via email: mp+157836@code.launchpad.net

Description of the change

Fix ServiceDeploy panic when called via the API.

Fix the panic that happens when calling ServiceDeploy via the juju-core API.

Add a global charm.CacheDir variable, in order to avoid the call to
config.JujuHomePath inside the CharmStore.Get method.

charm.CacheDir is originally empty, and is then set by the machineAgent.Run
method.

Pre-implementation call with Roger.

https://codereview.appspot.com/8566043/

To post a comment you must log in.
Revision history for this message
Francesco Banconi (frankban) wrote :
Download full text (6.7 KiB)

Reviewers: mp+157836_code.launchpad.net,

Message:
Please take a look.

Description:
Fix ServiceDeploy panic when called via the API.

Fix the panic that happens when calling ServiceDeploy via the juju-core
API.

Add a global charm.CacheDir variable, in order to avoid the call to
config.JujuHomePath inside the CharmStore.Get method.

charm.CacheDir is originally empty, and is then set by the
machineAgent.Run
method.

Pre-implementation call with Roger.

https://code.launchpad.net/~frankban/juju-core/bug-1166224-service-deploy-panic/+merge/157836

(do not edit description out of merge proposal)

Please review this at https://codereview.appspot.com/8566043/

Affected files:
   A [revision details]
   M charm/repo.go
   M charm/repo_test.go
   M cmd/jujud/machine.go
   M cmd/jujud/machine_test.go

Index: [revision details]
=== added file '[revision details]'
--- [revision details] 2012-01-01 00:00:00 +0000
+++ [revision details] 2012-01-01 00:00:00 +0000
@@ -0,0 +1,2 @@
+Old revision: <email address hidden>
+New revision:
<email address hidden>

Index: charm/repo.go
=== modified file 'charm/repo.go'
--- charm/repo.go 2013-04-03 23:29:07 +0000
+++ charm/repo.go 2013-04-08 16:36:35 +0000
@@ -7,7 +7,6 @@
   "fmt"
   "io"
   "io/ioutil"
- "launchpad.net/juju-core/environs/config"
   "launchpad.net/juju-core/log"
   "net/http"
   "net/url"
@@ -16,6 +15,9 @@
   "strings"
  )

+// CacheDir stores the charm cache directory path.
+var CacheDir string
+
  // InfoResponse is sent by the charm store in response to charm-info
requests.
  type InfoResponse struct {
   Revision int `json:"revision"` // Zero is valid. Can't omitempty.
@@ -211,8 +213,11 @@

  // Get returns the charm referenced by curl.
  func (s *CharmStore) Get(curl *URL) (Charm, error) {
- cachePath := config.JujuHomePath("cache")
- if err := os.MkdirAll(cachePath, 0755); err != nil {
+ // MachineAgent.Run should have already set the CacheDir.
+ if CacheDir == "" {
+ panic("the charm cache directory path is empty")
+ }
+ if err := os.MkdirAll(CacheDir, 0755); err != nil {
    return nil, err
   }
   rev, digest, err := s.revision(curl)
@@ -224,14 +229,14 @@
   } else if curl.Revision != rev {
    return nil, fmt.Errorf("charm: store returned charm with wrong revision
for %q", curl.String())
   }
- path := filepath.Join(cachePath, Quote(curl.String())+".charm")
+ path := filepath.Join(CacheDir, Quote(curl.String())+".charm")
   if verify(path, digest) != nil {
    resp, err := http.Get(s.baseURL + "/charm/" +
url.QueryEscape(curl.Path()))
    if err != nil {
     return nil, err
    }
    defer resp.Body.Close()
- f, err := ioutil.TempFile(cachePath, "charm-download")
+ f, err := ioutil.TempFile(CacheDir, "charm-download")
    if err != nil {
     return nil, err
    }

Index: charm/repo_test.go
=== modified file 'charm/repo_test.go'
--- charm/repo_test.go 2013-04-03 23:29:07 +0000
+++ charm/repo_test.go 2013-04-09 09:51:19 +0000
@@ -8,7 +8,6 @@
   "io/ioutil"
   . "launchpad.net/gocheck"
   "launchpad.net/juju-core/charm"
- "launchpad.net/juju-core/environs/config"
   "launchpad.net/juju-core/log"
 ...

Read more...

Revision history for this message
Roger Peppe (rogpeppe) wrote :

not lgtm for the moment - the CharmDir is not set when the juju command
is run.

please could you move the checkJujuHome function from cmd/juju/main.go
into the juju package, rename it to InitJujuHome, and add a line to set
charm.CharmDir appropriately.

https://codereview.appspot.com/8566043/diff/1/charm/repo.go
File charm/repo.go (right):

https://codereview.appspot.com/8566043/diff/1/charm/repo.go#newcode214
charm/repo.go:214: // Get returns the charm referenced by curl.
// CacheDir must have been set, otherwise Get will panic.

https://codereview.appspot.com/8566043/diff/1/charm/repo.go#newcode216
charm/repo.go:216: // MachineAgent.Run should have already set the
CacheDir.
// The cache location must have been previously set.
(it might have been set directly too, or via juju.SetJujuHome)

https://codereview.appspot.com/8566043/diff/1/charm/repo.go#newcode218
charm/repo.go:218: panic("the charm cache directory path is empty")
s/the //

just convention.

https://codereview.appspot.com/8566043/

Revision history for this message
Francesco Banconi (frankban) wrote :

Please take a look.

https://codereview.appspot.com/8566043/diff/1/charm/repo.go
File charm/repo.go (right):

https://codereview.appspot.com/8566043/diff/1/charm/repo.go#newcode214
charm/repo.go:214: // Get returns the charm referenced by curl.
On 2013/04/09 11:24:13, rog wrote:
> // CacheDir must have been set, otherwise Get will panic.

Done.

https://codereview.appspot.com/8566043/diff/1/charm/repo.go#newcode216
charm/repo.go:216: // MachineAgent.Run should have already set the
CacheDir.
On 2013/04/09 11:24:13, rog wrote:
> // The cache location must have been previously set.
> (it might have been set directly too, or via juju.SetJujuHome)

Done.

https://codereview.appspot.com/8566043/diff/1/charm/repo.go#newcode218
charm/repo.go:218: panic("the charm cache directory path is empty")
On 2013/04/09 11:24:13, rog wrote:
> s/the //

> just convention.

Done.

https://codereview.appspot.com/8566043/

Revision history for this message
Roger Peppe (rogpeppe) wrote :

LGTM with the below points addressed.
thanks!

https://codereview.appspot.com/8566043/diff/7001/cmd/juju/main.go
File cmd/juju/main.go (right):

https://codereview.appspot.com/8566043/diff/7001/cmd/juju/main.go#newcode30
cmd/juju/main.go:30: fmt.Fprintf(os.Stderr, "command failed:
"+err.Error()+"\n")
fmt.Fprintf(os.Stderr, "error: %s\n", err)

to be consistent with cmd.Main

in general passing a non-constant argument to Fprintf-like functions is
not a good idea regardless.

https://codereview.appspot.com/8566043/diff/7001/cmd/juju/main.go#newcode31
cmd/juju/main.go:31: os.Exit(1)
i know it was like this before, but i think this should probably be
os.Exit(2).

https://codereview.appspot.com/8566043/diff/7001/juju/conn.go
File juju/conn.go (right):

https://codereview.appspot.com/8566043/diff/7001/juju/conn.go#newcode413
juju/conn.go:413: // It also sets up the charm cache directory path in
charm.CacheDir.
// InitJujuHome initializes the charm and environs/config
// packages to use default paths based on the
// $JUJU_HOME or $HOME environment variables.
// This function should be called before calling NewConn or
// Conn.Deploy.

?

https://codereview.appspot.com/8566043/

Revision history for this message
Francesco Banconi (frankban) wrote :

*** Submitted:

Fix ServiceDeploy panic when called via the API.

Fix the panic that happens when calling ServiceDeploy via the juju-core
API.

Add a global charm.CacheDir variable, in order to avoid the call to
config.JujuHomePath inside the CharmStore.Get method.

charm.CacheDir is originally empty, and is then set by the
machineAgent.Run
method.

Pre-implementation call with Roger.

R=rog, TheMue
CC=
https://codereview.appspot.com/8566043

https://codereview.appspot.com/8566043/diff/7001/cmd/juju/main.go
File cmd/juju/main.go (right):

https://codereview.appspot.com/8566043/diff/7001/cmd/juju/main.go#newcode30
cmd/juju/main.go:30: fmt.Fprintf(os.Stderr, "command failed:
"+err.Error()+"\n")
On 2013/04/09 16:22:59, rog wrote:
> fmt.Fprintf(os.Stderr, "error: %s\n", err)

> to be consistent with cmd.Main

> in general passing a non-constant argument to Fprintf-like functions
is not a
> good idea regardless.

Done.

https://codereview.appspot.com/8566043/diff/7001/cmd/juju/main.go#newcode31
cmd/juju/main.go:31: os.Exit(1)
On 2013/04/09 16:22:59, rog wrote:
> i know it was like this before, but i think this should probably be
os.Exit(2).

Done.

https://codereview.appspot.com/8566043/diff/7001/juju/conn.go
File juju/conn.go (right):

https://codereview.appspot.com/8566043/diff/7001/juju/conn.go#newcode413
juju/conn.go:413: // It also sets up the charm cache directory path in
charm.CacheDir.
On 2013/04/09 16:22:59, rog wrote:
> // InitJujuHome initializes the charm and environs/config
> // packages to use default paths based on the
> // $JUJU_HOME or $HOME environment variables.
> // This function should be called before calling NewConn or
> // Conn.Deploy.

> ?

Done.

https://codereview.appspot.com/8566043/

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'charm/repo.go'
--- charm/repo.go 2013-04-09 14:37:05 +0000
+++ charm/repo.go 2013-04-09 16:40:27 +0000
@@ -7,7 +7,6 @@
7 "fmt"7 "fmt"
8 "io"8 "io"
9 "io/ioutil"9 "io/ioutil"
10 "launchpad.net/juju-core/environs/config"
11 "launchpad.net/juju-core/log"10 "launchpad.net/juju-core/log"
12 "net/http"11 "net/http"
13 "net/url"12 "net/url"
@@ -16,6 +15,9 @@
16 "strings"15 "strings"
17)16)
1817
18// CacheDir stores the charm cache directory path.
19var CacheDir string
20
19// InfoResponse is sent by the charm store in response to charm-info requests.21// InfoResponse is sent by the charm store in response to charm-info requests.
20type InfoResponse struct {22type InfoResponse struct {
21 Revision int `json:"revision"` // Zero is valid. Can't omitempty.23 Revision int `json:"revision"` // Zero is valid. Can't omitempty.
@@ -213,9 +215,13 @@
213}215}
214216
215// Get returns the charm referenced by curl.217// Get returns the charm referenced by curl.
218// CacheDir must have been set, otherwise Get will panic.
216func (s *CharmStore) Get(curl *URL) (Charm, error) {219func (s *CharmStore) Get(curl *URL) (Charm, error) {
217 cachePath := config.JujuHomePath("cache")220 // The cache location must have been previously set.
218 if err := os.MkdirAll(cachePath, 0755); err != nil {221 if CacheDir == "" {
222 panic("charm cache directory path is empty")
223 }
224 if err := os.MkdirAll(CacheDir, 0755); err != nil {
219 return nil, err225 return nil, err
220 }226 }
221 rev, digest, err := s.revision(curl)227 rev, digest, err := s.revision(curl)
@@ -227,14 +233,14 @@
227 } else if curl.Revision != rev {233 } else if curl.Revision != rev {
228 return nil, fmt.Errorf("charm: store returned charm with wrong revision for %q", curl.String())234 return nil, fmt.Errorf("charm: store returned charm with wrong revision for %q", curl.String())
229 }235 }
230 path := filepath.Join(cachePath, Quote(curl.String())+".charm")236 path := filepath.Join(CacheDir, Quote(curl.String())+".charm")
231 if verify(path, digest) != nil {237 if verify(path, digest) != nil {
232 resp, err := http.Get(s.BaseURL + "/charm/" + url.QueryEscape(curl.Path()))238 resp, err := http.Get(s.BaseURL + "/charm/" + url.QueryEscape(curl.Path()))
233 if err != nil {239 if err != nil {
234 return nil, err240 return nil, err
235 }241 }
236 defer resp.Body.Close()242 defer resp.Body.Close()
237 f, err := ioutil.TempFile(cachePath, "charm-download")243 f, err := ioutil.TempFile(CacheDir, "charm-download")
238 if err != nil {244 if err != nil {
239 return nil, err245 return nil, err
240 }246 }
241247
=== modified file 'charm/repo_test.go'
--- charm/repo_test.go 2013-04-09 14:37:05 +0000
+++ charm/repo_test.go 2013-04-09 16:40:27 +0000
@@ -8,7 +8,6 @@
8 "io/ioutil"8 "io/ioutil"
9 . "launchpad.net/gocheck"9 . "launchpad.net/gocheck"
10 "launchpad.net/juju-core/charm"10 "launchpad.net/juju-core/charm"
11 "launchpad.net/juju-core/environs/config"
12 "launchpad.net/juju-core/log"11 "launchpad.net/juju-core/log"
13 "launchpad.net/juju-core/testing"12 "launchpad.net/juju-core/testing"
14 "net"13 "net"
@@ -150,23 +149,24 @@
150type StoreSuite struct {149type StoreSuite struct {
151 server *MockStore150 server *MockStore
152 store *charm.CharmStore151 store *charm.CharmStore
153 oldJujuHome string152 oldCacheDir string
154}153}
155154
156var _ = Suite(&StoreSuite{})155var _ = Suite(&StoreSuite{})
157156
158func (s *StoreSuite) SetUpSuite(c *C) {157func (s *StoreSuite) SetUpSuite(c *C) {
159 s.server = NewMockStore(c)158 s.server = NewMockStore(c)
159 s.oldCacheDir = charm.CacheDir
160}160}
161161
162func (s *StoreSuite) SetUpTest(c *C) {162func (s *StoreSuite) SetUpTest(c *C) {
163 s.oldJujuHome = config.SetJujuHome(c.MkDir())163 charm.CacheDir = c.MkDir()
164 s.store = charm.NewStore("http://127.0.0.1:4444")164 s.store = charm.NewStore("http://127.0.0.1:4444")
165 s.server.downloads = nil165 s.server.downloads = nil
166}166}
167167
168func (s *StoreSuite) TearDownSuite(c *C) {168func (s *StoreSuite) TearDownSuite(c *C) {
169 config.SetJujuHome(s.oldJujuHome)169 charm.CacheDir = s.oldCacheDir
170 s.server.lis.Close()170 s.server.lis.Close()
171}171}
172172
@@ -245,12 +245,12 @@
245}245}
246246
247func (s *StoreSuite) TestGetBadCache(c *C) {247func (s *StoreSuite) TestGetBadCache(c *C) {
248 c.Assert(os.Mkdir(config.JujuHomePath("cache"), 0777), IsNil)248 c.Assert(os.Mkdir(filepath.Join(charm.CacheDir, "cache"), 0777), IsNil)
249 base := "cs:series/good"249 base := "cs:series/good"
250 curl := charm.MustParseURL(base)250 curl := charm.MustParseURL(base)
251 revCurl := charm.MustParseURL(base + "-23")251 revCurl := charm.MustParseURL(base + "-23")
252 name := charm.Quote(revCurl.String()) + ".charm"252 name := charm.Quote(revCurl.String()) + ".charm"
253 err := ioutil.WriteFile(config.JujuHomePath("cache", name), nil, 0666)253 err := ioutil.WriteFile(filepath.Join(charm.CacheDir, "cache", name), nil, 0666)
254 c.Assert(err, IsNil)254 c.Assert(err, IsNil)
255 ch, err := s.store.Get(curl)255 ch, err := s.store.Get(curl)
256 c.Assert(err, IsNil)256 c.Assert(err, IsNil)
257257
=== modified file 'cmd/juju/main.go'
--- cmd/juju/main.go 2013-04-05 18:51:03 +0000
+++ cmd/juju/main.go 2013-04-09 16:40:27 +0000
@@ -3,9 +3,8 @@
3import (3import (
4 "fmt"4 "fmt"
5 "launchpad.net/juju-core/cmd"5 "launchpad.net/juju-core/cmd"
6 "launchpad.net/juju-core/environs/config"6 "launchpad.net/juju-core/juju"
7 "os"7 "os"
8 "path/filepath"
9)8)
109
11// When we import an environment provider implementation10// When we import an environment provider implementation
@@ -23,27 +22,14 @@
23https://juju.ubuntu.com/22https://juju.ubuntu.com/
24`23`
2524
26// checkJujuHome retrieves $JUJU_HOME or $HOME to set the juju home.
27// In case both variables aren't set the command will exit with an
28// error.
29func checkJujuHome() {
30 jujuHome := os.Getenv("JUJU_HOME")
31 if jujuHome == "" {
32 home := os.Getenv("HOME")
33 if home == "" {
34 fmt.Fprintf(os.Stderr, "command failed: cannot determine juju home, neither $JUJU_HOME nor $HOME are set")
35 os.Exit(1)
36 }
37 jujuHome = filepath.Join(home, ".juju")
38 }
39 config.SetJujuHome(jujuHome)
40}
41
42// Main registers subcommands for the juju executable, and hands over control25// Main registers subcommands for the juju executable, and hands over control
43// to the cmd package. This function is not redundant with main, because it26// to the cmd package. This function is not redundant with main, because it
44// provides an entry point for testing with arbitrary command line arguments.27// provides an entry point for testing with arbitrary command line arguments.
45func Main(args []string) {28func Main(args []string) {
46 checkJujuHome()29 if err := juju.InitJujuHome(); err != nil {
30 fmt.Fprintf(os.Stderr, "error: %s\n", err)
31 os.Exit(2)
32 }
47 juju := cmd.NewSuperCommand(cmd.SuperCommandParams{33 juju := cmd.NewSuperCommand(cmd.SuperCommandParams{
48 Name: "juju",34 Name: "juju",
49 Doc: jujuDoc,35 Doc: jujuDoc,
5036
=== modified file 'cmd/jujud/machine.go'
--- cmd/jujud/machine.go 2013-04-05 13:47:17 +0000
+++ cmd/jujud/machine.go 2013-04-09 16:40:27 +0000
@@ -3,6 +3,7 @@
3import (3import (
4 "fmt"4 "fmt"
5 "launchpad.net/gnuflag"5 "launchpad.net/gnuflag"
6 "launchpad.net/juju-core/charm"
6 "launchpad.net/juju-core/cmd"7 "launchpad.net/juju-core/cmd"
7 "launchpad.net/juju-core/environs/agent"8 "launchpad.net/juju-core/environs/agent"
8 "launchpad.net/juju-core/log"9 "launchpad.net/juju-core/log"
@@ -13,6 +14,7 @@
13 "launchpad.net/juju-core/worker/machiner"14 "launchpad.net/juju-core/worker/machiner"
14 "launchpad.net/juju-core/worker/provisioner"15 "launchpad.net/juju-core/worker/provisioner"
15 "launchpad.net/tomb"16 "launchpad.net/tomb"
17 "path/filepath"
16 "time"18 "time"
17)19)
1820
@@ -58,6 +60,7 @@
58 if err := a.Conf.read(state.MachineTag(a.MachineId)); err != nil {60 if err := a.Conf.read(state.MachineTag(a.MachineId)); err != nil {
59 return err61 return err
60 }62 }
63 charm.CacheDir = filepath.Join(a.Conf.DataDir, "charmcache")
61 defer log.Noticef("cmd/jujud: machine agent exiting")64 defer log.Noticef("cmd/jujud: machine agent exiting")
62 defer a.tomb.Done()65 defer a.tomb.Done()
6366
6467
=== modified file 'cmd/jujud/machine_test.go'
--- cmd/jujud/machine_test.go 2013-04-09 09:32:06 +0000
+++ cmd/jujud/machine_test.go 2013-04-09 16:40:27 +0000
@@ -3,6 +3,7 @@
3import (3import (
4 "fmt"4 "fmt"
5 . "launchpad.net/gocheck"5 . "launchpad.net/gocheck"
6 "launchpad.net/juju-core/charm"
6 "launchpad.net/juju-core/cmd"7 "launchpad.net/juju-core/cmd"
7 "launchpad.net/juju-core/environs/agent"8 "launchpad.net/juju-core/environs/agent"
8 "launchpad.net/juju-core/environs/dummy"9 "launchpad.net/juju-core/environs/dummy"
@@ -10,16 +11,26 @@
10 "launchpad.net/juju-core/state/api"11 "launchpad.net/juju-core/state/api"
11 "launchpad.net/juju-core/state/watcher"12 "launchpad.net/juju-core/state/watcher"
12 "launchpad.net/juju-core/testing"13 "launchpad.net/juju-core/testing"
14 "path/filepath"
13 "reflect"15 "reflect"
14 "time"16 "time"
15)17)
1618
17type MachineSuite struct {19type MachineSuite struct {
18 agentSuite20 agentSuite
21 oldCacheDir string
19}22}
2023
21var _ = Suite(&MachineSuite{})24var _ = Suite(&MachineSuite{})
2225
26func (s *MachineSuite) SetUpSuite(c *C) {
27 s.oldCacheDir = charm.CacheDir
28}
29
30func (s *MachineSuite) TearDownSuite(c *C) {
31 charm.CacheDir = s.oldCacheDir
32}
33
23// primeAgent adds a new Machine to run the given jobs, and sets up the34// primeAgent adds a new Machine to run the given jobs, and sets up the
24// machine agent's directory. It returns the new machine, the35// machine agent's directory. It returns the new machine, the
25// agent's configuration and the tools currently running.36// agent's configuration and the tools currently running.
@@ -72,7 +83,7 @@
72}83}
7384
74func (s *MachineSuite) TestRunStop(c *C) {85func (s *MachineSuite) TestRunStop(c *C) {
75 m, _, _ := s.primeAgent(c, state.JobHostUnits)86 m, ac, _ := s.primeAgent(c, state.JobHostUnits)
76 a := s.newAgent(c, m)87 a := s.newAgent(c, m)
77 done := make(chan error)88 done := make(chan error)
78 go func() {89 go func() {
@@ -81,6 +92,7 @@
81 err := a.Stop()92 err := a.Stop()
82 c.Assert(err, IsNil)93 c.Assert(err, IsNil)
83 c.Assert(<-done, IsNil)94 c.Assert(<-done, IsNil)
95 c.Assert(charm.CacheDir, Equals, filepath.Join(ac.DataDir, "charmcache"))
84}96}
8597
86func (s *MachineSuite) TestWithDeadMachine(c *C) {98func (s *MachineSuite) TestWithDeadMachine(c *C) {
8799
=== modified file 'juju/conn.go'
--- juju/conn.go 2013-04-08 15:27:15 +0000
+++ juju/conn.go 2013-04-09 16:40:27 +0000
@@ -11,12 +11,14 @@
11 "launchpad.net/juju-core/charm"11 "launchpad.net/juju-core/charm"
12 "launchpad.net/juju-core/constraints"12 "launchpad.net/juju-core/constraints"
13 "launchpad.net/juju-core/environs"13 "launchpad.net/juju-core/environs"
14 "launchpad.net/juju-core/environs/config"
14 "launchpad.net/juju-core/log"15 "launchpad.net/juju-core/log"
15 "launchpad.net/juju-core/state"16 "launchpad.net/juju-core/state"
16 "launchpad.net/juju-core/state/api/params"17 "launchpad.net/juju-core/state/api/params"
17 "launchpad.net/juju-core/trivial"18 "launchpad.net/juju-core/trivial"
18 "net/url"19 "net/url"
19 "os"20 "os"
21 "path/filepath"
20 "time"22 "time"
21)23)
2224
@@ -405,3 +407,20 @@
405 }407 }
406 return validated408 return validated
407}409}
410
411// InitJujuHome initializes the charm and environs/config packages to use
412// default paths based on the $JUJU_HOME or $HOME environment variables.
413// This function should be called before calling NewConn or Conn.Deploy.
414func InitJujuHome() error {
415 jujuHome := os.Getenv("JUJU_HOME")
416 if jujuHome == "" {
417 home := os.Getenv("HOME")
418 if home == "" {
419 return errors.New("cannot determine juju home, neither $JUJU_HOME nor $HOME are set")
420 }
421 jujuHome = filepath.Join(home, ".juju")
422 }
423 config.SetJujuHome(jujuHome)
424 charm.CacheDir = filepath.Join(jujuHome, "charmcache")
425 return nil
426}
408427
=== modified file 'juju/conn_test.go'
--- juju/conn_test.go 2013-04-02 04:52:41 +0000
+++ juju/conn_test.go 2013-04-09 16:40:27 +0000
@@ -6,6 +6,7 @@
6 "launchpad.net/juju-core/charm"6 "launchpad.net/juju-core/charm"
7 "launchpad.net/juju-core/constraints"7 "launchpad.net/juju-core/constraints"
8 "launchpad.net/juju-core/environs"8 "launchpad.net/juju-core/environs"
9 "launchpad.net/juju-core/environs/config"
9 "launchpad.net/juju-core/environs/dummy"10 "launchpad.net/juju-core/environs/dummy"
10 "launchpad.net/juju-core/juju"11 "launchpad.net/juju-core/juju"
11 "launchpad.net/juju-core/juju/testing"12 "launchpad.net/juju-core/juju/testing"
@@ -474,3 +475,50 @@
474 c.Assert(mcons, DeepEquals, cons)475 c.Assert(mcons, DeepEquals, cons)
475 }476 }
476}477}
478
479type InitJujuHomeSuite struct {
480 originalHome string
481 originalJujuHome string
482}
483
484var _ = Suite(&InitJujuHomeSuite{})
485
486func (s *InitJujuHomeSuite) SetUpTest(c *C) {
487 s.originalHome = os.Getenv("HOME")
488 s.originalJujuHome = os.Getenv("JUJU_HOME")
489}
490
491func (s *InitJujuHomeSuite) TearDownTest(c *C) {
492 os.Setenv("HOME", s.originalHome)
493 os.Setenv("JUJU_HOME", s.originalJujuHome)
494}
495
496func (s *InitJujuHomeSuite) TestJujuHome(c *C) {
497 os.Setenv("JUJU_HOME", "/my/juju/home")
498 err := juju.InitJujuHome()
499 c.Assert(err, IsNil)
500 c.Assert(config.JujuHome(), Equals, "/my/juju/home")
501}
502
503func (s *InitJujuHomeSuite) TestHome(c *C) {
504 os.Setenv("JUJU_HOME", "")
505 os.Setenv("HOME", "/my/home/")
506 err := juju.InitJujuHome()
507 c.Assert(err, IsNil)
508 c.Assert(config.JujuHome(), Equals, "/my/home/.juju")
509}
510
511func (s *InitJujuHomeSuite) TestError(c *C) {
512 os.Setenv("JUJU_HOME", "")
513 os.Setenv("HOME", "")
514 err := juju.InitJujuHome()
515 c.Assert(err, ErrorMatches, "cannot determine juju home.*")
516}
517
518func (s *InitJujuHomeSuite) TestCacheDir(c *C) {
519 os.Setenv("JUJU_HOME", "/foo/bar")
520 c.Assert(charm.CacheDir, Equals, "")
521 err := juju.InitJujuHome()
522 c.Assert(err, IsNil)
523 c.Assert(charm.CacheDir, Equals, "/foo/bar/charmcache")
524}

Subscribers

People subscribed via source and target branches