Merge lp:~thumper/juju-core/use-errgo into lp:~go-bot/juju-core/trunk
- use-errgo
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Tim Penhey |
Approved revision: | no longer in the source branch. |
Merged at revision: | 2294 |
Proposed branch: | lp:~thumper/juju-core/use-errgo |
Merge into: | lp:~go-bot/juju-core/trunk |
Diff against target: |
796 lines (+139/-77) 15 files modified
agent/agent.go (+11/-10) agent/tools/toolsdir.go (+3/-1) cert/cert.go (+4/-2) cmd/juju/bootstrap.go (+2/-1) constraints/constraints.go (+3/-1) dependencies.tsv (+1/-0) dependencies_test.go (+42/-0) environs/cloudinit.go (+3/-1) environs/cloudinit/cloudinit.go (+4/-3) environs/config/config.go (+2/-1) environs/configstore/disk.go (+5/-4) environs/open.go (+3/-1) state/apiserver/charms.go (+19/-17) state/apiserver/client/client.go (+12/-11) worker/firewaller/firewaller.go (+25/-24) |
To merge this branch: | bzr merge lp:~thumper/juju-core/use-errgo |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Juju Engineering | Pending | ||
Review via email: mp+204604@code.launchpad.net |
Commit message
Add errgo as a dep, and start using it.
errgo adds the ability to capture the location of
the error creation or annotation. Annotated errors
don't lose the original error.
Description of the change
Add errgo as a dep, and start using it.
errgo adds the ability to capture the location of
the error creation or annotation. Annotated errors
don't lose the original error.
Tim Penhey (thumper) wrote : | # |
William Reade (fwereade) wrote : | # |
Roger Peppe (rogpeppe) wrote : | # |
https:/
File dependencies_
https:/
dependencies_
TestDependencie
I think this would work work better as a test in .lbox.check.
There is no package in the root directory and this doesn't really seem
like a great reason to create one.
awk -F "\t" 'NF != 4 {exit 1}' || {
echo dependencies.tsv is in an invalid format >&2
exit 1
}
would do the job.
John A Meinel (jameinel) wrote : | # |
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
On 02/04/2014 03:57 PM, Roger Peppe wrote:
>
> https:/
>
>
File dependencies_
>
> https:/
>
>
dependencies_
> TestDependencie
> better as a test in .lbox.check. There is no package in the root
> directory and this doesn't really seem like a great reason to
> create one.
>
> awk -F "\t" 'NF != 4 {exit 1}' || { echo dependencies.tsv is in an
> invalid format >&2 exit 1 }
>
> would do the job.
>
> https:/
>
It would, but in a couple of weeks we won't be using lbox submit
anymore because we'll be switching bots, etc.
John
=:->
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.14 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://
iEYEARECAAYFAlL
LzwAoLuDnRcPqSW
=3BxQ
-----END PGP SIGNATURE-----
Roger Peppe (rogpeppe) wrote : | # |
On 4 February 2014 14:00, John A Meinel <email address hidden> wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> On 02/04/2014 03:57 PM, Roger Peppe wrote:
>>
>> https:/
>>
>>
> File dependencies_
>>
>> https:/
>>
>>
> dependencies_
>> TestDependencie
>> better as a test in .lbox.check. There is no package in the root
>> directory and this doesn't really seem like a great reason to
>> create one.
>>
>> awk -F "\t" 'NF != 4 {exit 1}' || { echo dependencies.tsv is in an
>> invalid format >&2 exit 1 }
>>
>> would do the job.
>>
>> https:/
>>
>
> It would, but in a couple of weeks we won't be using lbox submit
> anymore because we'll be switching bots, etc.
Presumably we'll still have some replacement that does similar prechecks
before letting the 'bot at it, won't we?
John A Meinel (jameinel) wrote : | # |
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
...
>
> Presumably we'll still have some replacement that does similar
> prechecks before letting the 'bot at it, won't we?
>
I'm not sure why we would need that, rather than just having the bot
do whatever checks we actually care about. (And perhaps a script so
you can easily run them yourself?)
John
=:->
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.14 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://
iEYEARECAAYFAlL
ZPEAnijeFvfnHhu
=8tSa
-----END PGP SIGNATURE-----
Roger Peppe (rogpeppe) wrote : | # |
On 4 February 2014 14:09, John A Meinel <email address hidden> wrote:
>> Presumably we'll still have some replacement that does similar
>> prechecks before letting the 'bot at it, won't we?
>
> I'm not sure why we would need that, rather than just having the bot
> do whatever checks we actually care about. (And perhaps a script so
> you can easily run them yourself?)
I find it very useful because it provides a quick sanity check that
things are OK rather than checking my email in 30 minutes
only to find I'd forgotten to gofmt a file.
If we *don't* need a pre-check for all the things we currently
pre-check (gofmt, govet, go build, checktesting), then
why would we need a test specifically for dependencies.tsv
and not those?
It seems to me as if the dependencies.tsv format test
falls in the same category as the other .lbox.check
tests, and should be grouped accordingly.
One might argue that all the .lbox.check tests should
be Go tests, and I would probably agree, but only if our tests
took an order of magnitude less time to run.
John A Meinel (jameinel) wrote : | # |
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
On 02/04/2014 04:33 PM, Roger Peppe wrote:
> On 4 February 2014 14:09, John A Meinel <email address hidden>
> wrote:
>>> Presumably we'll still have some replacement that does similar
>>> prechecks before letting the 'bot at it, won't we?
>>
>> I'm not sure why we would need that, rather than just having the
>> bot do whatever checks we actually care about. (And perhaps a
>> script so you can easily run them yourself?)
>
> I find it very useful because it provides a quick sanity check
> that things are OK rather than checking my email in 30 minutes only
> to find I'd forgotten to gofmt a file.
The bot already does go fmt automatically before running the test
suite, so you don't actually have to go fmt for the bot.
>
> If we *don't* need a pre-check for all the things we currently
> pre-check (gofmt, govet, go build, checktesting), then why would we
> need a test specifically for dependencies.tsv and not those?
Because we've repeatedly broken dependencies.tsv for CI but not noticed?
>
> It seems to me as if the dependencies.tsv format test falls in the
> same category as the other .lbox.check tests, and should be grouped
> accordingly.
>
> One might argue that all the .lbox.check tests should be Go tests,
> and I would probably agree, but only if our tests took an order of
> magnitude less time to run.
>
John
=:->
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.14 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://
iEYEARECAAYFAlL
BTgAoJn7zDnpOha
=jyiJ
-----END PGP SIGNATURE-----
Roger Peppe (rogpeppe) wrote : | # |
On 4 February 2014 15:00, John A Meinel <email address hidden> wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> On 02/04/2014 04:33 PM, Roger Peppe wrote:
>> On 4 February 2014 14:09, John A Meinel <email address hidden>
>> wrote:
>>>> Presumably we'll still have some replacement that does similar
>>>> prechecks before letting the 'bot at it, won't we?
>>>
>>> I'm not sure why we would need that, rather than just having the
>>> bot do whatever checks we actually care about. (And perhaps a
>>> script so you can easily run them yourself?)
>>
>> I find it very useful because it provides a quick sanity check
>> that things are OK rather than checking my email in 30 minutes only
>> to find I'd forgotten to gofmt a file.
>
> The bot already does go fmt automatically before running the test
> suite, so you don't actually have to go fmt for the bot.
>
>>
>> If we *don't* need a pre-check for all the things we currently
>> pre-check (gofmt, govet, go build, checktesting), then why would we
>> need a test specifically for dependencies.tsv and not those?
>
> Because we've repeatedly broken dependencies.tsv for CI but not noticed?
We have also repeatedly had tests with broken printf format
strings and that have failed to run tests by omitting a call to
gocheck.TestingT.
Can we not lose any of those checks, please?
And then the dependencies.tsv test can go alongside them, whereever
we decide they should live.
Preview Diff
1 | === modified file 'agent/agent.go' |
2 | --- agent/agent.go 2014-01-28 04:58:43 +0000 |
3 | +++ agent/agent.go 2014-02-04 06:44:26 +0000 |
4 | @@ -9,6 +9,7 @@ |
5 | "regexp" |
6 | "sync" |
7 | |
8 | + "github.com/errgo/errgo" |
9 | "github.com/loggo/loggo" |
10 | |
11 | "launchpad.net/juju-core/errors" |
12 | @@ -150,16 +151,16 @@ |
13 | // machine or unit agent. |
14 | func NewAgentConfig(params AgentConfigParams) (Config, error) { |
15 | if params.DataDir == "" { |
16 | - return nil, requiredError("data directory") |
17 | + return nil, errgo.Trace(requiredError("data directory")) |
18 | } |
19 | if params.Tag == "" { |
20 | - return nil, requiredError("entity tag") |
21 | + return nil, errgo.Trace(requiredError("entity tag")) |
22 | } |
23 | if params.Password == "" { |
24 | - return nil, requiredError("password") |
25 | + return nil, errgo.Trace(requiredError("password")) |
26 | } |
27 | if params.CACert == nil { |
28 | - return nil, requiredError("CA certificate") |
29 | + return nil, errgo.Trace(requiredError("CA certificate")) |
30 | } |
31 | // Note that the password parts of the state and api information are |
32 | // blank. This is by design. |
33 | @@ -202,10 +203,10 @@ |
34 | // a machine running the state server. |
35 | func NewStateMachineConfig(params StateMachineConfigParams) (Config, error) { |
36 | if params.StateServerCert == nil { |
37 | - return nil, requiredError("state server cert") |
38 | + return nil, errgo.Trace(requiredError("state server cert")) |
39 | } |
40 | if params.StateServerKey == nil { |
41 | - return nil, requiredError("state server key") |
42 | + return nil, errgo.Trace(requiredError("state server key")) |
43 | } |
44 | config0, err := NewAgentConfig(params.AgentConfigParams) |
45 | if err != nil { |
46 | @@ -308,7 +309,7 @@ |
47 | |
48 | func (c *configInternal) APIAddresses() ([]string, error) { |
49 | if c.apiDetails == nil { |
50 | - return []string{}, fmt.Errorf("No apidetails in config") |
51 | + return []string{}, errgo.New("No apidetails in config") |
52 | } |
53 | return append([]string{}, c.apiDetails.addresses...), nil |
54 | } |
55 | @@ -323,7 +324,7 @@ |
56 | |
57 | func (c *configInternal) check() error { |
58 | if c.stateDetails == nil && c.apiDetails == nil { |
59 | - return requiredError("state or API addresses") |
60 | + return errgo.Trace(requiredError("state or API addresses")) |
61 | } |
62 | if c.stateDetails != nil { |
63 | if err := checkAddrs(c.stateDetails.addresses, "state server address"); err != nil { |
64 | @@ -342,11 +343,11 @@ |
65 | |
66 | func checkAddrs(addrs []string, what string) error { |
67 | if len(addrs) == 0 { |
68 | - return requiredError(what) |
69 | + return errgo.Trace(requiredError(what)) |
70 | } |
71 | for _, a := range addrs { |
72 | if !validAddr.MatchString(a) { |
73 | - return fmt.Errorf("invalid %s %q", what, a) |
74 | + return errgo.New("invalid %s %q", what, a) |
75 | } |
76 | } |
77 | return nil |
78 | |
79 | === modified file 'agent/tools/toolsdir.go' |
80 | --- agent/tools/toolsdir.go 2013-09-25 00:18:35 +0000 |
81 | +++ agent/tools/toolsdir.go 2014-02-04 06:44:26 +0000 |
82 | @@ -15,6 +15,8 @@ |
83 | "path" |
84 | "strings" |
85 | |
86 | + "github.com/errgo/errgo" |
87 | + |
88 | coretools "launchpad.net/juju-core/tools" |
89 | "launchpad.net/juju-core/version" |
90 | ) |
91 | @@ -99,7 +101,7 @@ |
92 | } |
93 | name := path.Join(dir, hdr.Name) |
94 | if err := writeFile(name, os.FileMode(hdr.Mode&0777), tr); err != nil { |
95 | - return fmt.Errorf("tar extract %q failed: %v", name, err) |
96 | + return errgo.Annotatef(err, "tar extract %q failed", name) |
97 | } |
98 | } |
99 | toolsMetadataData, err := json.Marshal(tools) |
100 | |
101 | === modified file 'cert/cert.go' |
102 | --- cert/cert.go 2013-09-24 05:42:43 +0000 |
103 | +++ cert/cert.go 2014-02-04 06:44:26 +0000 |
104 | @@ -16,6 +16,8 @@ |
105 | "math/big" |
106 | "net" |
107 | "time" |
108 | + |
109 | + "github.com/errgo/errgo" |
110 | ) |
111 | |
112 | var KeyBits = 1024 |
113 | @@ -61,11 +63,11 @@ |
114 | func Verify(srvCertPEM, caCertPEM []byte, when time.Time) error { |
115 | caCert, err := ParseCert(caCertPEM) |
116 | if err != nil { |
117 | - return fmt.Errorf("cannot parse CA certificate: %v", err) |
118 | + return errgo.Annotate(err, "cannot parse CA certificate") |
119 | } |
120 | srvCert, err := ParseCert(srvCertPEM) |
121 | if err != nil { |
122 | - return fmt.Errorf("cannot parse server certificate: %v", err) |
123 | + return errgo.Annotate(err, "cannot parse server certificate") |
124 | } |
125 | pool := x509.NewCertPool() |
126 | pool.AddCert(caCert) |
127 | |
128 | === modified file 'cmd/juju/bootstrap.go' |
129 | --- cmd/juju/bootstrap.go 2014-01-31 00:14:11 +0000 |
130 | +++ cmd/juju/bootstrap.go 2014-02-04 06:44:26 +0000 |
131 | @@ -9,6 +9,7 @@ |
132 | "os" |
133 | "strings" |
134 | |
135 | + "github.com/errgo/errgo" |
136 | "launchpad.net/gnuflag" |
137 | |
138 | "launchpad.net/juju-core/charm" |
139 | @@ -128,7 +129,7 @@ |
140 | // we'd otherwise use environ.Storage. |
141 | if bs, ok := environ.(environs.BootstrapStorager); ok { |
142 | if err := bs.EnableBootstrapStorage(bootstrapContext); err != nil { |
143 | - return fmt.Errorf("failed to enable bootstrap storage: %v", err) |
144 | + return errgo.Annotate(err, "failed to enable bootstrap storage") |
145 | } |
146 | } |
147 | if err := bootstrap.EnsureNotBootstrapped(environ); err != nil { |
148 | |
149 | === modified file 'constraints/constraints.go' |
150 | --- constraints/constraints.go 2013-11-12 01:59:52 +0000 |
151 | +++ constraints/constraints.go 2014-02-04 06:44:26 +0000 |
152 | @@ -9,6 +9,8 @@ |
153 | "strconv" |
154 | "strings" |
155 | |
156 | + "github.com/errgo/errgo" |
157 | + |
158 | "launchpad.net/juju-core/instance" |
159 | ) |
160 | |
161 | @@ -207,7 +209,7 @@ |
162 | return fmt.Errorf("unknown constraint %q", name) |
163 | } |
164 | if err != nil { |
165 | - return fmt.Errorf("bad %q constraint: %v", name, err) |
166 | + return errgo.Annotatef(err, "bad %q constraint", name) |
167 | } |
168 | return nil |
169 | } |
170 | |
171 | === modified file 'dependencies.tsv' |
172 | --- dependencies.tsv 2014-01-29 14:14:20 +0000 |
173 | +++ dependencies.tsv 2014-02-04 06:44:26 +0000 |
174 | @@ -1,6 +1,7 @@ |
175 | code.google.com/p/go.crypto hg 6478cc9340cbbe6c04511280c5007722269108e9 184 |
176 | code.google.com/p/go.net hg 3591c18acabc99439c783463ef00e6dc277eee39 77 |
177 | labix.org/v2/mgo bzr gustavo@niemeyer.net-20131118213720-aralgr4ienh0gdyq 248 |
178 | +github.com/errgo/errgo git 93d72bf813883d1054cae1c001d3a46603f7f559 |
179 | github.com/loggo/loggo git 89458b4dc99692bc24efe9c2252d7587f8dc247b |
180 | launchpad.net/gnuflag bzr roger.peppe@canonical.com-20121003093437-zcyyw0lpvj2nifpk 12 |
181 | launchpad.net/goamz bzr roger.peppe@canonical.com-20131218155244-hbnkvlkkzy3vmlh9 44 |
182 | |
183 | === added file 'dependencies_test.go' |
184 | --- dependencies_test.go 1970-01-01 00:00:00 +0000 |
185 | +++ dependencies_test.go 2014-02-04 06:44:26 +0000 |
186 | @@ -0,0 +1,42 @@ |
187 | +// Copyright 2013 Canonical Ltd. |
188 | +// Licensed under the AGPLv3, see LICENCE file for details. |
189 | + |
190 | +package juju_test |
191 | + |
192 | +import ( |
193 | + "go/build" |
194 | + "io/ioutil" |
195 | + "path/filepath" |
196 | + "strings" |
197 | + "testing" |
198 | + |
199 | + gc "launchpad.net/gocheck" |
200 | +) |
201 | + |
202 | +func Test(t *testing.T) { |
203 | + gc.TestingT(t) |
204 | +} |
205 | + |
206 | +type dependenciesTest struct{} |
207 | + |
208 | +var _ = gc.Suite(&dependenciesTest{}) |
209 | + |
210 | +func projectRoot(c *gc.C) string { |
211 | + p, err := build.Import("launchpad.net/juju-core", "", build.FindOnly) |
212 | + c.Assert(err, gc.IsNil) |
213 | + return p.Dir |
214 | +} |
215 | + |
216 | +func (*dependenciesTest) TestDependenciesTsvFormat(c *gc.C) { |
217 | + filename := filepath.Join(projectRoot(c), "dependencies.tsv") |
218 | + content, err := ioutil.ReadFile(filename) |
219 | + c.Assert(err, gc.IsNil) |
220 | + |
221 | + for _, line := range strings.Split(string(content), "\n") { |
222 | + if line == "" { |
223 | + continue |
224 | + } |
225 | + segments := strings.Split(line, "\t") |
226 | + c.Assert(segments, gc.HasLen, 4) |
227 | + } |
228 | +} |
229 | |
230 | === modified file 'environs/cloudinit.go' |
231 | --- environs/cloudinit.go 2014-01-31 03:36:58 +0000 |
232 | +++ environs/cloudinit.go 2014-02-04 06:44:26 +0000 |
233 | @@ -6,6 +6,8 @@ |
234 | import ( |
235 | "fmt" |
236 | |
237 | + "github.com/errgo/errgo" |
238 | + |
239 | "launchpad.net/juju-core/agent" |
240 | coreCloudinit "launchpad.net/juju-core/cloudinit" |
241 | "launchpad.net/juju-core/constraints" |
242 | @@ -154,7 +156,7 @@ |
243 | // These really are directly relevant to running a state server. |
244 | cert, key, err := cfg.GenerateStateServerCertAndKey() |
245 | if err != nil { |
246 | - return fmt.Errorf("cannot generate state server certificate: %v", err) |
247 | + return errgo.Annotate(err, "cannot generate state server certificate") |
248 | } |
249 | mcfg.StateServerCert = cert |
250 | mcfg.StateServerKey = key |
251 | |
252 | === modified file 'environs/cloudinit/cloudinit.go' |
253 | --- environs/cloudinit/cloudinit.go 2014-01-30 19:54:48 +0000 |
254 | +++ environs/cloudinit/cloudinit.go 2014-02-04 06:44:26 +0000 |
255 | @@ -10,6 +10,7 @@ |
256 | "path" |
257 | "strings" |
258 | |
259 | + "github.com/errgo/errgo" |
260 | "launchpad.net/goyaml" |
261 | |
262 | "launchpad.net/juju-core/agent" |
263 | @@ -456,7 +457,7 @@ |
264 | } |
265 | cmds, err := acfg.WriteCommands() |
266 | if err != nil { |
267 | - return nil, err |
268 | + return nil, errgo.Annotate(err, "failed to write commands") |
269 | } |
270 | c.AddScripts(cmds...) |
271 | return acfg, nil |
272 | @@ -474,7 +475,7 @@ |
273 | conf := upstart.MachineAgentUpstartService(name, toolsDir, cfg.DataDir, cfg.LogDir, tag, machineId, nil) |
274 | cmds, err := conf.InstallCommands() |
275 | if err != nil { |
276 | - return fmt.Errorf("cannot make cloud-init upstart script for the %s agent: %v", tag, err) |
277 | + return errgo.Annotatef(err, "cannot make cloud-init upstart script for the %s agent", tag) |
278 | } |
279 | c.AddRunCmd(cloudinit.LogProgressCmd("Starting Juju machine agent (%s)", name)) |
280 | c.AddScripts(cmds...) |
281 | @@ -496,7 +497,7 @@ |
282 | conf := upstart.MongoUpstartService(name, cfg.DataDir, dbDir, cfg.StatePort) |
283 | cmds, err := conf.InstallCommands() |
284 | if err != nil { |
285 | - return fmt.Errorf("cannot make cloud-init upstart script for the state database: %v", err) |
286 | + return errgo.Annotate(err, "cannot make cloud-init upstart script for the state database") |
287 | } |
288 | c.AddRunCmd(cloudinit.LogProgressCmd("Starting MongoDB server (%s)", name)) |
289 | c.AddScripts(cmds...) |
290 | |
291 | === modified file 'environs/config/config.go' |
292 | --- environs/config/config.go 2014-02-04 01:15:09 +0000 |
293 | +++ environs/config/config.go 2014-02-04 06:44:26 +0000 |
294 | @@ -12,6 +12,7 @@ |
295 | "strings" |
296 | "time" |
297 | |
298 | + "github.com/errgo/errgo" |
299 | "github.com/loggo/loggo" |
300 | |
301 | "launchpad.net/juju-core/cert" |
302 | @@ -277,7 +278,7 @@ |
303 | caKey, caKeyOK := cfg.CAPrivateKey() |
304 | if caCertOK || caKeyOK { |
305 | if err := verifyKeyPair(caCert, caKey); err != nil { |
306 | - return fmt.Errorf("bad CA certificate/key in configuration: %v", err) |
307 | + return errgo.Annotate(err, "bad CA certificate/key in configuration") |
308 | } |
309 | } |
310 | |
311 | |
312 | === modified file 'environs/configstore/disk.go' |
313 | --- environs/configstore/disk.go 2014-01-28 04:58:43 +0000 |
314 | +++ environs/configstore/disk.go 2014-02-04 06:44:26 +0000 |
315 | @@ -9,6 +9,7 @@ |
316 | "os" |
317 | "path/filepath" |
318 | |
319 | + "github.com/errgo/errgo" |
320 | "github.com/loggo/loggo" |
321 | "launchpad.net/goyaml" |
322 | |
323 | @@ -162,14 +163,14 @@ |
324 | func (info *environInfo) Write() error { |
325 | data, err := goyaml.Marshal(info) |
326 | if err != nil { |
327 | - return fmt.Errorf("cannot marshal environment info: %v", err) |
328 | + return errgo.Annotate(err, "cannot marshal environment info") |
329 | } |
330 | // Create a temporary file and rename it, so that the data |
331 | // changes atomically. |
332 | parent, _ := filepath.Split(info.path) |
333 | tmpFile, err := ioutil.TempFile(parent, "") |
334 | if err != nil { |
335 | - return fmt.Errorf("cannot create temporary file: %v", err) |
336 | + return errgo.Annotate(err, "cannot create temporary file") |
337 | } |
338 | _, err = tmpFile.Write(data) |
339 | // N.B. We need to close the file before renaming it |
340 | @@ -177,11 +178,11 @@ |
341 | // error. |
342 | tmpFile.Close() |
343 | if err != nil { |
344 | - return fmt.Errorf("cannot write temporary file: %v", err) |
345 | + return errgo.Annotate(err, "cannot write temporary file") |
346 | } |
347 | if err := utils.ReplaceFile(tmpFile.Name(), info.path); err != nil { |
348 | os.Remove(tmpFile.Name()) |
349 | - return fmt.Errorf("cannot rename new environment info file: %v", err) |
350 | + return errgo.Annotate(err, "cannot rename new environment info file") |
351 | } |
352 | info.initialized = true |
353 | return nil |
354 | |
355 | === modified file 'environs/open.go' |
356 | --- environs/open.go 2013-10-04 12:18:17 +0000 |
357 | +++ environs/open.go 2014-02-04 06:44:26 +0000 |
358 | @@ -9,6 +9,8 @@ |
359 | "strings" |
360 | "time" |
361 | |
362 | + "github.com/errgo/errgo" |
363 | + |
364 | "launchpad.net/juju-core/cert" |
365 | "launchpad.net/juju-core/environs/config" |
366 | "launchpad.net/juju-core/environs/configstore" |
367 | @@ -243,7 +245,7 @@ |
368 | return err |
369 | } |
370 | if err := info.Destroy(); err != nil { |
371 | - return fmt.Errorf("cannot destroy environment configuration information: %v", err) |
372 | + return errgo.Annotate(err, "cannot destroy environment configuration information") |
373 | } |
374 | return nil |
375 | } |
376 | |
377 | === modified file 'state/apiserver/charms.go' |
378 | --- state/apiserver/charms.go 2014-01-31 15:14:34 +0000 |
379 | +++ state/apiserver/charms.go 2014-02-04 06:44:26 +0000 |
380 | @@ -18,6 +18,8 @@ |
381 | "path/filepath" |
382 | "strings" |
383 | |
384 | + "github.com/errgo/errgo" |
385 | + |
386 | "launchpad.net/juju-core/charm" |
387 | envtesting "launchpad.net/juju-core/environs/testing" |
388 | "launchpad.net/juju-core/names" |
389 | @@ -174,13 +176,13 @@ |
390 | } |
391 | zipr, err := zip.NewReader(f, fi.Size()) |
392 | if err != nil { |
393 | - return fmt.Errorf("cannot open charm archive: %v", err) |
394 | + return errgo.Annotate(err, "cannot open charm archive") |
395 | } |
396 | |
397 | // Find out the root dir prefix from the archive. |
398 | rootDir, err := h.findArchiveRootDir(zipr) |
399 | if err != nil { |
400 | - return fmt.Errorf("cannot read charm archive: %v", err) |
401 | + return errgo.Annotate(err, "cannot read charm archive") |
402 | } |
403 | if rootDir == "" { |
404 | // Normal charm, just use charm.ReadBundle(). |
405 | @@ -190,16 +192,16 @@ |
406 | // dir and then read is as a charm dir. |
407 | tempDir, err := ioutil.TempDir("", "charm-extract") |
408 | if err != nil { |
409 | - return fmt.Errorf("cannot create temp directory: %v", err) |
410 | + return errgo.Annotate(err, "cannot create temp directory") |
411 | } |
412 | defer os.RemoveAll(tempDir) |
413 | err = h.extractArchiveTo(zipr, rootDir, tempDir) |
414 | if err != nil { |
415 | - return fmt.Errorf("cannot extract charm archive: %v", err) |
416 | + return errgo.Annotate(err, "cannot extract charm archive") |
417 | } |
418 | dir, err := charm.ReadDir(tempDir) |
419 | if err != nil { |
420 | - return fmt.Errorf("cannot read extracted archive: %v", err) |
421 | + return errgo.Annotate(err, "cannot read extracted archive") |
422 | } |
423 | // Now repackage the dir as a bundle at the original path. |
424 | if err := f.Truncate(0); err != nil { |
425 | @@ -354,66 +356,66 @@ |
426 | // dir and the repackaged archive. |
427 | tempDir, err := ioutil.TempDir("", "charm-download") |
428 | if err != nil { |
429 | - return fmt.Errorf("cannot create temp directory: %v", err) |
430 | + return errgo.Annotate(err, "cannot create temp directory") |
431 | } |
432 | defer os.RemoveAll(tempDir) |
433 | extractPath := filepath.Join(tempDir, "extracted") |
434 | repackagedPath := filepath.Join(tempDir, "repackaged.zip") |
435 | repackagedArchive, err := os.Create(repackagedPath) |
436 | if err != nil { |
437 | - return fmt.Errorf("cannot repackage uploaded charm: %v", err) |
438 | + return errgo.Annotate(err, "cannot repackage uploaded charm") |
439 | } |
440 | defer repackagedArchive.Close() |
441 | |
442 | // Expand and repack it with the revision specified by curl. |
443 | archive.SetRevision(curl.Revision) |
444 | if err := archive.ExpandTo(extractPath); err != nil { |
445 | - return fmt.Errorf("cannot extract uploaded charm: %v", err) |
446 | + return errgo.Annotate(err, "cannot extract uploaded charm") |
447 | } |
448 | charmDir, err := charm.ReadDir(extractPath) |
449 | if err != nil { |
450 | - return fmt.Errorf("cannot read extracted charm: %v", err) |
451 | + return errgo.Annotate(err, "cannot read extracted charm") |
452 | } |
453 | // Bundle the charm and calculate its sha256 hash at the |
454 | // same time. |
455 | hash := sha256.New() |
456 | err = charmDir.BundleTo(io.MultiWriter(hash, repackagedArchive)) |
457 | if err != nil { |
458 | - return fmt.Errorf("cannot repackage uploaded charm: %v", err) |
459 | + return errgo.Annotate(err, "cannot repackage uploaded charm") |
460 | } |
461 | bundleSHA256 := hex.EncodeToString(hash.Sum(nil)) |
462 | size, err := repackagedArchive.Seek(0, 2) |
463 | if err != nil { |
464 | - return fmt.Errorf("cannot get charm file size: %v", err) |
465 | + return errgo.Annotate(err, "cannot get charm file size") |
466 | } |
467 | // Seek to the beginning so the subsequent Put will read |
468 | // the whole file again. |
469 | if _, err := repackagedArchive.Seek(0, 0); err != nil { |
470 | - return fmt.Errorf("cannot rewind the charm file reader: %v", err) |
471 | + return errgo.Annotate(err, "cannot rewind the charm file reader") |
472 | } |
473 | |
474 | // Now upload to provider storage. |
475 | storage, err := envtesting.GetEnvironStorage(h.state) |
476 | if err != nil { |
477 | - return fmt.Errorf("cannot access provider storage: %v", err) |
478 | + return errgo.Annotate(err, "cannot access provider storage") |
479 | } |
480 | name := charm.Quote(curl.String()) |
481 | if err := storage.Put(name, repackagedArchive, size); err != nil { |
482 | - return fmt.Errorf("cannot upload charm to provider storage: %v", err) |
483 | + return errgo.Annotate(err, "cannot upload charm to provider storage") |
484 | } |
485 | storageURL, err := storage.URL(name) |
486 | if err != nil { |
487 | - return fmt.Errorf("cannot get storage URL for charm: %v", err) |
488 | + return errgo.Annotate(err, "cannot get storage URL for charm") |
489 | } |
490 | bundleURL, err := url.Parse(storageURL) |
491 | if err != nil { |
492 | - return fmt.Errorf("cannot parse storage URL: %v", err) |
493 | + return errgo.Annotate(err, "cannot parse storage URL") |
494 | } |
495 | |
496 | // And finally, update state. |
497 | _, err = h.state.UpdateUploadedCharm(archive, curl, bundleURL, bundleSHA256) |
498 | if err != nil { |
499 | - return fmt.Errorf("cannot update uploaded charm in state: %v", err) |
500 | + return errgo.Annotate(err, "cannot update uploaded charm in state") |
501 | } |
502 | return nil |
503 | } |
504 | |
505 | === modified file 'state/apiserver/client/client.go' |
506 | --- state/apiserver/client/client.go 2014-01-30 14:22:46 +0000 |
507 | +++ state/apiserver/client/client.go 2014-02-04 06:44:26 +0000 |
508 | @@ -9,6 +9,7 @@ |
509 | "os" |
510 | "strings" |
511 | |
512 | + "github.com/errgo/errgo" |
513 | "github.com/loggo/loggo" |
514 | |
515 | "launchpad.net/juju-core/charm" |
516 | @@ -851,47 +852,47 @@ |
517 | store := config.AuthorizeCharmRepo(CharmStore, envConfig) |
518 | downloadedCharm, err := store.Get(charmURL) |
519 | if err != nil { |
520 | - return fmt.Errorf("cannot download charm %q: %v", charmURL.String(), err) |
521 | + return errgo.Annotatef(err, "cannot download charm %q", charmURL.String()) |
522 | } |
523 | |
524 | // Open it and calculate the SHA256 hash. |
525 | downloadedBundle, ok := downloadedCharm.(*charm.Bundle) |
526 | if !ok { |
527 | - return fmt.Errorf("expected a charm archive, got %T", downloadedCharm) |
528 | + return errgo.New("expected a charm archive, got %T", downloadedCharm) |
529 | } |
530 | archive, err := os.Open(downloadedBundle.Path) |
531 | if err != nil { |
532 | - return fmt.Errorf("cannot read downloaded charm: %v", err) |
533 | + return errgo.Annotate(err, "cannot read downloaded charm") |
534 | } |
535 | defer archive.Close() |
536 | bundleSHA256, size, err := utils.ReadSHA256(archive) |
537 | if err != nil { |
538 | - return fmt.Errorf("cannot calculate SHA256 hash of charm: %v", err) |
539 | + return errgo.Annotate(err, "cannot calculate SHA256 hash of charm") |
540 | } |
541 | if _, err := archive.Seek(0, 0); err != nil { |
542 | - return fmt.Errorf("cannot rewind charm archive: %v", err) |
543 | + return errgo.Annotate(err, "cannot rewind charm archive") |
544 | } |
545 | |
546 | // Get the environment storage and upload the charm. |
547 | env, err := environs.New(envConfig) |
548 | if err != nil { |
549 | - return fmt.Errorf("cannot access environment: %v", err) |
550 | + return errgo.Annotate(err, "cannot access environment") |
551 | } |
552 | storage := env.Storage() |
553 | archiveName, err := CharmArchiveName(charmURL.Name, charmURL.Revision) |
554 | if err != nil { |
555 | - return fmt.Errorf("cannot generate charm archive name: %v", err) |
556 | + return errgo.Annotate(err, "cannot generate charm archive name") |
557 | } |
558 | if err := storage.Put(archiveName, archive, size); err != nil { |
559 | - return fmt.Errorf("cannot upload charm to provider storage: %v", err) |
560 | + return errgo.Annotate(err, "cannot upload charm to provider storage") |
561 | } |
562 | storageURL, err := storage.URL(archiveName) |
563 | if err != nil { |
564 | - return fmt.Errorf("cannot get storage URL for charm: %v", err) |
565 | + return errgo.Annotate(err, "cannot get storage URL for charm") |
566 | } |
567 | bundleURL, err := url.Parse(storageURL) |
568 | if err != nil { |
569 | - return fmt.Errorf("cannot parse storage URL: %v", err) |
570 | + return errgo.Annotate(err, "cannot parse storage URL") |
571 | } |
572 | |
573 | // Finally, update the charm data in state and mark it as no longer pending. |
574 | @@ -903,7 +904,7 @@ |
575 | // us. This means we have to delete what we just uploaded |
576 | // to storage. |
577 | if err := storage.Remove(archiveName); err != nil { |
578 | - logger.Errorf("cannot remove duplicated charm from storage: %v", err) |
579 | + errgo.Annotate(err, "cannot remove duplicated charm from storage") |
580 | } |
581 | return nil |
582 | } |
583 | |
584 | === modified file 'worker/firewaller/firewaller.go' |
585 | --- worker/firewaller/firewaller.go 2014-01-23 17:08:36 +0000 |
586 | +++ worker/firewaller/firewaller.go 2014-02-04 06:44:26 +0000 |
587 | @@ -4,14 +4,13 @@ |
588 | package firewaller |
589 | |
590 | import ( |
591 | - "fmt" |
592 | - |
593 | + "github.com/errgo/errgo" |
594 | + "github.com/loggo/loggo" |
595 | "launchpad.net/tomb" |
596 | |
597 | "launchpad.net/juju-core/environs" |
598 | "launchpad.net/juju-core/environs/config" |
599 | "launchpad.net/juju-core/instance" |
600 | - "launchpad.net/juju-core/log" |
601 | "launchpad.net/juju-core/names" |
602 | apifirewaller "launchpad.net/juju-core/state/api/firewaller" |
603 | "launchpad.net/juju-core/state/api/params" |
604 | @@ -20,6 +19,8 @@ |
605 | "launchpad.net/juju-core/worker" |
606 | ) |
607 | |
608 | +var logger = loggo.GetLogger("juju.worker.firewaller") |
609 | + |
610 | // Firewaller watches the state for ports opened or closed |
611 | // and reflects those changes onto the backing environment. |
612 | type Firewaller struct { |
613 | @@ -93,7 +94,7 @@ |
614 | return err |
615 | } |
616 | if err := fw.environ.SetConfig(config); err != nil { |
617 | - log.Errorf("worker/firewaller: loaded invalid environment configuration: %v", err) |
618 | + logger.Errorf("loaded invalid environment configuration: %v", err) |
619 | } |
620 | case change, ok := <-fw.machinesWatcher.Changes(): |
621 | if !ok { |
622 | @@ -121,7 +122,7 @@ |
623 | case change := <-fw.portsChange: |
624 | change.unitd.ports = change.ports |
625 | if err := fw.flushUnits([]*unitData{change.unitd}); err != nil { |
626 | - return fmt.Errorf("cannot change firewall ports: %v", err) |
627 | + return errgo.Annotate(err, "cannot change firewall ports") |
628 | } |
629 | case change := <-fw.exposedChange: |
630 | change.serviced.exposed = change.exposed |
631 | @@ -130,7 +131,7 @@ |
632 | unitds = append(unitds, unitd) |
633 | } |
634 | if err := fw.flushUnits(unitds); err != nil { |
635 | - return fmt.Errorf("cannot change firewall ports: %v", err) |
636 | + return errgo.Annotate(err, "cannot change firewall ports") |
637 | } |
638 | } |
639 | } |
640 | @@ -139,7 +140,7 @@ |
641 | // stop a watcher with logging of a possible error. |
642 | func stop(what string, stopper watcher.Stopper) { |
643 | if err := stopper.Stop(); err != nil { |
644 | - log.Errorf("worker/firewaller: error stopping %s: %v", what, err) |
645 | + logger.Errorf("error stopping %s: %v", what, err) |
646 | } |
647 | } |
648 | |
649 | @@ -156,7 +157,7 @@ |
650 | if params.IsCodeNotFound(err) { |
651 | return nil |
652 | } else if err != nil { |
653 | - return fmt.Errorf("worker/firewaller: cannot watch machine units: %v", err) |
654 | + return errgo.Annotate(err, "cannot watch machine units") |
655 | } |
656 | unitw, err := m.WatchUnits() |
657 | if err != nil { |
658 | @@ -176,7 +177,7 @@ |
659 | if err != nil { |
660 | stop("units watcher", unitw) |
661 | delete(fw.machineds, tag) |
662 | - return fmt.Errorf("worker/firewaller: cannot respond to units changes for %q: %v", tag, err) |
663 | + return errgo.Annotatef(err, "cannot respond to units changes for %q", tag) |
664 | } |
665 | } |
666 | go machined.watchLoop(unitw) |
667 | @@ -266,14 +267,14 @@ |
668 | toOpen := Diff(wantedPorts, initialPorts) |
669 | toClose := Diff(initialPorts, wantedPorts) |
670 | if len(toOpen) > 0 { |
671 | - log.Infof("worker/firewaller: opening global ports %v", toOpen) |
672 | + logger.Infof("opening global ports %v", toOpen) |
673 | if err := fw.environ.OpenPorts(toOpen); err != nil { |
674 | return err |
675 | } |
676 | instance.SortPorts(toOpen) |
677 | } |
678 | if len(toClose) > 0 { |
679 | - log.Infof("worker/firewaller: closing global ports %v", toClose) |
680 | + logger.Infof("closing global ports %v", toClose) |
681 | if err := fw.environ.ClosePorts(toClose); err != nil { |
682 | return err |
683 | } |
684 | @@ -318,7 +319,7 @@ |
685 | toOpen := Diff(machined.ports, initialPorts) |
686 | toClose := Diff(initialPorts, machined.ports) |
687 | if len(toOpen) > 0 { |
688 | - log.Infof("worker/firewaller: opening instance ports %v for %q", |
689 | + logger.Infof("opening instance ports %v for %q", |
690 | toOpen, machined.tag) |
691 | if err := instances[0].OpenPorts(machineId, toOpen); err != nil { |
692 | // TODO(mue) Add local retry logic. |
693 | @@ -327,7 +328,7 @@ |
694 | instance.SortPorts(toOpen) |
695 | } |
696 | if len(toClose) > 0 { |
697 | - log.Infof("worker/firewaller: closing instance ports %v for %q", |
698 | + logger.Infof("closing instance ports %v for %q", |
699 | toClose, machined.tag) |
700 | if err := instances[0].ClosePorts(machineId, toClose); err != nil { |
701 | // TODO(mue) Add local retry logic. |
702 | @@ -361,7 +362,7 @@ |
703 | if unit == nil || unit.Life() == params.Dead || machineTag != knownMachineTag { |
704 | fw.forgetUnit(unitd) |
705 | changed = append(changed, unitd) |
706 | - log.Debugf("worker/firewaller: stopped watching unit %s", name) |
707 | + logger.Debugf("stopped watching unit %s", name) |
708 | } |
709 | } else if unit != nil && unit.Life() != params.Dead && fw.machineds[machineTag] != nil { |
710 | err = fw.startUnit(unit, machineTag) |
711 | @@ -369,11 +370,11 @@ |
712 | return err |
713 | } |
714 | changed = append(changed, fw.unitds[name]) |
715 | - log.Debugf("worker/firewaller: started watching unit %s", name) |
716 | + logger.Debugf("started watching unit %s", name) |
717 | } |
718 | } |
719 | if err := fw.flushUnits(changed); err != nil { |
720 | - return fmt.Errorf("cannot change firewall ports: %v", err) |
721 | + return errgo.Annotate(err, "cannot change firewall ports") |
722 | } |
723 | return nil |
724 | } |
725 | @@ -442,7 +443,7 @@ |
726 | return err |
727 | } |
728 | instance.SortPorts(toOpen) |
729 | - log.Infof("worker/firewaller: opened ports %v in environment", toOpen) |
730 | + logger.Infof("opened ports %v in environment", toOpen) |
731 | } |
732 | if len(toClose) > 0 { |
733 | if err := fw.environ.ClosePorts(toClose); err != nil { |
734 | @@ -450,7 +451,7 @@ |
735 | return err |
736 | } |
737 | instance.SortPorts(toClose) |
738 | - log.Infof("worker/firewaller: closed ports %v in environment", toClose) |
739 | + logger.Infof("closed ports %v in environment", toClose) |
740 | } |
741 | return nil |
742 | } |
743 | @@ -490,7 +491,7 @@ |
744 | return err |
745 | } |
746 | instance.SortPorts(toOpen) |
747 | - log.Infof("worker/firewaller: opened ports %v on %q", toOpen, machined.tag) |
748 | + logger.Infof("opened ports %v on %q", toOpen, machined.tag) |
749 | } |
750 | if len(toClose) > 0 { |
751 | if err := instances[0].ClosePorts(machineId, toClose); err != nil { |
752 | @@ -498,7 +499,7 @@ |
753 | return err |
754 | } |
755 | instance.SortPorts(toClose) |
756 | - log.Infof("worker/firewaller: closed ports %v on %q", toClose, machined.tag) |
757 | + logger.Infof("closed ports %v on %q", toClose, machined.tag) |
758 | } |
759 | return nil |
760 | } |
761 | @@ -522,7 +523,7 @@ |
762 | if err != nil { |
763 | return err |
764 | } |
765 | - log.Debugf("worker/firewaller: started watching %q", tag) |
766 | + logger.Debugf("started watching %q", tag) |
767 | } |
768 | return nil |
769 | } |
770 | @@ -539,7 +540,7 @@ |
771 | if err := machined.Stop(); err != nil { |
772 | return err |
773 | } |
774 | - log.Debugf("worker/firewaller: stopped watching %q", machined.tag) |
775 | + logger.Debugf("stopped watching %q", machined.tag) |
776 | return nil |
777 | } |
778 | |
779 | @@ -549,7 +550,7 @@ |
780 | serviced := unitd.serviced |
781 | machined := unitd.machined |
782 | if err := unitd.Stop(); err != nil { |
783 | - log.Errorf("worker/firewaller: unit watcher %q returned error when stopping: %v", name, err) |
784 | + logger.Errorf("unit watcher %q returned error when stopping: %v", name, err) |
785 | } |
786 | // Clean up after stopping. |
787 | delete(fw.unitds, name) |
788 | @@ -558,7 +559,7 @@ |
789 | if len(serviced.unitds) == 0 { |
790 | // Stop service data after all units are removed. |
791 | if err := serviced.Stop(); err != nil { |
792 | - log.Errorf("worker/firewaller: service watcher %q returned error when stopping: %v", serviced.service.Name(), err) |
793 | + logger.Errorf("service watcher %q returned error when stopping: %v", serviced.service.Name(), err) |
794 | } |
795 | delete(fw.serviceds, serviced.service.Name()) |
796 | } |
Reviewers: mp+204604_ code.launchpad. net,
Message:
Please take a look.
Description:
Add errgo as a dep, and start using it.
errgo adds the ability to capture the location of
the error creation or annotation. Annotated errors
don't lose the original error.
https:/ /code.launchpad .net/~thumper/ juju-core/ use-errgo/ +merge/ 204604
(do not edit description out of merge proposal)
Please review this at https:/ /codereview. appspot. com/59930043/
Affected files (+141, -77 lines): toolsdir. go bootstrap. go constraints. go test.go cloudinit. go cloudinit/ cloudinit. go config/ config. go configstore/ disk.go /charms. go /client/ client. go firewaller/ firewaller. go
A [revision details]
M agent/agent.go
M agent/tools/
M cert/cert.go
M cmd/juju/
M constraints/
M dependencies.tsv
A dependencies_
M environs/
M environs/
M environs/
M environs/
M environs/open.go
M state/apiserver
M state/apiserver
M worker/