Merge lp:~frankban/juju-core/bug-1166224-service-deploy-panic into lp:~juju/juju-core/trunk
- bug-1166224-service-deploy-panic
- Merge into trunk
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 | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Juju Engineering | Pending | ||
Review via email:
|
Commit message
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.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Francesco Banconi (frankban) wrote : | # |
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
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:/
File charm/repo.go (right):
https:/
charm/repo.go:214: // Get returns the charm referenced by curl.
// CacheDir must have been set, otherwise Get will panic.
https:/
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:/
charm/repo.go:218: panic("the charm cache directory path is empty")
s/the //
just convention.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Francesco Banconi (frankban) wrote : | # |
Please take a look.
https:/
File charm/repo.go (right):
https:/
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:/
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:/
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.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Roger Peppe (rogpeppe) wrote : | # |
LGTM with the below points addressed.
thanks!
https:/
File cmd/juju/main.go (right):
https:/
cmd/juju/
"+err.Error()+"\n")
fmt.Fprintf(
to be consistent with cmd.Main
in general passing a non-constant argument to Fprintf-like functions is
not a good idea regardless.
https:/
cmd/juju/
i know it was like this before, but i think this should probably be
os.Exit(2).
https:/
File juju/conn.go (right):
https:/
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.
?
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
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:/
https:/
File cmd/juju/main.go (right):
https:/
cmd/juju/
"+err.Error()+"\n")
On 2013/04/09 16:22:59, rog wrote:
> fmt.Fprintf(
> 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:/
cmd/juju/
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:/
File juju/conn.go (right):
https:/
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.
Preview Diff
1 | === modified file 'charm/repo.go' | |||
2 | --- charm/repo.go 2013-04-09 14:37:05 +0000 | |||
3 | +++ charm/repo.go 2013-04-09 16:40:27 +0000 | |||
4 | @@ -7,7 +7,6 @@ | |||
5 | 7 | "fmt" | 7 | "fmt" |
6 | 8 | "io" | 8 | "io" |
7 | 9 | "io/ioutil" | 9 | "io/ioutil" |
8 | 10 | "launchpad.net/juju-core/environs/config" | ||
9 | 11 | "launchpad.net/juju-core/log" | 10 | "launchpad.net/juju-core/log" |
10 | 12 | "net/http" | 11 | "net/http" |
11 | 13 | "net/url" | 12 | "net/url" |
12 | @@ -16,6 +15,9 @@ | |||
13 | 16 | "strings" | 15 | "strings" |
14 | 17 | ) | 16 | ) |
15 | 18 | 17 | ||
16 | 18 | // CacheDir stores the charm cache directory path. | ||
17 | 19 | var CacheDir string | ||
18 | 20 | |||
19 | 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. |
20 | 20 | type InfoResponse struct { | 22 | type InfoResponse struct { |
21 | 21 | Revision int `json:"revision"` // Zero is valid. Can't omitempty. | 23 | Revision int `json:"revision"` // Zero is valid. Can't omitempty. |
22 | @@ -213,9 +215,13 @@ | |||
23 | 213 | } | 215 | } |
24 | 214 | 216 | ||
25 | 215 | // Get returns the charm referenced by curl. | 217 | // Get returns the charm referenced by curl. |
26 | 218 | // CacheDir must have been set, otherwise Get will panic. | ||
27 | 216 | func (s *CharmStore) Get(curl *URL) (Charm, error) { | 219 | func (s *CharmStore) Get(curl *URL) (Charm, error) { |
30 | 217 | cachePath := config.JujuHomePath("cache") | 220 | // The cache location must have been previously set. |
31 | 218 | if err := os.MkdirAll(cachePath, 0755); err != nil { | 221 | if CacheDir == "" { |
32 | 222 | panic("charm cache directory path is empty") | ||
33 | 223 | } | ||
34 | 224 | if err := os.MkdirAll(CacheDir, 0755); err != nil { | ||
35 | 219 | return nil, err | 225 | return nil, err |
36 | 220 | } | 226 | } |
37 | 221 | rev, digest, err := s.revision(curl) | 227 | rev, digest, err := s.revision(curl) |
38 | @@ -227,14 +233,14 @@ | |||
39 | 227 | } else if curl.Revision != rev { | 233 | } else if curl.Revision != rev { |
40 | 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()) |
41 | 229 | } | 235 | } |
43 | 230 | path := filepath.Join(cachePath, Quote(curl.String())+".charm") | 236 | path := filepath.Join(CacheDir, Quote(curl.String())+".charm") |
44 | 231 | if verify(path, digest) != nil { | 237 | if verify(path, digest) != nil { |
45 | 232 | resp, err := http.Get(s.BaseURL + "/charm/" + url.QueryEscape(curl.Path())) | 238 | resp, err := http.Get(s.BaseURL + "/charm/" + url.QueryEscape(curl.Path())) |
46 | 233 | if err != nil { | 239 | if err != nil { |
47 | 234 | return nil, err | 240 | return nil, err |
48 | 235 | } | 241 | } |
49 | 236 | defer resp.Body.Close() | 242 | defer resp.Body.Close() |
51 | 237 | f, err := ioutil.TempFile(cachePath, "charm-download") | 243 | f, err := ioutil.TempFile(CacheDir, "charm-download") |
52 | 238 | if err != nil { | 244 | if err != nil { |
53 | 239 | return nil, err | 245 | return nil, err |
54 | 240 | } | 246 | } |
55 | 241 | 247 | ||
56 | === modified file 'charm/repo_test.go' | |||
57 | --- charm/repo_test.go 2013-04-09 14:37:05 +0000 | |||
58 | +++ charm/repo_test.go 2013-04-09 16:40:27 +0000 | |||
59 | @@ -8,7 +8,6 @@ | |||
60 | 8 | "io/ioutil" | 8 | "io/ioutil" |
61 | 9 | . "launchpad.net/gocheck" | 9 | . "launchpad.net/gocheck" |
62 | 10 | "launchpad.net/juju-core/charm" | 10 | "launchpad.net/juju-core/charm" |
63 | 11 | "launchpad.net/juju-core/environs/config" | ||
64 | 12 | "launchpad.net/juju-core/log" | 11 | "launchpad.net/juju-core/log" |
65 | 13 | "launchpad.net/juju-core/testing" | 12 | "launchpad.net/juju-core/testing" |
66 | 14 | "net" | 13 | "net" |
67 | @@ -150,23 +149,24 @@ | |||
68 | 150 | type StoreSuite struct { | 149 | type StoreSuite struct { |
69 | 151 | server *MockStore | 150 | server *MockStore |
70 | 152 | store *charm.CharmStore | 151 | store *charm.CharmStore |
72 | 153 | oldJujuHome string | 152 | oldCacheDir string |
73 | 154 | } | 153 | } |
74 | 155 | 154 | ||
75 | 156 | var _ = Suite(&StoreSuite{}) | 155 | var _ = Suite(&StoreSuite{}) |
76 | 157 | 156 | ||
77 | 158 | func (s *StoreSuite) SetUpSuite(c *C) { | 157 | func (s *StoreSuite) SetUpSuite(c *C) { |
78 | 159 | s.server = NewMockStore(c) | 158 | s.server = NewMockStore(c) |
79 | 159 | s.oldCacheDir = charm.CacheDir | ||
80 | 160 | } | 160 | } |
81 | 161 | 161 | ||
82 | 162 | func (s *StoreSuite) SetUpTest(c *C) { | 162 | func (s *StoreSuite) SetUpTest(c *C) { |
84 | 163 | s.oldJujuHome = config.SetJujuHome(c.MkDir()) | 163 | charm.CacheDir = c.MkDir() |
85 | 164 | s.store = charm.NewStore("http://127.0.0.1:4444") | 164 | s.store = charm.NewStore("http://127.0.0.1:4444") |
86 | 165 | s.server.downloads = nil | 165 | s.server.downloads = nil |
87 | 166 | } | 166 | } |
88 | 167 | 167 | ||
89 | 168 | func (s *StoreSuite) TearDownSuite(c *C) { | 168 | func (s *StoreSuite) TearDownSuite(c *C) { |
91 | 169 | config.SetJujuHome(s.oldJujuHome) | 169 | charm.CacheDir = s.oldCacheDir |
92 | 170 | s.server.lis.Close() | 170 | s.server.lis.Close() |
93 | 171 | } | 171 | } |
94 | 172 | 172 | ||
95 | @@ -245,12 +245,12 @@ | |||
96 | 245 | } | 245 | } |
97 | 246 | 246 | ||
98 | 247 | func (s *StoreSuite) TestGetBadCache(c *C) { | 247 | func (s *StoreSuite) TestGetBadCache(c *C) { |
100 | 248 | c.Assert(os.Mkdir(config.JujuHomePath("cache"), 0777), IsNil) | 248 | c.Assert(os.Mkdir(filepath.Join(charm.CacheDir, "cache"), 0777), IsNil) |
101 | 249 | base := "cs:series/good" | 249 | base := "cs:series/good" |
102 | 250 | curl := charm.MustParseURL(base) | 250 | curl := charm.MustParseURL(base) |
103 | 251 | revCurl := charm.MustParseURL(base + "-23") | 251 | revCurl := charm.MustParseURL(base + "-23") |
104 | 252 | name := charm.Quote(revCurl.String()) + ".charm" | 252 | name := charm.Quote(revCurl.String()) + ".charm" |
106 | 253 | err := ioutil.WriteFile(config.JujuHomePath("cache", name), nil, 0666) | 253 | err := ioutil.WriteFile(filepath.Join(charm.CacheDir, "cache", name), nil, 0666) |
107 | 254 | c.Assert(err, IsNil) | 254 | c.Assert(err, IsNil) |
108 | 255 | ch, err := s.store.Get(curl) | 255 | ch, err := s.store.Get(curl) |
109 | 256 | c.Assert(err, IsNil) | 256 | c.Assert(err, IsNil) |
110 | 257 | 257 | ||
111 | === modified file 'cmd/juju/main.go' | |||
112 | --- cmd/juju/main.go 2013-04-05 18:51:03 +0000 | |||
113 | +++ cmd/juju/main.go 2013-04-09 16:40:27 +0000 | |||
114 | @@ -3,9 +3,8 @@ | |||
115 | 3 | import ( | 3 | import ( |
116 | 4 | "fmt" | 4 | "fmt" |
117 | 5 | "launchpad.net/juju-core/cmd" | 5 | "launchpad.net/juju-core/cmd" |
119 | 6 | "launchpad.net/juju-core/environs/config" | 6 | "launchpad.net/juju-core/juju" |
120 | 7 | "os" | 7 | "os" |
121 | 8 | "path/filepath" | ||
122 | 9 | ) | 8 | ) |
123 | 10 | 9 | ||
124 | 11 | // When we import an environment provider implementation | 10 | // When we import an environment provider implementation |
125 | @@ -23,27 +22,14 @@ | |||
126 | 23 | https://juju.ubuntu.com/ | 22 | https://juju.ubuntu.com/ |
127 | 24 | ` | 23 | ` |
128 | 25 | 24 | ||
129 | 26 | // checkJujuHome retrieves $JUJU_HOME or $HOME to set the juju home. | ||
130 | 27 | // In case both variables aren't set the command will exit with an | ||
131 | 28 | // error. | ||
132 | 29 | func checkJujuHome() { | ||
133 | 30 | jujuHome := os.Getenv("JUJU_HOME") | ||
134 | 31 | if jujuHome == "" { | ||
135 | 32 | home := os.Getenv("HOME") | ||
136 | 33 | if home == "" { | ||
137 | 34 | fmt.Fprintf(os.Stderr, "command failed: cannot determine juju home, neither $JUJU_HOME nor $HOME are set") | ||
138 | 35 | os.Exit(1) | ||
139 | 36 | } | ||
140 | 37 | jujuHome = filepath.Join(home, ".juju") | ||
141 | 38 | } | ||
142 | 39 | config.SetJujuHome(jujuHome) | ||
143 | 40 | } | ||
144 | 41 | |||
145 | 42 | // Main registers subcommands for the juju executable, and hands over control | 25 | // Main registers subcommands for the juju executable, and hands over control |
146 | 43 | // to the cmd package. This function is not redundant with main, because it | 26 | // to the cmd package. This function is not redundant with main, because it |
147 | 44 | // provides an entry point for testing with arbitrary command line arguments. | 27 | // provides an entry point for testing with arbitrary command line arguments. |
148 | 45 | func Main(args []string) { | 28 | func Main(args []string) { |
150 | 46 | checkJujuHome() | 29 | if err := juju.InitJujuHome(); err != nil { |
151 | 30 | fmt.Fprintf(os.Stderr, "error: %s\n", err) | ||
152 | 31 | os.Exit(2) | ||
153 | 32 | } | ||
154 | 47 | juju := cmd.NewSuperCommand(cmd.SuperCommandParams{ | 33 | juju := cmd.NewSuperCommand(cmd.SuperCommandParams{ |
155 | 48 | Name: "juju", | 34 | Name: "juju", |
156 | 49 | Doc: jujuDoc, | 35 | Doc: jujuDoc, |
157 | 50 | 36 | ||
158 | === modified file 'cmd/jujud/machine.go' | |||
159 | --- cmd/jujud/machine.go 2013-04-05 13:47:17 +0000 | |||
160 | +++ cmd/jujud/machine.go 2013-04-09 16:40:27 +0000 | |||
161 | @@ -3,6 +3,7 @@ | |||
162 | 3 | import ( | 3 | import ( |
163 | 4 | "fmt" | 4 | "fmt" |
164 | 5 | "launchpad.net/gnuflag" | 5 | "launchpad.net/gnuflag" |
165 | 6 | "launchpad.net/juju-core/charm" | ||
166 | 6 | "launchpad.net/juju-core/cmd" | 7 | "launchpad.net/juju-core/cmd" |
167 | 7 | "launchpad.net/juju-core/environs/agent" | 8 | "launchpad.net/juju-core/environs/agent" |
168 | 8 | "launchpad.net/juju-core/log" | 9 | "launchpad.net/juju-core/log" |
169 | @@ -13,6 +14,7 @@ | |||
170 | 13 | "launchpad.net/juju-core/worker/machiner" | 14 | "launchpad.net/juju-core/worker/machiner" |
171 | 14 | "launchpad.net/juju-core/worker/provisioner" | 15 | "launchpad.net/juju-core/worker/provisioner" |
172 | 15 | "launchpad.net/tomb" | 16 | "launchpad.net/tomb" |
173 | 17 | "path/filepath" | ||
174 | 16 | "time" | 18 | "time" |
175 | 17 | ) | 19 | ) |
176 | 18 | 20 | ||
177 | @@ -58,6 +60,7 @@ | |||
178 | 58 | if err := a.Conf.read(state.MachineTag(a.MachineId)); err != nil { | 60 | if err := a.Conf.read(state.MachineTag(a.MachineId)); err != nil { |
179 | 59 | return err | 61 | return err |
180 | 60 | } | 62 | } |
181 | 63 | charm.CacheDir = filepath.Join(a.Conf.DataDir, "charmcache") | ||
182 | 61 | defer log.Noticef("cmd/jujud: machine agent exiting") | 64 | defer log.Noticef("cmd/jujud: machine agent exiting") |
183 | 62 | defer a.tomb.Done() | 65 | defer a.tomb.Done() |
184 | 63 | 66 | ||
185 | 64 | 67 | ||
186 | === modified file 'cmd/jujud/machine_test.go' | |||
187 | --- cmd/jujud/machine_test.go 2013-04-09 09:32:06 +0000 | |||
188 | +++ cmd/jujud/machine_test.go 2013-04-09 16:40:27 +0000 | |||
189 | @@ -3,6 +3,7 @@ | |||
190 | 3 | import ( | 3 | import ( |
191 | 4 | "fmt" | 4 | "fmt" |
192 | 5 | . "launchpad.net/gocheck" | 5 | . "launchpad.net/gocheck" |
193 | 6 | "launchpad.net/juju-core/charm" | ||
194 | 6 | "launchpad.net/juju-core/cmd" | 7 | "launchpad.net/juju-core/cmd" |
195 | 7 | "launchpad.net/juju-core/environs/agent" | 8 | "launchpad.net/juju-core/environs/agent" |
196 | 8 | "launchpad.net/juju-core/environs/dummy" | 9 | "launchpad.net/juju-core/environs/dummy" |
197 | @@ -10,16 +11,26 @@ | |||
198 | 10 | "launchpad.net/juju-core/state/api" | 11 | "launchpad.net/juju-core/state/api" |
199 | 11 | "launchpad.net/juju-core/state/watcher" | 12 | "launchpad.net/juju-core/state/watcher" |
200 | 12 | "launchpad.net/juju-core/testing" | 13 | "launchpad.net/juju-core/testing" |
201 | 14 | "path/filepath" | ||
202 | 13 | "reflect" | 15 | "reflect" |
203 | 14 | "time" | 16 | "time" |
204 | 15 | ) | 17 | ) |
205 | 16 | 18 | ||
206 | 17 | type MachineSuite struct { | 19 | type MachineSuite struct { |
207 | 18 | agentSuite | 20 | agentSuite |
208 | 21 | oldCacheDir string | ||
209 | 19 | } | 22 | } |
210 | 20 | 23 | ||
211 | 21 | var _ = Suite(&MachineSuite{}) | 24 | var _ = Suite(&MachineSuite{}) |
212 | 22 | 25 | ||
213 | 26 | func (s *MachineSuite) SetUpSuite(c *C) { | ||
214 | 27 | s.oldCacheDir = charm.CacheDir | ||
215 | 28 | } | ||
216 | 29 | |||
217 | 30 | func (s *MachineSuite) TearDownSuite(c *C) { | ||
218 | 31 | charm.CacheDir = s.oldCacheDir | ||
219 | 32 | } | ||
220 | 33 | |||
221 | 23 | // primeAgent adds a new Machine to run the given jobs, and sets up the | 34 | // primeAgent adds a new Machine to run the given jobs, and sets up the |
222 | 24 | // machine agent's directory. It returns the new machine, the | 35 | // machine agent's directory. It returns the new machine, the |
223 | 25 | // agent's configuration and the tools currently running. | 36 | // agent's configuration and the tools currently running. |
224 | @@ -72,7 +83,7 @@ | |||
225 | 72 | } | 83 | } |
226 | 73 | 84 | ||
227 | 74 | func (s *MachineSuite) TestRunStop(c *C) { | 85 | func (s *MachineSuite) TestRunStop(c *C) { |
229 | 75 | m, _, _ := s.primeAgent(c, state.JobHostUnits) | 86 | m, ac, _ := s.primeAgent(c, state.JobHostUnits) |
230 | 76 | a := s.newAgent(c, m) | 87 | a := s.newAgent(c, m) |
231 | 77 | done := make(chan error) | 88 | done := make(chan error) |
232 | 78 | go func() { | 89 | go func() { |
233 | @@ -81,6 +92,7 @@ | |||
234 | 81 | err := a.Stop() | 92 | err := a.Stop() |
235 | 82 | c.Assert(err, IsNil) | 93 | c.Assert(err, IsNil) |
236 | 83 | c.Assert(<-done, IsNil) | 94 | c.Assert(<-done, IsNil) |
237 | 95 | c.Assert(charm.CacheDir, Equals, filepath.Join(ac.DataDir, "charmcache")) | ||
238 | 84 | } | 96 | } |
239 | 85 | 97 | ||
240 | 86 | func (s *MachineSuite) TestWithDeadMachine(c *C) { | 98 | func (s *MachineSuite) TestWithDeadMachine(c *C) { |
241 | 87 | 99 | ||
242 | === modified file 'juju/conn.go' | |||
243 | --- juju/conn.go 2013-04-08 15:27:15 +0000 | |||
244 | +++ juju/conn.go 2013-04-09 16:40:27 +0000 | |||
245 | @@ -11,12 +11,14 @@ | |||
246 | 11 | "launchpad.net/juju-core/charm" | 11 | "launchpad.net/juju-core/charm" |
247 | 12 | "launchpad.net/juju-core/constraints" | 12 | "launchpad.net/juju-core/constraints" |
248 | 13 | "launchpad.net/juju-core/environs" | 13 | "launchpad.net/juju-core/environs" |
249 | 14 | "launchpad.net/juju-core/environs/config" | ||
250 | 14 | "launchpad.net/juju-core/log" | 15 | "launchpad.net/juju-core/log" |
251 | 15 | "launchpad.net/juju-core/state" | 16 | "launchpad.net/juju-core/state" |
252 | 16 | "launchpad.net/juju-core/state/api/params" | 17 | "launchpad.net/juju-core/state/api/params" |
253 | 17 | "launchpad.net/juju-core/trivial" | 18 | "launchpad.net/juju-core/trivial" |
254 | 18 | "net/url" | 19 | "net/url" |
255 | 19 | "os" | 20 | "os" |
256 | 21 | "path/filepath" | ||
257 | 20 | "time" | 22 | "time" |
258 | 21 | ) | 23 | ) |
259 | 22 | 24 | ||
260 | @@ -405,3 +407,20 @@ | |||
261 | 405 | } | 407 | } |
262 | 406 | return validated | 408 | return validated |
263 | 407 | } | 409 | } |
264 | 410 | |||
265 | 411 | // InitJujuHome initializes the charm and environs/config packages to use | ||
266 | 412 | // default paths based on the $JUJU_HOME or $HOME environment variables. | ||
267 | 413 | // This function should be called before calling NewConn or Conn.Deploy. | ||
268 | 414 | func InitJujuHome() error { | ||
269 | 415 | jujuHome := os.Getenv("JUJU_HOME") | ||
270 | 416 | if jujuHome == "" { | ||
271 | 417 | home := os.Getenv("HOME") | ||
272 | 418 | if home == "" { | ||
273 | 419 | return errors.New("cannot determine juju home, neither $JUJU_HOME nor $HOME are set") | ||
274 | 420 | } | ||
275 | 421 | jujuHome = filepath.Join(home, ".juju") | ||
276 | 422 | } | ||
277 | 423 | config.SetJujuHome(jujuHome) | ||
278 | 424 | charm.CacheDir = filepath.Join(jujuHome, "charmcache") | ||
279 | 425 | return nil | ||
280 | 426 | } | ||
281 | 408 | 427 | ||
282 | === modified file 'juju/conn_test.go' | |||
283 | --- juju/conn_test.go 2013-04-02 04:52:41 +0000 | |||
284 | +++ juju/conn_test.go 2013-04-09 16:40:27 +0000 | |||
285 | @@ -6,6 +6,7 @@ | |||
286 | 6 | "launchpad.net/juju-core/charm" | 6 | "launchpad.net/juju-core/charm" |
287 | 7 | "launchpad.net/juju-core/constraints" | 7 | "launchpad.net/juju-core/constraints" |
288 | 8 | "launchpad.net/juju-core/environs" | 8 | "launchpad.net/juju-core/environs" |
289 | 9 | "launchpad.net/juju-core/environs/config" | ||
290 | 9 | "launchpad.net/juju-core/environs/dummy" | 10 | "launchpad.net/juju-core/environs/dummy" |
291 | 10 | "launchpad.net/juju-core/juju" | 11 | "launchpad.net/juju-core/juju" |
292 | 11 | "launchpad.net/juju-core/juju/testing" | 12 | "launchpad.net/juju-core/juju/testing" |
293 | @@ -474,3 +475,50 @@ | |||
294 | 474 | c.Assert(mcons, DeepEquals, cons) | 475 | c.Assert(mcons, DeepEquals, cons) |
295 | 475 | } | 476 | } |
296 | 476 | } | 477 | } |
297 | 478 | |||
298 | 479 | type InitJujuHomeSuite struct { | ||
299 | 480 | originalHome string | ||
300 | 481 | originalJujuHome string | ||
301 | 482 | } | ||
302 | 483 | |||
303 | 484 | var _ = Suite(&InitJujuHomeSuite{}) | ||
304 | 485 | |||
305 | 486 | func (s *InitJujuHomeSuite) SetUpTest(c *C) { | ||
306 | 487 | s.originalHome = os.Getenv("HOME") | ||
307 | 488 | s.originalJujuHome = os.Getenv("JUJU_HOME") | ||
308 | 489 | } | ||
309 | 490 | |||
310 | 491 | func (s *InitJujuHomeSuite) TearDownTest(c *C) { | ||
311 | 492 | os.Setenv("HOME", s.originalHome) | ||
312 | 493 | os.Setenv("JUJU_HOME", s.originalJujuHome) | ||
313 | 494 | } | ||
314 | 495 | |||
315 | 496 | func (s *InitJujuHomeSuite) TestJujuHome(c *C) { | ||
316 | 497 | os.Setenv("JUJU_HOME", "/my/juju/home") | ||
317 | 498 | err := juju.InitJujuHome() | ||
318 | 499 | c.Assert(err, IsNil) | ||
319 | 500 | c.Assert(config.JujuHome(), Equals, "/my/juju/home") | ||
320 | 501 | } | ||
321 | 502 | |||
322 | 503 | func (s *InitJujuHomeSuite) TestHome(c *C) { | ||
323 | 504 | os.Setenv("JUJU_HOME", "") | ||
324 | 505 | os.Setenv("HOME", "/my/home/") | ||
325 | 506 | err := juju.InitJujuHome() | ||
326 | 507 | c.Assert(err, IsNil) | ||
327 | 508 | c.Assert(config.JujuHome(), Equals, "/my/home/.juju") | ||
328 | 509 | } | ||
329 | 510 | |||
330 | 511 | func (s *InitJujuHomeSuite) TestError(c *C) { | ||
331 | 512 | os.Setenv("JUJU_HOME", "") | ||
332 | 513 | os.Setenv("HOME", "") | ||
333 | 514 | err := juju.InitJujuHome() | ||
334 | 515 | c.Assert(err, ErrorMatches, "cannot determine juju home.*") | ||
335 | 516 | } | ||
336 | 517 | |||
337 | 518 | func (s *InitJujuHomeSuite) TestCacheDir(c *C) { | ||
338 | 519 | os.Setenv("JUJU_HOME", "/foo/bar") | ||
339 | 520 | c.Assert(charm.CacheDir, Equals, "") | ||
340 | 521 | err := juju.InitJujuHome() | ||
341 | 522 | c.Assert(err, IsNil) | ||
342 | 523 | c.Assert(charm.CacheDir, Equals, "/foo/bar/charmcache") | ||
343 | 524 | } |
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: machine. go machine_ test.go
A [revision details]
M charm/repo.go
M charm/repo_test.go
M cmd/jujud/
M cmd/jujud/
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 net/juju- core/environs/ config" net/juju- core/log"
=== 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.
"launchpad.
"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. JujuHomePath( "cache" ) cachePath, 0755); err != nil { CacheDir, 0755); err != nil { Join(cachePath, Quote(curl. String( ))+".charm" ) Join(CacheDir, Quote(curl. String( ))+".charm" ) (curl.Path( ))) TempFile( cachePath, "charm-download") TempFile( CacheDir, "charm-download")
func (s *CharmStore) Get(curl *URL) (Charm, error) {
- cachePath := config.
- if err := os.MkdirAll(
+ // MachineAgent.Run should have already set the CacheDir.
+ if CacheDir == "" {
+ panic("the charm cache directory path is empty")
+ }
+ if err := os.MkdirAll(
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.
+ path := filepath.
if verify(path, digest) != nil {
resp, err := http.Get(s.baseURL + "/charm/" +
url.QueryEscape
if err != nil {
return nil, err
}
defer resp.Body.Close()
- f, err := ioutil.
+ f, err := ioutil.
if err != nil {
return nil, err
}
Index: charm/repo_test.go repo_test. go' net/gocheck" net/juju- core/charm" net/juju- core/environs/ config" net/juju- core/log"
=== modified file 'charm/
--- 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.
"launchpad.
- "launchpad.
"launchpad.
...