Merge lp:~sidnei/juju-core/lxc-mirror into lp:~go-bot/juju-core/trunk

Proposed by Sidnei da Silva
Status: Merged
Approved by: Sidnei da Silva
Approved revision: no longer in the source branch.
Merged at revision: 1603
Proposed branch: lp:~sidnei/juju-core/lxc-mirror
Merge into: lp:~go-bot/juju-core/trunk
Diff against target: 349 lines (+177/-19)
6 files modified
cloudinit/cloudinit_test.go (+7/-0)
cloudinit/options.go (+6/-0)
container/lxc/lxc.go (+30/-0)
container/lxc/lxc_test.go (+29/-2)
utils/apt.go (+34/-8)
utils/apt_test.go (+71/-9)
To merge this branch: bzr merge lp:~sidnei/juju-core/lxc-mirror
Reviewer Review Type Date Requested Status
Scott Moser (community) Approve
Review via email: mp+177737@code.launchpad.net

Commit message

Fetch apt proxy config via host apt-config

Since we're passing custom userdata to the ubuntu-cloud lxc template, it ends
up not setting the apt_mirror to the MIRROR setting. Read apt proxy
configuration from the container's host instead via the apt-config command and
inject that into the container via apt_proxy cloud init setting for the http
proxy plus a runcmd that writes /etc/apt/apt.conf.d/99proxy-extra with the
same config as the host for the remaing settings not supported explicitly by
cloud-init at the moment.

https://codereview.appspot.com/12143043/

R=dimitern, rogpeppe, smoser

Description of the change

Fetch apt proxy config via host apt-config

Since we're passing custom userdata to the ubuntu-cloud lxc template, it ends
up not setting the apt_mirror to the MIRROR setting. Read apt proxy
configuration from the container's host instead via the apt-config command and
inject that into the container via apt_proxy cloud init setting for the http
proxy plus a runcmd that writes /etc/apt/apt.conf.d/99proxy-extra with the
same config as the host for the remaing settings not supported explicitly by
cloud-init at the moment.

https://codereview.appspot.com/12143043/

To post a comment you must log in.
Revision history for this message
Sidnei da Silva (sidnei) wrote :

Reviewers: mp+177737_code.launchpad.net,

Message:
Please take a look.

Description:
Fetch MIRROR setting from /etc/default/lxc

Since we're passing custom userdata to the ubuntu-cloud lxc template, it
ends
up not setting the apt_mirror to the MIRROR setting. One could argue
that the
template should be fixed instead to always set the apt_mirror if it's
unset in
the custom userdata, but that's a separate discussion.

https://code.launchpad.net/~sidnei/juju-core/lxc-mirror/+merge/177737

(do not edit description out of merge proposal)

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

Affected files:
   A [revision details]
   M agent/agent.go
   M cloudinit/cloudinit_test.go
   M cloudinit/options.go
   M container/lxc/lxc.go
   M container/lxc/lxc_test.go
   M environs/cloudinit/cloudinit.go
   M environs/cloudinit/cloudinit_test.go
   M utils/apt.go
   M utils/apt_test.go

Revision history for this message
Sidnei da Silva (sidnei) wrote :
Revision history for this message
Dimiter Naydenov (dimitern) wrote :

LGTM, although I think I reviewed part of that as a previous CL
(AddFile, AddScripts, etc.) did that one get merged here?

https://codereview.appspot.com/12143043/diff/7001/container/lxc/lxc_test.go
File container/lxc/lxc_test.go (right):

https://codereview.appspot.com/12143043/diff/7001/container/lxc/lxc_test.go#newcode46
container/lxc/lxc_test.go:46: []byte(aptConfig), 0755)

Please put 0755 on a separate line, like the other args.

https://codereview.appspot.com/12143043/

Revision history for this message
Sidnei da Silva (sidnei) wrote :
Revision history for this message
Sidnei da Silva (sidnei) wrote :

Please take a look.

https://codereview.appspot.com/12143043/diff/7001/container/lxc/lxc_test.go
File container/lxc/lxc_test.go (right):

https://codereview.appspot.com/12143043/diff/7001/container/lxc/lxc_test.go#newcode46
container/lxc/lxc_test.go:46: []byte(aptConfig), 0755)
On 2013/08/05 10:46:08, dimitern wrote:

> Please put 0755 on a separate line, like the other args.

Done.

https://codereview.appspot.com/12143043/

Revision history for this message
Sidnei da Silva (sidnei) wrote :
Revision history for this message
Roger Peppe (rogpeppe) wrote :

Looks OK to me, although I'm not qualified to
review it - I have no knowledge of apt proxy
settings, and given that we can't have tests that
actually test this for real, I'd be happier if it's
reviewed by someone that does.

Some suggestions below.

https://codereview.appspot.com/12143043/diff/15002/container/lxc/lxc_test.go
File container/lxc/lxc_test.go (right):

https://codereview.appspot.com/12143043/diff/15002/container/lxc/lxc_test.go#newcode124
container/lxc/lxc_test.go:124: c.Assert(scripts[len(scripts)-4],
gc.Equals, "start jujud-machine-1-lxc-0")
c.Assert(scripts[len(scripts)-4:], gc.DeepEquals, []string{
     "start juju-machine-1-lxc-0",
     "install -m 600 /dev/null '/etc/apt.conf.d/99proxy-extra'",
     etc
})

?

https://codereview.appspot.com/12143043/diff/15002/utils/apt.go
File utils/apt.go (right):

https://codereview.appspot.com/12143043/diff/15002/utils/apt.go#newcode32
utils/apt.go:32: var commandOutput = osCommandOutput

var commandOutput = exec.Cmd.Output

(and you can delete the osCommandOutput definition
and probably move most of the comment onto commandOutput)

https://codereview.appspot.com/12143043/diff/15002/utils/apt.go#newcode60
utils/apt.go:60: var (

No need to declare these here.

https://codereview.appspot.com/12143043/diff/15002/utils/apt.go#newcode70
utils/apt.go:70: if out, err = commandOutput(cmd); err != nil {

out, err := commandOutput(cmd)
if err != nil {
     return "", err
}
return strings.TrimSpace(string(out)), nil

https://codereview.appspot.com/12143043/diff/15002/utils/apt.go#newcode71
utils/apt.go:71: return "", err
If the command has failed for some reason other
than a missing apt-config command, this error
will be highly opaque (it will contain only
the apt-config exit code).

I suggest that you acquire the standard error output
too, and parcel it up into an error if
the command fails.

You could use the same runCommand hook mechanism that AptGetInstall
uses (and in fact, AptGetInstall suffers from the same issue, but that's
probably something to fix in another CL)

https://codereview.appspot.com/12143043/

Revision history for this message
Sidnei da Silva (sidnei) wrote :

Please take a look.

https://codereview.appspot.com/12143043/diff/15002/container/lxc/lxc_test.go
File container/lxc/lxc_test.go (right):

https://codereview.appspot.com/12143043/diff/15002/container/lxc/lxc_test.go#newcode124
container/lxc/lxc_test.go:124: c.Assert(scripts[len(scripts)-4],
gc.Equals, "start jujud-machine-1-lxc-0")
On 2013/08/05 16:05:34, rog wrote:
> c.Assert(scripts[len(scripts)-4:], gc.DeepEquals, []string{
> "start juju-machine-1-lxc-0",
> "install -m 600 /dev/null '/etc/apt.conf.d/99proxy-extra'",
> etc
> })

> ?

Done.

https://codereview.appspot.com/12143043/diff/15002/utils/apt.go
File utils/apt.go (right):

https://codereview.appspot.com/12143043/diff/15002/utils/apt.go#newcode32
utils/apt.go:32: var commandOutput = osCommandOutput
On 2013/08/05 16:05:34, rog wrote:

> var commandOutput = exec.Cmd.Output

> (and you can delete the osCommandOutput definition
> and probably move most of the comment onto commandOutput)

Done.

https://codereview.appspot.com/12143043/diff/15002/utils/apt.go#newcode60
utils/apt.go:60: var (
On 2013/08/05 16:05:34, rog wrote:

> No need to declare these here.

Done.

https://codereview.appspot.com/12143043/diff/15002/utils/apt.go#newcode70
utils/apt.go:70: if out, err = commandOutput(cmd); err != nil {
On 2013/08/05 16:05:34, rog wrote:

> out, err := commandOutput(cmd)
> if err != nil {
> return "", err
> }
> return strings.TrimSpace(string(out)), nil

Done.

https://codereview.appspot.com/12143043/diff/15002/utils/apt.go#newcode70
utils/apt.go:70: if out, err = commandOutput(cmd); err != nil {
On 2013/08/05 16:05:34, rog wrote:

> out, err := commandOutput(cmd)
> if err != nil {
> return "", err
> }
> return strings.TrimSpace(string(out)), nil

Done.

https://codereview.appspot.com/12143043/diff/15002/utils/apt.go#newcode71
utils/apt.go:71: return "", err
On 2013/08/05 16:05:34, rog wrote:
> If the command has failed for some reason other
> than a missing apt-config command, this error
> will be highly opaque (it will contain only
> the apt-config exit code).

> I suggest that you acquire the standard error output
> too, and parcel it up into an error if
> the command fails.

> You could use the same runCommand hook mechanism that AptGetInstall
> uses (and in fact, AptGetInstall suffers from the same issue, but
that's
> probably something to fix in another CL)

Done, fixed in this branch.

https://codereview.appspot.com/12143043/

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

LGTM with a couple of trivials.
Thanks a lot.

https://codereview.appspot.com/12143043/diff/22001/container/lxc/lxc_test.go
File container/lxc/lxc_test.go (right):

https://codereview.appspot.com/12143043/diff/22001/container/lxc/lxc_test.go#newcode128
container/lxc/lxc_test.go:128: "ifconfig"})

We'd usually put the }) on a new line here, so each string gets its own
line.

https://codereview.appspot.com/12143043/diff/22001/utils/apt.go
File utils/apt.go (right):

https://codereview.appspot.com/12143043/diff/22001/utils/apt.go#newcode61
utils/apt.go:61: "Acquire::ftp::Proxy"}

newline before } please

https://codereview.appspot.com/12143043/

Revision history for this message
Scott Moser (smoser) wrote :

so i think this is reasonable.
the only comments (that I think Sidnei is aware of) is that https_proxy set via runcmnd will be too late to affect 'apt-get installs' from cloud-config.

they should work fine for subsequent juju charm installs. though.

the principle seems sound here.

review: Approve
Revision history for this message
Sidnei da Silva (sidnei) wrote :

Please take a look.

https://codereview.appspot.com/12143043/diff/22001/container/lxc/lxc_test.go
File container/lxc/lxc_test.go (right):

https://codereview.appspot.com/12143043/diff/22001/container/lxc/lxc_test.go#newcode128
container/lxc/lxc_test.go:128: "ifconfig"})
On 2013/08/05 17:35:39, rog wrote:

> We'd usually put the }) on a new line here, so each string gets its
own line.

Done.

https://codereview.appspot.com/12143043/diff/22001/utils/apt.go
File utils/apt.go (right):

https://codereview.appspot.com/12143043/diff/22001/utils/apt.go#newcode61
utils/apt.go:61: "Acquire::ftp::Proxy"}
On 2013/08/05 17:35:39, rog wrote:

> newline before } please

Done.

https://codereview.appspot.com/12143043/

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'cloudinit/cloudinit_test.go'
2--- cloudinit/cloudinit_test.go 2013-08-02 17:03:19 +0000
3+++ cloudinit/cloudinit_test.go 2013-08-05 17:47:24 +0000
4@@ -49,6 +49,13 @@
5 },
6 },
7 {
8+ "AptProxy",
9+ "apt_proxy: http://foo.com\n",
10+ func(cfg *cloudinit.Config) {
11+ cfg.SetAptProxy("http://foo.com")
12+ },
13+ },
14+ {
15 "AptMirror",
16 "apt_mirror: http://foo.com\n",
17 func(cfg *cloudinit.Config) {
18
19=== modified file 'cloudinit/options.go'
20--- cloudinit/options.go 2013-08-02 15:50:58 +0000
21+++ cloudinit/options.go 2013-08-05 17:47:24 +0000
22@@ -37,6 +37,12 @@
23 cfg.set("apt_update", yes, yes)
24 }
25
26+// SetAptProxy sets the URL to be used as the apt
27+// proxy.
28+func (cfg *Config) SetAptProxy(url string) {
29+ cfg.set("apt_proxy", url != "", url)
30+}
31+
32 // SetAptMirror sets the URL to be used as the apt
33 // mirror site. If not set, the URL is selected based
34 // on cloud metadata in EC2 - <region>.archive.ubuntu.com
35
36=== modified file 'container/lxc/lxc.go'
37--- container/lxc/lxc.go 2013-08-02 12:37:43 +0000
38+++ container/lxc/lxc.go 2013-08-05 17:47:24 +0000
39@@ -8,6 +8,7 @@
40 "io/ioutil"
41 "os"
42 "path/filepath"
43+ "regexp"
44 "strings"
45
46 "launchpad.net/golxc"
47@@ -22,6 +23,7 @@
48 "launchpad.net/juju-core/names"
49 "launchpad.net/juju-core/state"
50 "launchpad.net/juju-core/state/api"
51+ "launchpad.net/juju-core/utils"
52 )
53
54 var logger = loggo.GetLogger("juju.container.lxc")
55@@ -33,6 +35,7 @@
56 lxcContainerDir = "/var/lib/lxc"
57 lxcRestartDir = "/etc/lxc/auto"
58 lxcObjectFactory = golxc.Factory()
59+ aptHTTPProxyRE = regexp.MustCompile(`(?i)^Acquire::HTTP::Proxy\s+"([^"]+)";$`)
60 )
61
62 const (
63@@ -340,9 +343,36 @@
64 if err != nil {
65 return nil, err
66 }
67+
68+ // Run apt-config to fetch proxy settings from host. If no proxy
69+ // settings are configured, then we don't set up any proxy information
70+ // on the container.
71+ proxyConfig, err := utils.AptConfigProxy()
72+ if err != nil {
73+ return nil, err
74+ }
75+ if proxyConfig != "" {
76+ var proxyLines []string
77+ for _, line := range strings.Split(proxyConfig, "\n") {
78+ line = strings.TrimSpace(line)
79+ if m := aptHTTPProxyRE.FindStringSubmatch(line); m != nil {
80+ cloudConfig.SetAptProxy(m[1])
81+ } else {
82+ proxyLines = append(proxyLines, line)
83+ }
84+ }
85+ if len(proxyLines) > 0 {
86+ cloudConfig.AddFile(
87+ "/etc/apt/apt.conf.d/99proxy-extra",
88+ strings.Join(proxyLines, "\n"),
89+ 0600)
90+ }
91+ }
92+
93 // Run ifconfig to get the addresses of the internal container at least
94 // logged in the host.
95 cloudConfig.AddRunCmd("ifconfig")
96+
97 data, err := cloudConfig.Render()
98 if err != nil {
99 return nil, err
100
101=== modified file 'container/lxc/lxc_test.go'
102--- container/lxc/lxc_test.go 2013-07-31 23:07:56 +0000
103+++ container/lxc/lxc_test.go 2013-08-05 17:47:24 +0000
104@@ -30,6 +30,7 @@
105 type LxcSuite struct {
106 testing.LoggingSuite
107 lxc.TestSuite
108+ oldPath string
109 }
110
111 var _ = gc.Suite(&LxcSuite{})
112@@ -37,9 +38,18 @@
113 func (s *LxcSuite) SetUpSuite(c *gc.C) {
114 s.LoggingSuite.SetUpSuite(c)
115 s.TestSuite.SetUpSuite(c)
116+ tmpDir := c.MkDir()
117+ s.oldPath = os.Getenv("PATH")
118+ os.Setenv("PATH", tmpDir)
119+ err := ioutil.WriteFile(
120+ filepath.Join(tmpDir, "apt-config"),
121+ []byte(aptConfigScript),
122+ 0755)
123+ c.Assert(err, gc.IsNil)
124 }
125
126 func (s *LxcSuite) TearDownSuite(c *gc.C) {
127+ os.Setenv("PATH", s.oldPath)
128 s.TestSuite.TearDownSuite(c)
129 s.LoggingSuite.TearDownSuite(c)
130 }
131@@ -55,6 +65,17 @@
132 s.LoggingSuite.TearDownTest(c)
133 }
134
135+const (
136+ aptHTTPProxy = "http://1.2.3.4:3142"
137+ configProxyExtra = `Acquire::https::Proxy "false";
138+Acquire::ftp::Proxy "false";`
139+)
140+
141+var (
142+ configHttpProxy = fmt.Sprintf(`Acquire::http::Proxy "%s";`, aptHTTPProxy)
143+ aptConfigScript = fmt.Sprintf("#!/bin/sh\n echo '%s\n%s'", configHttpProxy, configProxyExtra)
144+)
145+
146 func StartContainer(c *gc.C, manager lxc.ContainerManager, machineId string) instance.Instance {
147 config := testing.EnvironConfig(c)
148 stateInfo := jujutesting.FakeStateInfo(machineId)
149@@ -93,13 +114,19 @@
150 err = goyaml.Unmarshal(data, &x)
151 c.Assert(err, gc.IsNil)
152
153+ c.Assert(x["apt_proxy"], gc.Equals, aptHTTPProxy)
154+
155 var scripts []string
156 for _, s := range x["runcmd"].([]interface{}) {
157 scripts = append(scripts, s.(string))
158 }
159
160- c.Assert(scripts[len(scripts)-2], gc.Equals, "start jujud-machine-1-lxc-0")
161- c.Assert(scripts[len(scripts)-1], gc.Equals, "ifconfig")
162+ c.Assert(scripts[len(scripts)-4:], gc.DeepEquals, []string{
163+ "start jujud-machine-1-lxc-0",
164+ "install -m 600 /dev/null '/etc/apt/apt.conf.d/99proxy-extra'",
165+ fmt.Sprintf("echo '%s' > '/etc/apt/apt.conf.d/99proxy-extra'", configProxyExtra),
166+ "ifconfig",
167+ })
168
169 // Check the mount point has been created inside the container.
170 c.Assert(filepath.Join(s.LxcDir, name, "rootfs/var/log/juju"), jc.IsDirectory)
171
172=== modified file 'utils/apt.go'
173--- utils/apt.go 2013-07-11 15:51:06 +0000
174+++ utils/apt.go 2013-08-05 17:47:24 +0000
175@@ -4,9 +4,12 @@
176 package utils
177
178 import (
179+ "fmt"
180 "os"
181 "os/exec"
182+ "strings"
183
184+ "launchpad.net/juju-core/log"
185 "launchpad.net/loggo"
186 )
187
188@@ -14,13 +17,9 @@
189
190 // Some helpful functions for running apt in a sane way
191
192-// osRunCommand calls cmd.Run, this is used as an overloading point so we can
193-// test what *would* be run without actually executing another program
194-func osRunCommand(cmd *exec.Cmd) error {
195- return cmd.Run()
196-}
197-
198-var runCommand = osRunCommand
199+// commandOutput calls cmd.Output, this is used as an overloading point so we
200+// can test what *would* be run without actually executing another program
201+var commandOutput = (*exec.Cmd).CombinedOutput
202
203 // This is the default apt-get command used in cloud-init, the various settings
204 // mean that apt won't actually block waiting for a prompt from the user.
205@@ -41,5 +40,32 @@
206 aptLogger.Infof("Running: %s", cmdArgs)
207 cmd := exec.Command(cmdArgs[0], cmdArgs[1:]...)
208 cmd.Env = append(os.Environ(), aptGetEnvOptions...)
209- return runCommand(cmd)
210+ out, err := commandOutput(cmd)
211+ if err != nil {
212+ log.Errorf("utils/apt: apt-get command failed: %v\nargs: %#v\n%s",
213+ err, cmdArgs, string(out))
214+ return fmt.Errorf("apt-get failed: %v", err)
215+ }
216+ return nil
217+}
218+
219+// AptConfigProxy will consult apt-config about the configured proxy
220+// settings. If there are no proxy settings configured, an empty string is
221+// returned.
222+func AptConfigProxy() (string, error) {
223+ cmdArgs := []string{
224+ "apt-config",
225+ "dump",
226+ "Acquire::http::Proxy",
227+ "Acquire::https::Proxy",
228+ "Acquire::ftp::Proxy",
229+ }
230+ cmd := exec.Command(cmdArgs[0], cmdArgs[1:]...)
231+ out, err := commandOutput(cmd)
232+ if err != nil {
233+ log.Errorf("utils/apt: apt-config command failed: %v\nargs: %#v\n%s",
234+ err, cmdArgs, string(out))
235+ return "", fmt.Errorf("apt-config failed: %v", err)
236+ }
237+ return strings.TrimSpace(string(out)), nil
238 }
239
240=== modified file 'utils/apt_test.go'
241--- utils/apt_test.go 2013-07-11 13:35:37 +0000
242+++ utils/apt_test.go 2013-08-05 17:47:24 +0000
243@@ -4,6 +4,7 @@
244 package utils
245
246 import (
247+ "fmt"
248 "os/exec"
249
250 gc "launchpad.net/gocheck"
251@@ -13,24 +14,25 @@
252
253 var _ = gc.Suite(&AptSuite{})
254
255-// hookRunCommand intercepts runCommand to a function that passes the actual
256-// command back via a channel, and returns the error passed into this function.
257-// It also returns a cleanup function so you can restore the original function
258-func (s *AptSuite) hookRunCommand(err error) (<-chan *exec.Cmd, func()) {
259+// hookCommandOutput intercepts commandOutput to a function that passes the
260+// actual command and it's output back via a channel, and returns the error
261+// passed into this function. It also returns a cleanup function so you can
262+// restore the original function
263+func (s *AptSuite) hookCommandOutput(output []byte, err error) (<-chan *exec.Cmd, func()) {
264 cmdChan := make(chan *exec.Cmd, 1)
265- origRunCommand := runCommand
266+ origCommandOutput := commandOutput
267 cleanup := func() {
268- runCommand = origRunCommand
269+ commandOutput = origCommandOutput
270 }
271- runCommand = func(cmd *exec.Cmd) error {
272+ commandOutput = func(cmd *exec.Cmd) ([]byte, error) {
273 cmdChan <- cmd
274- return err
275+ return output, err
276 }
277 return cmdChan, cleanup
278 }
279
280 func (s *AptSuite) TestOnePackage(c *gc.C) {
281- cmdChan, cleanup := s.hookRunCommand(nil)
282+ cmdChan, cleanup := s.hookCommandOutput([]byte{}, nil)
283 defer cleanup()
284 err := AptGetInstall("test-package")
285 c.Assert(err, gc.IsNil)
286@@ -42,3 +44,63 @@
287 })
288 c.Assert(cmd.Env[len(cmd.Env)-1], gc.Equals, "DEBIAN_FRONTEND=noninteractive")
289 }
290+
291+func (s *AptSuite) TestAptGetError(c *gc.C) {
292+ const expected = `E: frobnicator failure detected`
293+ cmdError := fmt.Errorf("error")
294+ cmdExpectedError := fmt.Errorf("apt-get failed: error")
295+ cmdChan, cleanup := s.hookCommandOutput([]byte(expected), cmdError)
296+ defer cleanup()
297+ err := AptGetInstall("foo")
298+ c.Assert(err, gc.DeepEquals, cmdExpectedError)
299+ cmd := <-cmdChan
300+ c.Assert(cmd.Args, gc.DeepEquals, []string{
301+ "apt-get", "--option=Dpkg::Options::=--force-confold",
302+ "--option=Dpkg::options::=--force-unsafe-io", "--assume-yes", "--quiet",
303+ "install", "foo",
304+ })
305+}
306+
307+func (s *AptSuite) TestConfigProxyEmpty(c *gc.C) {
308+ cmdChan, cleanup := s.hookCommandOutput([]byte{}, nil)
309+ defer cleanup()
310+ out, err := AptConfigProxy()
311+ c.Assert(err, gc.IsNil)
312+ cmd := <-cmdChan
313+ c.Assert(cmd.Args, gc.DeepEquals, []string{
314+ "apt-config", "dump", "Acquire::http::Proxy",
315+ "Acquire::https::Proxy", "Acquire::ftp::Proxy",
316+ })
317+ c.Assert(out, gc.Equals, "")
318+}
319+
320+func (s *AptSuite) TestConfigProxyConfigured(c *gc.C) {
321+ const expected = `Acquire::http::Proxy "10.0.3.1:3142";
322+Acquire::https::Proxy "false";`
323+ cmdChan, cleanup := s.hookCommandOutput([]byte(expected), nil)
324+ defer cleanup()
325+ out, err := AptConfigProxy()
326+ c.Assert(err, gc.IsNil)
327+ cmd := <-cmdChan
328+ c.Assert(cmd.Args, gc.DeepEquals, []string{
329+ "apt-config", "dump", "Acquire::http::Proxy",
330+ "Acquire::https::Proxy", "Acquire::ftp::Proxy",
331+ })
332+ c.Assert(out, gc.Equals, expected)
333+}
334+
335+func (s *AptSuite) TestConfigProxyError(c *gc.C) {
336+ const expected = `E: frobnicator failure detected`
337+ cmdError := fmt.Errorf("error")
338+ cmdExpectedError := fmt.Errorf("apt-config failed: error")
339+ cmdChan, cleanup := s.hookCommandOutput([]byte(expected), cmdError)
340+ defer cleanup()
341+ out, err := AptConfigProxy()
342+ c.Assert(err, gc.DeepEquals, cmdExpectedError)
343+ cmd := <-cmdChan
344+ c.Assert(cmd.Args, gc.DeepEquals, []string{
345+ "apt-config", "dump", "Acquire::http::Proxy",
346+ "Acquire::https::Proxy", "Acquire::ftp::Proxy",
347+ })
348+ c.Assert(out, gc.Equals, "")
349+}

Subscribers

People subscribed via source and target branches

to status/vote changes: