~go-bot/juju-core/trunk

« back to all changes in this revision

Viewing changes to environs/manual/bootstrap_test.go

[r=dimitern],[bug=1221134] various: production code and logging improvements

Fixed 4 slightly annoying, unrelated minor issues:
1. Refactored production code not to depend on
gocheck (manual provider and apiserver/charms).
As a drive-by fix, I refactored environs/manual
tests to be proper black-box unit tests, rather
than white-box tests in the manual package.
2. Fixed and improved tools download output via
curl and better handling of errors.
3. Added debug logging to environs sshstorage and
httpstorage, and the manual provider.
4. Reformatted and unified generated boilerplate
config across all providers, fixing bug #1221134 in
the process (-e env not properly explained).

Changes tested live with a manual and local environs
with added manually provisioned machines.

While testing I found out and filed this bug #1291292
(basically manual bootstrap is broken with ssl-hostname-
verification set to false, but this is due to a deeper
issue).

I tried to unify and fix when all commands report
"environment not bootstrapped", consistently across
providers, but it turned out like more work than I
originally thought, so I'll do a follow-up on that
(which will entail dropping support for 1.14 environments
without a .jenv file).

https://codereview.appspot.com/72860045/

R=jameinel, rogpeppe

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
// Copyright 2013 Canonical Ltd.
2
2
// Licensed under the AGPLv3, see LICENCE file for details.
3
3
 
4
 
package manual
 
4
package manual_test
5
5
 
6
6
import (
7
7
        "fmt"
14
14
        "launchpad.net/juju-core/environs/bootstrap"
15
15
        "launchpad.net/juju-core/environs/cloudinit"
16
16
        "launchpad.net/juju-core/environs/filestorage"
 
17
        "launchpad.net/juju-core/environs/manual"
17
18
        "launchpad.net/juju-core/environs/storage"
18
19
        "launchpad.net/juju-core/environs/tools"
19
20
        "launchpad.net/juju-core/instance"
59
60
        s.env.storage = storage
60
61
}
61
62
 
62
 
func (s *bootstrapSuite) getArgs(c *gc.C) BootstrapArgs {
 
63
func (s *bootstrapSuite) getArgs(c *gc.C) manual.BootstrapArgs {
63
64
        hostname, err := os.Hostname()
64
65
        c.Assert(err, gc.IsNil)
65
66
        toolsList, err := tools.FindBootstrapTools(s.Conn.Environ, tools.BootstrapToolsParams{})
66
67
        c.Assert(err, gc.IsNil)
67
68
        arch := "amd64"
68
 
        return BootstrapArgs{
 
69
        return manual.BootstrapArgs{
69
70
                Host:          hostname,
70
71
                DataDir:       "/var/lib/juju",
71
72
                Environ:       s.env,
83
84
        args.Host = "ubuntu@" + args.Host
84
85
 
85
86
        defer fakeSSH{SkipDetection: true}.install(c).Restore()
86
 
        err := Bootstrap(args)
 
87
        err := manual.Bootstrap(args)
87
88
        c.Assert(err, gc.IsNil)
88
89
 
89
90
        bootstrapState, err := bootstrap.LoadState(s.env.Storage())
91
92
        c.Assert(
92
93
                bootstrapState.StateInstances,
93
94
                gc.DeepEquals,
94
 
                []instance.Id{BootstrapInstanceId},
 
95
                []instance.Id{manual.BootstrapInstanceId},
95
96
        )
96
97
 
97
98
        // Do it all again; this should work, despite the fact that
98
99
        // there's a bootstrap state file. Existence for that is
99
100
        // checked in general bootstrap code (environs/bootstrap).
100
101
        defer fakeSSH{SkipDetection: true}.install(c).Restore()
101
 
        err = Bootstrap(args)
 
102
        err = manual.Bootstrap(args)
102
103
        c.Assert(err, gc.IsNil)
103
104
 
104
105
        // We *do* check that the machine has no juju* upstart jobs, though.
107
108
                SkipDetection:      true,
108
109
                SkipProvisionAgent: true,
109
110
        }.install(c).Restore()
110
 
        err = Bootstrap(args)
111
 
        c.Assert(err, gc.Equals, ErrProvisioned)
 
111
        err = manual.Bootstrap(args)
 
112
        c.Assert(err, gc.Equals, manual.ErrProvisioned)
112
113
}
113
114
 
114
115
func (s *bootstrapSuite) TestBootstrapScriptFailure(c *gc.C) {
115
116
        args := s.getArgs(c)
116
117
        args.Host = "ubuntu@" + args.Host
117
118
        defer fakeSSH{SkipDetection: true, ProvisionAgentExitCode: 1}.install(c).Restore()
118
 
        err := Bootstrap(args)
 
119
        err := manual.Bootstrap(args)
119
120
        c.Assert(err, gc.NotNil)
120
121
 
121
122
        // Since the script failed, the state file should have been
127
128
func (s *bootstrapSuite) TestBootstrapEmptyDataDir(c *gc.C) {
128
129
        args := s.getArgs(c)
129
130
        args.DataDir = ""
130
 
        c.Assert(Bootstrap(args), gc.ErrorMatches, "data-dir argument is empty")
 
131
        c.Assert(manual.Bootstrap(args), gc.ErrorMatches, "data-dir argument is empty")
131
132
}
132
133
 
133
134
func (s *bootstrapSuite) TestBootstrapEmptyHost(c *gc.C) {
134
135
        args := s.getArgs(c)
135
136
        args.Host = ""
136
 
        c.Assert(Bootstrap(args), gc.ErrorMatches, "host argument is empty")
 
137
        c.Assert(manual.Bootstrap(args), gc.ErrorMatches, "host argument is empty")
137
138
}
138
139
 
139
140
func (s *bootstrapSuite) TestBootstrapNilEnviron(c *gc.C) {
140
141
        args := s.getArgs(c)
141
142
        args.Environ = nil
142
 
        c.Assert(Bootstrap(args), gc.ErrorMatches, "environ argument is nil")
 
143
        c.Assert(manual.Bootstrap(args), gc.ErrorMatches, "environ argument is nil")
143
144
}
144
145
 
145
146
func (s *bootstrapSuite) TestBootstrapNoMatchingTools(c *gc.C) {
147
148
        args := s.getArgs(c)
148
149
        args.PossibleTools = nil
149
150
        defer fakeSSH{SkipDetection: true, SkipProvisionAgent: true}.install(c).Restore()
150
 
        c.Assert(Bootstrap(args), gc.ErrorMatches, "possible tools is empty")
 
151
        c.Assert(manual.Bootstrap(args), gc.ErrorMatches, "possible tools is empty")
151
152
 
152
153
        // Non-empty list, but none that match the series/arch.
153
154
        args = s.getArgs(c)
154
155
        args.Series = "edgy"
155
156
        defer fakeSSH{SkipDetection: true, SkipProvisionAgent: true}.install(c).Restore()
156
 
        c.Assert(Bootstrap(args), gc.ErrorMatches, "no matching tools available")
 
157
        c.Assert(manual.Bootstrap(args), gc.ErrorMatches, "no matching tools available")
157
158
}
158
159
 
159
160
func (s *bootstrapSuite) TestBootstrapToolsFileURL(c *gc.C) {
170
171
}
171
172
 
172
173
func (s *bootstrapSuite) testBootstrapToolsURL(c *gc.C, toolsURL, expectedURL string) {
173
 
        s.PatchValue(&provisionMachineAgent, func(host string, mcfg *cloudinit.MachineConfig, w io.Writer) error {
 
174
        s.PatchValue(manual.ProvisionMachineAgent, func(host string, mcfg *cloudinit.MachineConfig, w io.Writer) error {
174
175
                c.Assert(mcfg.Tools.URL, gc.Equals, expectedURL)
175
176
                return nil
176
177
        })
177
178
        args := s.getArgs(c)
178
179
        args.PossibleTools[0].URL = toolsURL
179
180
        defer fakeSSH{SkipDetection: true}.install(c).Restore()
180
 
        err := Bootstrap(args)
 
181
        err := manual.Bootstrap(args)
181
182
        c.Assert(err, gc.IsNil)
182
183
}