Merge lp:~thumper/juju-core/use-errgo into lp:~go-bot/juju-core/trunk

Proposed by Tim Penhey
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
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.

https://codereview.appspot.com/59930043/

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.

https://codereview.appspot.com/59930043/

To post a comment you must log in.
Revision history for this message
Tim Penhey (thumper) wrote :

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):
   A [revision details]
   M agent/agent.go
   M agent/tools/toolsdir.go
   M cert/cert.go
   M cmd/juju/bootstrap.go
   M constraints/constraints.go
   M dependencies.tsv
   A dependencies_test.go
   M environs/cloudinit.go
   M environs/cloudinit/cloudinit.go
   M environs/config/config.go
   M environs/configstore/disk.go
   M environs/open.go
   M state/apiserver/charms.go
   M state/apiserver/client/client.go
   M worker/firewaller/firewaller.go

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

https://codereview.appspot.com/59930043/diff/1/dependencies_test.go
File dependencies_test.go (right):

https://codereview.appspot.com/59930043/diff/1/dependencies_test.go#newcode30
dependencies_test.go:30: func (*dependenciesTest)
TestDependenciesTsvFormat(c *gc.C) {
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.

https://codereview.appspot.com/59930043/

Revision history for this message
John A Meinel (jameinel) wrote :

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 02/04/2014 03:57 PM, Roger Peppe wrote:
>
> https://codereview.appspot.com/59930043/diff/1/dependencies_test.go
>
>
File dependencies_test.go (right):
>
> https://codereview.appspot.com/59930043/diff/1/dependencies_test.go#newcode30
>
>
dependencies_test.go:30: func (*dependenciesTest)
> TestDependenciesTsvFormat(c *gc.C) { 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.
>
> https://codereview.appspot.com/59930043/
>

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://www.enigmail.net/

iEYEARECAAYFAlLw8kgACgkQJdeBCYSNAAPFowCePA3p9JoEFfj5697wqoStX9Mx
LzwAoLuDnRcPqSWcCUkpQSZzorSI7oQM
=3BxQ
-----END PGP SIGNATURE-----

Revision history for this message
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://codereview.appspot.com/59930043/diff/1/dependencies_test.go
>>
>>
> File dependencies_test.go (right):
>>
>> https://codereview.appspot.com/59930043/diff/1/dependencies_test.go#newcode30
>>
>>
> dependencies_test.go:30: func (*dependenciesTest)
>> TestDependenciesTsvFormat(c *gc.C) { 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.
>>
>> https://codereview.appspot.com/59930043/
>>
>
> 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?

Revision history for this message
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://www.enigmail.net/

iEYEARECAAYFAlLw9HUACgkQJdeBCYSNAANhjACgrbEUX2tmk+9r1HZJwTK5xA/s
ZPEAnijeFvfnHhubPtUHf7bcsV0k4Vm/
=8tSa
-----END PGP SIGNATURE-----

Revision history for this message
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.

Revision history for this message
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://www.enigmail.net/

iEYEARECAAYFAlLxABAACgkQJdeBCYSNAAMowwCfTCqU4gVWdRbdctezwkH7O4zH
BTgAoJn7zDnpOha3d/eSn0mvjAT0jPo/
=jyiJ
-----END PGP SIGNATURE-----

Revision history for this message
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

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
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 }

Subscribers

People subscribed via source and target branches

to status/vote changes: