Merge lp:~dstroppa/juju-core/joyent-provider-storage into lp:~go-bot/juju-core/trunk
- joyent-provider-storage
- Merge into trunk
Status: | Work in progress |
---|---|
Proposed branch: | lp:~dstroppa/juju-core/joyent-provider-storage |
Merge into: | lp:~go-bot/juju-core/trunk |
Diff against target: |
1198 lines (+685/-134) 13 files modified
.bzrignore (+2/-0) dependencies.tsv (+1/-0) provider/joyent/config.go (+41/-15) provider/joyent/config_test.go (+63/-47) provider/joyent/environ.go (+28/-13) provider/joyent/environ_firewall.go (+3/-3) provider/joyent/environ_instance.go (+4/-4) provider/joyent/export_test.go (+3/-2) provider/joyent/instance.go (+1/-1) provider/joyent/joyent_test.go (+167/-14) provider/joyent/provider.go (+5/-1) provider/joyent/storage.go (+178/-34) provider/joyent/storage_test.go (+189/-0) |
To merge this branch: | bzr merge lp:~dstroppa/juju-core/joyent-provider-storage |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Juju Engineering | Pending | ||
Review via email: mp+200851@code.launchpad.net |
Commit message
provider/joyent: Implementation of storage
Add storage implementation to joyent provider. Also
pulls in new gojoyent library dependency.
R=gz, jameinel
Description of the change
Joyent Provider - Storage impl
Daniele Stroppa (dstroppa) wrote : | # |
Please take a look.
Martin Packman (gz) wrote : | # |
Thanks for getting this next step up for review! Several things in need
of fixing:
https:/
File dependencies.tsv (right):
https:/
dependencies.tsv:7:
launchpad.
<email address hidden> 47
It seems gojoyent in turn depends on github.
tests in localservices/
That would also need adding here - do we want it as a dep or should the
tests just generate sample uuids through some other method?
https:/
File provider/
https:/
provider/
What's the reason to change this from external to internal testing?
https:/
provider/
"12:c3:
Not changed here, but duplicated later, so mentioning. These fake values
should be faker, rather than being for name and a real-looking key id.
Better to spot in test assertions and such like if it's testuser and
00:11:22:... or similar obvious made up values.
https:/
File provider/
https:/
provider/
"12:c3:
These values look very similar to the earlier ones, perhaps they need to
be in a shared location and accessed from there. Otherwise, same comment
applies, user and key-id should be more obviously fake.
https:/
File provider/
https:/
provider/
comtainer from the storage account.
Typo, 'coNtainer'.
https:/
provider/
can retrieve the object at, without any credentials
This may as well be an actual function doc comment.
https:/
provider/
time.Now(
I think the EC2 provider uses a mcuh longer duration, what a sensible
value is I'm less sure.
https:/
provider/
Remove.
https:/
provider/
error {
This is logic I'm not wild about having done (and slightly differently)
in all provide...
Daniele Stroppa (dstroppa) wrote : | # |
https:/
File provider/
https:/
provider/
comtainer from the storage account.
On 2014/01/09 17:50:34, gz wrote:
> Typo, 'coNtainer'.
Done.
https:/
provider/
can retrieve the object at, without any credentials
On 2014/01/09 17:50:34, gz wrote:
> This may as well be an actual function doc comment.
Done.
https:/
provider/
time.Now(
On 2014/01/09 17:50:34, gz wrote:
> I think the EC2 provider uses a mcuh longer duration, what a sensible
value is
> I'm less sure.
5 minutes is the value used in the Node.js SDK (used as reference). EC2,
Azure and OpenStack providers use 10 years. Changed to 10 years to be
consistent.
https:/
provider/
On 2014/01/09 17:50:34, gz wrote:
> Remove.
Done.
Daniele Stroppa (dstroppa) wrote : | # |
https:/
File dependencies.tsv (right):
https:/
dependencies.tsv:7:
launchpad.
<email address hidden> 47
On 2014/01/09 17:50:34, gz wrote:
> It seems gojoyent in turn depends on github.
tests in
> localservices/
> That would also need adding here - do we want it as a dep or should
the tests
> just generate sample uuids through some other method?
Replaced the gouuid dep with a custom method implemented with std libs.
Daniele Stroppa (dstroppa) wrote : | # |
https:/
File provider/
https:/
provider/
On 2014/01/09 17:50:34, gz wrote:
> What's the reason to change this from external to internal testing?
No reason actually, it was just a mistake. Changed it to external
testing.
Daniele Stroppa (dstroppa) wrote : | # |
https:/
File provider/
https:/
provider/
"12:c3:
On 2014/01/09 17:50:34, gz wrote:
> Not changed here, but duplicated later, so mentioning. These fake
values should
> be faker, rather than being for name and a real-looking key id. Better
to spot
> in test assertions and such like if it's testuser and 00:11:22:... or
similar
> obvious made up values.
Changed to obvious made up values.
Daniele Stroppa (dstroppa) wrote : | # |
https:/
File provider/
https:/
provider/
"12:c3:
On 2014/01/09 17:50:34, gz wrote:
> These values look very similar to the earlier ones, perhaps they need
to be in a
> shared location and accessed from there. Otherwise, same comment
applies, user
> and key-id should be more obviously fake.
Changed to valid fake values.
Daniele Stroppa (dstroppa) wrote : | # |
https:/
File provider/
https:/
provider/
On 2014/01/09 17:50:34, gz wrote:
> All the tests in this file bar TestURL fail when I run them here, with
> variations on:
> FAIL: storage_
> storage_
> s.assertContain
> storage_test.go:43:
> c.Assert(err, gc.IsNil)
> ... value *errors.
> &errors.
> errcode:
("failed to
> create directory: juju-test\ncaused by: Bad request
> https:/
request
> (https:/
unexpected
> status: 400; error info:
{\"code\
> header invalid: signature was not specified\"}")
> It seems they're escaping isolation, rather than using the test
services?
Changed the storage test to run against the local services instead of
the Joyent Live environment
Daniele Stroppa (dstroppa) wrote : | # |
Please take a look.
Martin Packman (gz) wrote : | # |
LGTM, should be ready to go with a settled gojoyent version.
William Reade (fwereade) wrote : | # |
Martin, is this ready to land now?
John A Meinel (jameinel) wrote : | # |
On 2014/01/23 16:23:42, gz wrote:
> LGTM, should be ready to go with a settled gojoyent version.
We're still hanging on this 10 days later. It does seem like we should
just land it so that we can start ratcheting forward rather than
delaying it.
Daniele Stroppa (dstroppa) wrote : | # |
Please take a look.
Go Bot (go-bot) wrote : | # |
The attempt to merge lp:~dstroppa/juju-core/joyent-provider-storage into lp:juju-core failed. Below is the output from the failed tests.
provider/
/usr/lib/
/home/
provider/
/usr/lib/
/home/
provider/
/usr/lib/
/home/
Go Bot (go-bot) wrote : | # |
The attempt to merge lp:~dstroppa/juju-core/joyent-provider-storage into lp:juju-core failed. Below is the output from the failed tests.
-------
FAIL: dependencies_
dependencies_
c.Assert(
... obtained []string = []string{
... n int = 4
OOPS: 0 passed, 1 FAILED
--- FAIL: Test (0.00 seconds)
FAIL
FAIL launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
? launchpad.
? launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
? launchpad.
? launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
? launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
? launchpad.
ok launchpad.
? launchpad.
? launchpad.
? launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
? launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
? launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
? launchpad.
Go Bot (go-bot) wrote : | # |
There are additional revisions which have not been approved in review. Please seek review and approval of these new revisions.
Go Bot (go-bot) wrote : | # |
The attempt to merge lp:~dstroppa/juju-core/joyent-provider-storage into lp:juju-core failed. Below is the output from the failed tests.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
? launchpad.
? launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
? launchpad.
? launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
? launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
? launchpad.
ok launchpad.
? launchpad.
? launchpad.
? launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
? launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
? launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
? launchpad.
ok launchpad.
ok launchpad.
? launchpad.
ok launchpad.
ok launchpad.
? launchpad.
ok launchpad.
ok launchpad.
? launchpad.
Go Bot (go-bot) wrote : | # |
The attempt to merge lp:~dstroppa/juju-core/joyent-provider-storage into lp:juju-core failed. Below is the output from the failed tests.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
? launchpad.
? launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
? launchpad.
? launchpad.
*** Test killed: ran too long (10m0s).
FAIL launchpad.
-------
FAIL: machine_
[LOG] 39.51530 DEBUG juju.environs.
[LOG] 44.18314 DEBUG juju.environs.tools reading v1.* tools
[LOG] 44.18320 INFO juju environs/testing: uploading FAKE tools 1.17.4-
[LOG] 44.18412 DEBUG juju.environs.tools no architecture specified when finding tools, looking for any
[LOG] 44.18413 DEBUG juju.environs.tools no series specified when finding tools, looking for any
[LOG] 44.18430 DEBUG juju.environs.
[LOG] 44.18432 DEBUG juju.environs.
[LOG] 44.18436 DEBUG juju.environs.
[LOG] 44.18437 DEBUG juju.environs.
[LOG] 44.18482 INFO juju.environs.tools Writing tools/streams/
[LOG] 44.18504 INFO juju.environs.tools Writing tools/streams/
[LOG] 44.18508 INFO juju.environs.
[LOG] 44.18512 DEBUG juju.environs.
[LOG] 44.18514 INFO juju.environs.tools reading tools with major.minor version 1.17
[LOG] 44.18515 INFO juju.environs.tools filtering tools by version: 1.17.4
[LOG] 44.18517 INFO juju.environs.tools filtering tools by series: precise
[LOG] 44.18519 DEBUG juju.environs.tools no architecture specified when finding tools, looking for any
[LOG] 44.18522 DEBUG juju.environs.
[LOG] 44.18524 DEBUG juju.environs.
[LOG] 44.18534 DEBUG juju.environs.
Go Bot (go-bot) wrote : | # |
The attempt to merge lp:~dstroppa/juju-core/joyent-provider-storage into lp:juju-core failed. Below is the output from the failed tests.
provider/
/usr/lib/
/home/
provider/
/usr/lib/
/home/
provider/
/usr/lib/
/home/
Unmerged revisions
- 1983. By Daniele Stroppa
-
Updated dependencies.tsv: tabs instead of spaces
- 1982. By Daniele Stroppa
-
Merged trunk
- 1981. By Daniele Stroppa
-
Updated GoJoyent dependency
Preview Diff
1 | === modified file '.bzrignore' | |||
2 | --- .bzrignore 2013-08-27 15:27:47 +0000 | |||
3 | +++ .bzrignore 2014-02-27 18:08:22 +0000 | |||
4 | @@ -8,3 +8,5 @@ | |||
5 | 8 | .emacs.desktop | 8 | .emacs.desktop |
6 | 9 | .emacs.desktop.lock | 9 | .emacs.desktop.lock |
7 | 10 | *.test | 10 | *.test |
8 | 11 | .idea | ||
9 | 12 | add-joyent-provider.iml | ||
10 | 11 | 13 | ||
11 | === modified file 'dependencies.tsv' | |||
12 | --- dependencies.tsv 2014-02-25 22:19:30 +0000 | |||
13 | +++ dependencies.tsv 2014-02-27 18:08:22 +0000 | |||
14 | @@ -6,6 +6,7 @@ | |||
15 | 6 | launchpad.net/gnuflag bzr roger.peppe@canonical.com-20121003093437-zcyyw0lpvj2nifpk 12 | 6 | launchpad.net/gnuflag bzr roger.peppe@canonical.com-20121003093437-zcyyw0lpvj2nifpk 12 |
16 | 7 | launchpad.net/goamz bzr roger.peppe@canonical.com-20131218155244-hbnkvlkkzy3vmlh9 44 | 7 | launchpad.net/goamz bzr roger.peppe@canonical.com-20131218155244-hbnkvlkkzy3vmlh9 44 |
17 | 8 | launchpad.net/gocheck bzr gustavo@niemeyer.net-20130302024745-6ikofwq2c03h7giu 85 | 8 | launchpad.net/gocheck bzr gustavo@niemeyer.net-20130302024745-6ikofwq2c03h7giu 85 |
18 | 9 | launchpad.net/gojoyent bzr daniele.stroppa@joyent.com-20140225172734-ltce6n3vrhj3cngg 61 | ||
19 | 9 | launchpad.net/golxc bzr ian.booth@canonical.com-20140116225718-lvoikrb0me6zugin 6 | 10 | launchpad.net/golxc bzr ian.booth@canonical.com-20140116225718-lvoikrb0me6zugin 6 |
20 | 10 | launchpad.net/gomaasapi bzr ian.booth@canonical.com-20131017011445-m1hmr0ap14osd7li 47 | 11 | launchpad.net/gomaasapi bzr ian.booth@canonical.com-20131017011445-m1hmr0ap14osd7li 47 |
21 | 11 | launchpad.net/goose bzr tarmac-20140124165235-h9rloooc531udms5 116 | 12 | launchpad.net/goose bzr tarmac-20140124165235-h9rloooc531udms5 116 |
22 | 12 | 13 | ||
23 | === modified file 'provider/joyent/config.go' | |||
24 | --- provider/joyent/config.go 2013-11-21 17:53:05 +0000 | |||
25 | +++ provider/joyent/config.go 2014-02-27 18:08:22 +0000 | |||
26 | @@ -22,16 +22,21 @@ | |||
27 | 22 | # sdc-user: <secret> | 22 | # sdc-user: <secret> |
28 | 23 | # Can be set via env variables, or specified here | 23 | # Can be set via env variables, or specified here |
29 | 24 | # sdc-key-id: <secret> | 24 | # sdc-key-id: <secret> |
32 | 25 | # region defaults to us-west-1, override if required | 25 | # url defaults to us-west-1 DC, override if required |
33 | 26 | # sdc-region: us-west-1 | 26 | # sdc-url: https://us-west-1.api.joyentcloud.com |
34 | 27 | 27 | ||
35 | 28 | # Manta config | 28 | # Manta config |
36 | 29 | # Can be set via env variables, or specified here | 29 | # Can be set via env variables, or specified here |
37 | 30 | # manta-user: <secret> | 30 | # manta-user: <secret> |
38 | 31 | # Can be set via env variables, or specified here | 31 | # Can be set via env variables, or specified here |
39 | 32 | # manta-key-id: <secret> | 32 | # manta-key-id: <secret> |
42 | 33 | # region defaults to us-east, override if required | 33 | # url defaults to us-east DC, override if required |
43 | 34 | # manta-region: us-east | 34 | # manta-url: https://us-east.manta.joyent.com |
44 | 35 | |||
45 | 36 | # Auth config | ||
46 | 37 | # key-file: <secret> | ||
47 | 38 | # algorithm defaults to rsa-sha256, override if required | ||
48 | 39 | # algorithm: rsa-sha256 | ||
49 | 35 | ` | 40 | ` |
50 | 36 | 41 | ||
51 | 37 | const ( | 42 | const ( |
52 | @@ -41,6 +46,7 @@ | |||
53 | 41 | MantaUser = "MANTA_USER" | 46 | MantaUser = "MANTA_USER" |
54 | 42 | MantaKeyId = "MANTA_KEY_ID" | 47 | MantaKeyId = "MANTA_KEY_ID" |
55 | 43 | MantaUrl = "MANTA_URL" | 48 | MantaUrl = "MANTA_URL" |
56 | 49 | Home = "HOME" | ||
57 | 44 | ) | 50 | ) |
58 | 45 | 51 | ||
59 | 46 | var environmentVariables = map[string]string{ | 52 | var environmentVariables = map[string]string{ |
60 | @@ -48,21 +54,25 @@ | |||
61 | 48 | "sdc-key-id": SdcKeyId, | 54 | "sdc-key-id": SdcKeyId, |
62 | 49 | "manta-user": MantaUser, | 55 | "manta-user": MantaUser, |
63 | 50 | "manta-key-id": MantaKeyId, | 56 | "manta-key-id": MantaKeyId, |
64 | 57 | "key-file": Home, | ||
65 | 51 | } | 58 | } |
66 | 52 | 59 | ||
67 | 53 | var configFields = schema.Fields{ | 60 | var configFields = schema.Fields{ |
68 | 54 | "sdc-user": schema.String(), | 61 | "sdc-user": schema.String(), |
69 | 55 | "sdc-key-id": schema.String(), | 62 | "sdc-key-id": schema.String(), |
71 | 56 | "sdc-region": schema.String(), | 63 | "sdc-url": schema.String(), |
72 | 57 | "manta-user": schema.String(), | 64 | "manta-user": schema.String(), |
73 | 58 | "manta-key-id": schema.String(), | 65 | "manta-key-id": schema.String(), |
75 | 59 | "manta-region": schema.String(), | 66 | "manta-url": schema.String(), |
76 | 67 | "key-file": schema.String(), | ||
77 | 68 | "algorithm": schema.String(), | ||
78 | 60 | "control-dir": schema.String(), | 69 | "control-dir": schema.String(), |
79 | 61 | } | 70 | } |
80 | 62 | 71 | ||
81 | 63 | var configDefaultFields = schema.Defaults{ | 72 | var configDefaultFields = schema.Defaults{ |
84 | 64 | "sdc-region": "us-west-1", | 73 | "sdc-url": "https://us-west-1.api.joyentcloud.com", |
85 | 65 | "manta-region": "us-east", | 74 | "manta-url": "https://us-east.manta.joyent.com", |
86 | 75 | "algorithm": "rsa-sha256", | ||
87 | 66 | } | 76 | } |
88 | 67 | 77 | ||
89 | 68 | var configSecretFields = []string{ | 78 | var configSecretFields = []string{ |
90 | @@ -70,11 +80,14 @@ | |||
91 | 70 | "sdc-key-id", | 80 | "sdc-key-id", |
92 | 71 | "manta-user", | 81 | "manta-user", |
93 | 72 | "manta-key-id", | 82 | "manta-key-id", |
94 | 83 | "key-file", | ||
95 | 73 | } | 84 | } |
96 | 74 | 85 | ||
97 | 75 | var configImmutableFields = []string{ | 86 | var configImmutableFields = []string{ |
100 | 76 | "sdc-region", | 87 | "sdc-url", |
101 | 77 | "manta-region", | 88 | "manta-url", |
102 | 89 | "key-file", | ||
103 | 90 | "algorithm", | ||
104 | 78 | } | 91 | } |
105 | 79 | 92 | ||
106 | 80 | func prepareConfig(cfg *config.Config) (*config.Config, error) { | 93 | func prepareConfig(cfg *config.Config) (*config.Config, error) { |
107 | @@ -86,7 +99,12 @@ | |||
108 | 86 | if err != nil { | 99 | if err != nil { |
109 | 87 | return nil, err | 100 | return nil, err |
110 | 88 | } | 101 | } |
112 | 89 | attrs["control-bucket"] = fmt.Sprintf("%x", uuid.Raw()) | 102 | attrs["control-dir"] = fmt.Sprintf("%x", uuid.Raw()) |
113 | 103 | } | ||
114 | 104 | |||
115 | 105 | if _, ok := attrs["key-file"]; !ok { | ||
116 | 106 | localEnvVariableHome := os.Getenv(environmentVariables["key-file"]) | ||
117 | 107 | attrs["key-file"] = fmt.Sprintf("%s/.ssh/id_rsa", localEnvVariableHome) | ||
118 | 90 | } | 108 | } |
119 | 91 | 109 | ||
120 | 92 | // Read env variables | 110 | // Read env variables |
121 | @@ -165,8 +183,8 @@ | |||
122 | 165 | attrs map[string]interface{} | 183 | attrs map[string]interface{} |
123 | 166 | } | 184 | } |
124 | 167 | 185 | ||
127 | 168 | func (ecfg *environConfig) sdcRegion() string { | 186 | func (ecfg *environConfig) sdcUrl() string { |
128 | 169 | return ecfg.attrs["sdc-region"].(string) | 187 | return ecfg.attrs["sdc-url"].(string) |
129 | 170 | } | 188 | } |
130 | 171 | 189 | ||
131 | 172 | func (ecfg *environConfig) sdcUser() string { | 190 | func (ecfg *environConfig) sdcUser() string { |
132 | @@ -177,8 +195,8 @@ | |||
133 | 177 | return ecfg.attrs["sdc-key-id"].(string) | 195 | return ecfg.attrs["sdc-key-id"].(string) |
134 | 178 | } | 196 | } |
135 | 179 | 197 | ||
138 | 180 | func (ecfg *environConfig) mantaRegion() string { | 198 | func (ecfg *environConfig) mantaUrl() string { |
139 | 181 | return ecfg.attrs["manta-region"].(string) | 199 | return ecfg.attrs["manta-url"].(string) |
140 | 182 | } | 200 | } |
141 | 183 | 201 | ||
142 | 184 | func (ecfg *environConfig) mantaUser() string { | 202 | func (ecfg *environConfig) mantaUser() string { |
143 | @@ -189,6 +207,14 @@ | |||
144 | 189 | return ecfg.attrs["manta-key-id"].(string) | 207 | return ecfg.attrs["manta-key-id"].(string) |
145 | 190 | } | 208 | } |
146 | 191 | 209 | ||
147 | 210 | func (ecfg *environConfig) keyFile() string { | ||
148 | 211 | return ecfg.attrs["key-file"].(string) | ||
149 | 212 | } | ||
150 | 213 | |||
151 | 214 | func (ecfg *environConfig) algorithm() string { | ||
152 | 215 | return ecfg.attrs["algorithm"].(string) | ||
153 | 216 | } | ||
154 | 217 | |||
155 | 192 | func (c *environConfig) controlDir() string { | 218 | func (c *environConfig) controlDir() string { |
156 | 193 | return c.attrs["control-dir"].(string) | 219 | return c.attrs["control-dir"].(string) |
157 | 194 | } | 220 | } |
158 | 195 | 221 | ||
159 | === modified file 'provider/joyent/config_test.go' | |||
160 | --- provider/joyent/config_test.go 2014-02-13 02:46:58 +0000 | |||
161 | +++ provider/joyent/config_test.go 2014-02-27 18:08:22 +0000 | |||
162 | @@ -8,7 +8,7 @@ | |||
163 | 8 | 8 | ||
164 | 9 | "launchpad.net/juju-core/environs" | 9 | "launchpad.net/juju-core/environs" |
165 | 10 | "launchpad.net/juju-core/environs/config" | 10 | "launchpad.net/juju-core/environs/config" |
167 | 11 | "launchpad.net/juju-core/provider/joyent" | 11 | jp "launchpad.net/juju-core/provider/joyent" |
168 | 12 | "launchpad.net/juju-core/testing" | 12 | "launchpad.net/juju-core/testing" |
169 | 13 | "launchpad.net/juju-core/testing/testbase" | 13 | "launchpad.net/juju-core/testing/testbase" |
170 | 14 | ) | 14 | ) |
171 | @@ -23,12 +23,14 @@ | |||
172 | 23 | func validAttrs() testing.Attrs { | 23 | func validAttrs() testing.Attrs { |
173 | 24 | return testing.FakeConfig().Merge(testing.Attrs{ | 24 | return testing.FakeConfig().Merge(testing.Attrs{ |
174 | 25 | "type": "joyent", | 25 | "type": "joyent", |
181 | 26 | "sdc-user": "dstroppa", | 26 | "sdc-user": "juju-test", |
182 | 27 | "sdc-key-id": "12:c3:a7:cb:a2:29:e2:90:88:3f:04:53:3b:4e:75:40", | 27 | "sdc-key-id": "00:11:22:33:44:55:66:77:88:99:aa:bb:cc:dd:ee:ff", |
183 | 28 | "sdc-region": "us-west-1", | 28 | "sdc-url": "https://test.api.joyentcloud.com", |
184 | 29 | "manta-user": "dstroppa", | 29 | "manta-user": "juju-test", |
185 | 30 | "manta-key-id": "12:c3:a7:cb:a2:29:e2:90:88:3f:04:53:3b:4e:75:40", | 30 | "manta-key-id": "00:11:22:33:44:55:66:77:88:99:aa:bb:cc:dd:ee:ff", |
186 | 31 | "manta-region": "us-east", | 31 | "manta-url": "https://test.manta.joyent.com", |
187 | 32 | "key-file": "~/.ssh/id_rsa", | ||
188 | 33 | "algorithm": "rsa-sha256", | ||
189 | 32 | "control-dir": "juju-test", | 34 | "control-dir": "juju-test", |
190 | 33 | }) | 35 | }) |
191 | 34 | } | 36 | } |
192 | @@ -41,10 +43,10 @@ | |||
193 | 41 | var _ = gc.Suite(&ConfigSuite{}) | 43 | var _ = gc.Suite(&ConfigSuite{}) |
194 | 42 | 44 | ||
195 | 43 | func (s *ConfigSuite) SetUpSuite(c *gc.C) { | 45 | func (s *ConfigSuite) SetUpSuite(c *gc.C) { |
200 | 44 | s.PatchEnvironment(joyent.SdcAccount, "tester") | 46 | s.PatchEnvironment(jp.SdcAccount, "tester") |
201 | 45 | s.PatchEnvironment(joyent.SdcKeyId, "11:c4:b6:c0:a3:24:22:96:a8:1f:07:53:3f:8e:14:7a") | 47 | s.PatchEnvironment(jp.SdcKeyId, "ff:ee:dd:cc:bb:aa:99:88:77:66:55:44:33:22:11:00") |
202 | 46 | s.PatchEnvironment(joyent.MantaUser, "tester") | 48 | s.PatchEnvironment(jp.MantaUser, "tester") |
203 | 47 | s.PatchEnvironment(joyent.MantaKeyId, "11:c4:b6:c0:a3:24:22:96:a8:1f:07:53:3f:8e:14:7a") | 49 | s.PatchEnvironment(jp.MantaKeyId, "ff:ee:dd:cc:bb:aa:99:88:77:66:55:44:33:22:11:00") |
204 | 48 | } | 50 | } |
205 | 49 | 51 | ||
206 | 50 | var newConfigTests = []struct { | 52 | var newConfigTests = []struct { |
207 | @@ -70,16 +72,16 @@ | |||
208 | 70 | insert: testing.Attrs{"sdc-key-id": ""}, | 72 | insert: testing.Attrs{"sdc-key-id": ""}, |
209 | 71 | err: "sdc-key-id: must not be empty", | 73 | err: "sdc-key-id: must not be empty", |
210 | 72 | }, { | 74 | }, { |
221 | 73 | info: "sdc-region is inserted if missing", | 75 | info: "sdc-url is inserted if missing", |
222 | 74 | expect: testing.Attrs{"sdc-region": "us-west-1"}, | 76 | expect: testing.Attrs{"sdc-url": "https://test.api.joyentcloud.com"}, |
223 | 75 | }, { | 77 | }, { |
224 | 76 | info: "sdc-region cannot be empty", | 78 | info: "sdc-url cannot be empty", |
225 | 77 | insert: testing.Attrs{"sdc-region": ""}, | 79 | insert: testing.Attrs{"sdc-url": ""}, |
226 | 78 | err: "sdc-region: must not be empty", | 80 | err: "sdc-url: must not be empty", |
227 | 79 | }, { | 81 | }, { |
228 | 80 | info: "sdc-region is untouched if present", | 82 | info: "sdc-url is untouched if present", |
229 | 81 | insert: testing.Attrs{"sdc-region": "us-west-1"}, | 83 | insert: testing.Attrs{"sdc-url": "https://test.api.joyentcloud.com"}, |
230 | 82 | expect: testing.Attrs{"sdc-region": "us-west-1"}, | 84 | expect: testing.Attrs{"sdc-url": "https://test.api.joyentcloud.com"}, |
231 | 83 | }, { | 85 | }, { |
232 | 84 | info: "manta-user is required", | 86 | info: "manta-user is required", |
233 | 85 | remove: []string{"manta-user"}, | 87 | remove: []string{"manta-user"}, |
234 | @@ -97,16 +99,30 @@ | |||
235 | 97 | insert: testing.Attrs{"manta-key-id": ""}, | 99 | insert: testing.Attrs{"manta-key-id": ""}, |
236 | 98 | err: "manta-key-id: must not be empty", | 100 | err: "manta-key-id: must not be empty", |
237 | 99 | }, { | 101 | }, { |
248 | 100 | info: "manta-region is inserted if missing", | 102 | info: "manta-url is inserted if missing", |
249 | 101 | expect: testing.Attrs{"manta-region": "us-east"}, | 103 | expect: testing.Attrs{"manta-url": "https://test.manta.joyent.com"}, |
250 | 102 | }, { | 104 | }, { |
251 | 103 | info: "manta-region cannot be empty", | 105 | info: "manta-url cannot be empty", |
252 | 104 | insert: testing.Attrs{"manta-region": ""}, | 106 | insert: testing.Attrs{"manta-url": ""}, |
253 | 105 | err: "manta-region: must not be empty", | 107 | err: "manta-url: must not be empty", |
254 | 106 | }, { | 108 | }, { |
255 | 107 | info: "manta-region is untouched if present", | 109 | info: "manta-url is untouched if present", |
256 | 108 | insert: testing.Attrs{"manta-region": "us-east"}, | 110 | insert: testing.Attrs{"manta-url": "https://test.manta.joyent.com"}, |
257 | 109 | expect: testing.Attrs{"manta-region": "us-east"}, | 111 | expect: testing.Attrs{"manta-url": "https://test.manta.joyent.com"}, |
258 | 112 | }, { | ||
259 | 113 | info: "key-file is inserted if missing", | ||
260 | 114 | expect: testing.Attrs{"key-file": "~/.ssh/id_rsa"}, | ||
261 | 115 | }, { | ||
262 | 116 | info: "key-file cannot be empty", | ||
263 | 117 | insert: testing.Attrs{"key-file": ""}, | ||
264 | 118 | err: "key-file: must not be empty", | ||
265 | 119 | }, { | ||
266 | 120 | info: "algorithm is inserted if missing", | ||
267 | 121 | expect: testing.Attrs{"algorithm": "rsa-sha256"}, | ||
268 | 122 | }, { | ||
269 | 123 | info: "algorithm cannot be empty", | ||
270 | 124 | insert: testing.Attrs{"algorithm": ""}, | ||
271 | 125 | err: "algorithm: must not be empty", | ||
272 | 110 | }, { | 126 | }, { |
273 | 111 | info: "unknown field is not touched", | 127 | info: "unknown field is not touched", |
274 | 112 | insert: testing.Attrs{"unknown-field": 12345}, | 128 | insert: testing.Attrs{"unknown-field": 12345}, |
275 | @@ -137,7 +153,7 @@ | |||
276 | 137 | c.Logf("test %d: %s", i, test.info) | 153 | c.Logf("test %d: %s", i, test.info) |
277 | 138 | attrs := validAttrs().Merge(test.insert).Delete(test.remove...) | 154 | attrs := validAttrs().Merge(test.insert).Delete(test.remove...) |
278 | 139 | testConfig := newConfig(c, attrs) | 155 | testConfig := newConfig(c, attrs) |
280 | 140 | validatedConfig, err := joyent.Provider.Validate(testConfig, nil) | 156 | validatedConfig, err := Provider.Validate(testConfig, nil) |
281 | 141 | if test.err == "" { | 157 | if test.err == "" { |
282 | 142 | c.Assert(err, gc.IsNil) | 158 | c.Assert(err, gc.IsNil) |
283 | 143 | attrs := validatedConfig.AllAttrs() | 159 | attrs := validatedConfig.AllAttrs() |
284 | @@ -157,7 +173,7 @@ | |||
285 | 157 | c.Logf("test %d: %s", i, test.info) | 173 | c.Logf("test %d: %s", i, test.info) |
286 | 158 | attrs := validAttrs().Merge(test.insert).Delete(test.remove...) | 174 | attrs := validAttrs().Merge(test.insert).Delete(test.remove...) |
287 | 159 | testConfig := newConfig(c, attrs) | 175 | testConfig := newConfig(c, attrs) |
289 | 160 | validatedConfig, err := joyent.Provider.Validate(knownGoodConfig, testConfig) | 176 | validatedConfig, err := Provider.Validate(knownGoodConfig, testConfig) |
290 | 161 | if test.err == "" { | 177 | if test.err == "" { |
291 | 162 | c.Assert(err, gc.IsNil) | 178 | c.Assert(err, gc.IsNil) |
292 | 163 | attrs := validatedConfig.AllAttrs() | 179 | attrs := validatedConfig.AllAttrs() |
293 | @@ -186,24 +202,24 @@ | |||
294 | 186 | expect: testing.Attrs{"sdc-user": "joyent_user"}, | 202 | expect: testing.Attrs{"sdc-user": "joyent_user"}, |
295 | 187 | }, { | 203 | }, { |
296 | 188 | info: "can change sdc-key-id", | 204 | info: "can change sdc-key-id", |
299 | 189 | insert: testing.Attrs{"sdc-key-id": "11:c4:b6:c0:a3:24:22:96:a8:1f:07:53:3f:8e:14:7a"}, | 205 | insert: testing.Attrs{"sdc-key-id": "ff:ee:dd:cc:bb:aa:99:88:77:66:55:44:33:22:11:00"}, |
300 | 190 | expect: testing.Attrs{"sdc-key-id": "11:c4:b6:c0:a3:24:22:96:a8:1f:07:53:3f:8e:14:7a"}, | 206 | expect: testing.Attrs{"sdc-key-id": "ff:ee:dd:cc:bb:aa:99:88:77:66:55:44:33:22:11:00"}, |
301 | 191 | }, { | 207 | }, { |
305 | 192 | info: "can change sdc-region", | 208 | info: "can change sdc-url", |
306 | 193 | insert: testing.Attrs{"sdc-region": "us-west-1"}, | 209 | insert: testing.Attrs{"sdc-url": "https://test.api.joyentcloud.com"}, |
307 | 194 | expect: testing.Attrs{"sdc-region": "us-west-1"}, | 210 | expect: testing.Attrs{"sdc-url": "https://test.api.joyentcloud.com"}, |
308 | 195 | }, { | 211 | }, { |
309 | 196 | info: "can change manta-user", | 212 | info: "can change manta-user", |
310 | 197 | insert: testing.Attrs{"manta-user": "manta_user"}, | 213 | insert: testing.Attrs{"manta-user": "manta_user"}, |
311 | 198 | expect: testing.Attrs{"manta-user": "manta_user"}, | 214 | expect: testing.Attrs{"manta-user": "manta_user"}, |
312 | 199 | }, { | 215 | }, { |
313 | 200 | info: "can change manta-key-id", | 216 | info: "can change manta-key-id", |
316 | 201 | insert: testing.Attrs{"manta-key-id": "11:c4:b6:c0:a3:24:22:96:a8:1f:07:53:3f:8e:14:7a"}, | 217 | insert: testing.Attrs{"manta-key-id": "ff:ee:dd:cc:bb:aa:99:88:77:66:55:44:33:22:11:00"}, |
317 | 202 | expect: testing.Attrs{"manta-key-id": "11:c4:b6:c0:a3:24:22:96:a8:1f:07:53:3f:8e:14:7a"}, | 218 | expect: testing.Attrs{"manta-key-id": "ff:ee:dd:cc:bb:aa:99:88:77:66:55:44:33:22:11:00"}, |
318 | 203 | }, { | 219 | }, { |
322 | 204 | info: "can change manta-region", | 220 | info: "can change manta-url", |
323 | 205 | insert: testing.Attrs{"manta-region": "us-east"}, | 221 | insert: testing.Attrs{"manta-url": "https://test.manta.joyent.com"}, |
324 | 206 | expect: testing.Attrs{"manta-region": "us-east"}, | 222 | expect: testing.Attrs{"manta-url": "https://test.manta.joyent.com"}, |
325 | 207 | }, { | 223 | }, { |
326 | 208 | info: "can insert unknown field", | 224 | info: "can insert unknown field", |
327 | 209 | insert: testing.Attrs{"unknown": "ignoti"}, | 225 | insert: testing.Attrs{"unknown": "ignoti"}, |
328 | @@ -216,7 +232,7 @@ | |||
329 | 216 | c.Logf("test %d: %s", i, test.info) | 232 | c.Logf("test %d: %s", i, test.info) |
330 | 217 | attrs := validAttrs().Merge(test.insert).Delete(test.remove...) | 233 | attrs := validAttrs().Merge(test.insert).Delete(test.remove...) |
331 | 218 | testConfig := newConfig(c, attrs) | 234 | testConfig := newConfig(c, attrs) |
333 | 219 | validatedConfig, err := joyent.Provider.Validate(testConfig, baseConfig) | 235 | validatedConfig, err := Provider.Validate(testConfig, baseConfig) |
334 | 220 | if test.err == "" { | 236 | if test.err == "" { |
335 | 221 | c.Assert(err, gc.IsNil) | 237 | c.Assert(err, gc.IsNil) |
336 | 222 | attrs := validatedConfig.AllAttrs() | 238 | attrs := validatedConfig.AllAttrs() |
337 | @@ -270,7 +286,7 @@ | |||
338 | 270 | }, { | 286 | }, { |
339 | 271 | info: "can get sdc-key-id from env variable", | 287 | info: "can get sdc-key-id from env variable", |
340 | 272 | insert: testing.Attrs{"sdc-key-id": ""}, | 288 | insert: testing.Attrs{"sdc-key-id": ""}, |
342 | 273 | expect: testing.Attrs{"sdc-key-id": "11:c4:b6:c0:a3:24:22:96:a8:1f:07:53:3f:8e:14:7a"}, | 289 | expect: testing.Attrs{"sdc-key-id": "ff:ee:dd:cc:bb:aa:99:88:77:66:55:44:33:22:11:00"}, |
343 | 274 | }, { | 290 | }, { |
344 | 275 | info: "can get manta-user from env variable", | 291 | info: "can get manta-user from env variable", |
345 | 276 | insert: testing.Attrs{"manta-user": ""}, | 292 | insert: testing.Attrs{"manta-user": ""}, |
346 | @@ -278,7 +294,7 @@ | |||
347 | 278 | }, { | 294 | }, { |
348 | 279 | info: "can get manta-key-id from env variable", | 295 | info: "can get manta-key-id from env variable", |
349 | 280 | insert: testing.Attrs{"manta-key-id": ""}, | 296 | insert: testing.Attrs{"manta-key-id": ""}, |
351 | 281 | expect: testing.Attrs{"manta-key-id": "11:c4:b6:c0:a3:24:22:96:a8:1f:07:53:3f:8e:14:7a"}, | 297 | expect: testing.Attrs{"manta-key-id": "ff:ee:dd:cc:bb:aa:99:88:77:66:55:44:33:22:11:00"}, |
352 | 282 | }} | 298 | }} |
353 | 283 | 299 | ||
354 | 284 | func (s *ConfigSuite) TestPrepare(c *gc.C) { | 300 | func (s *ConfigSuite) TestPrepare(c *gc.C) { |
355 | @@ -286,7 +302,7 @@ | |||
356 | 286 | c.Logf("test %d: %s", i, test.info) | 302 | c.Logf("test %d: %s", i, test.info) |
357 | 287 | attrs := validAttrs().Merge(test.insert).Delete(test.remove...) | 303 | attrs := validAttrs().Merge(test.insert).Delete(test.remove...) |
358 | 288 | testConfig := newConfig(c, attrs) | 304 | testConfig := newConfig(c, attrs) |
360 | 289 | preparedConfig, err := joyent.Provider.Prepare(testing.Context(c), testConfig) | 305 | preparedConfig, err := Provider.Prepare(testing.Context(c), testConfig) |
361 | 290 | if test.err == "" { | 306 | if test.err == "" { |
362 | 291 | c.Assert(err, gc.IsNil) | 307 | c.Assert(err, gc.IsNil) |
363 | 292 | attrs := preparedConfig.Config().AllAttrs() | 308 | attrs := preparedConfig.Config().AllAttrs() |
364 | 293 | 309 | ||
365 | === modified file 'provider/joyent/environ.go' | |||
366 | --- provider/joyent/environ.go 2013-12-19 08:40:11 +0000 | |||
367 | +++ provider/joyent/environ.go 2014-02-27 18:08:22 +0000 | |||
368 | @@ -23,7 +23,7 @@ | |||
369 | 23 | // must be implemented ) and environ_firewall.go (which can be safely | 23 | // must be implemented ) and environ_firewall.go (which can be safely |
370 | 24 | // ignored until you've got an environment bootstrapping successfully). | 24 | // ignored until you've got an environment bootstrapping successfully). |
371 | 25 | 25 | ||
373 | 26 | type environ struct { | 26 | type JoyentEnviron struct { |
374 | 27 | name string | 27 | name string |
375 | 28 | // All mutating operations should lock the mutex. Non-mutating operations | 28 | // All mutating operations should lock the mutex. Non-mutating operations |
376 | 29 | // should read all fields (other than name, which is immutable) from a | 29 | // should read all fields (other than name, which is immutable) from a |
377 | @@ -35,17 +35,32 @@ | |||
378 | 35 | storage storage.Storage | 35 | storage storage.Storage |
379 | 36 | } | 36 | } |
380 | 37 | 37 | ||
384 | 38 | var _ environs.Environ = (*environ)(nil) | 38 | var _ environs.Environ = (*JoyentEnviron)(nil) |
385 | 39 | 39 | ||
386 | 40 | func (env *environ) Name() string { | 40 | func NewEnviron(cfg *config.Config) (*JoyentEnviron, error) { |
387 | 41 | env := new(JoyentEnviron) | ||
388 | 42 | err := env.SetConfig(cfg) | ||
389 | 43 | if err != nil { | ||
390 | 44 | return nil, err | ||
391 | 45 | } | ||
392 | 46 | env.name = cfg.Name() | ||
393 | 47 | env.storage = NewStorage(env) | ||
394 | 48 | return env, nil | ||
395 | 49 | } | ||
396 | 50 | |||
397 | 51 | func (env *JoyentEnviron) SetName(envName string) { | ||
398 | 52 | env.name = envName | ||
399 | 53 | } | ||
400 | 54 | |||
401 | 55 | func (env *JoyentEnviron) Name() string { | ||
402 | 41 | return env.name | 56 | return env.name |
403 | 42 | } | 57 | } |
404 | 43 | 58 | ||
406 | 44 | func (*environ) Provider() environs.EnvironProvider { | 59 | func (*JoyentEnviron) Provider() environs.EnvironProvider { |
407 | 45 | return providerInstance | 60 | return providerInstance |
408 | 46 | } | 61 | } |
409 | 47 | 62 | ||
411 | 48 | func (env *environ) SetConfig(cfg *config.Config) error { | 63 | func (env *JoyentEnviron) SetConfig(cfg *config.Config) error { |
412 | 49 | env.lock.Lock() | 64 | env.lock.Lock() |
413 | 50 | defer env.lock.Unlock() | 65 | defer env.lock.Unlock() |
414 | 51 | ecfg, err := validateConfig(cfg, env.ecfg) | 66 | ecfg, err := validateConfig(cfg, env.ecfg) |
415 | @@ -61,7 +76,7 @@ | |||
416 | 61 | return nil | 76 | return nil |
417 | 62 | } | 77 | } |
418 | 63 | 78 | ||
420 | 64 | func (env *environ) getSnapshot() *environ { | 79 | func (env *JoyentEnviron) getSnapshot() *JoyentEnviron { |
421 | 65 | env.lock.Lock() | 80 | env.lock.Lock() |
422 | 66 | clone := *env | 81 | clone := *env |
423 | 67 | env.lock.Unlock() | 82 | env.lock.Unlock() |
424 | @@ -69,26 +84,26 @@ | |||
425 | 69 | return &clone | 84 | return &clone |
426 | 70 | } | 85 | } |
427 | 71 | 86 | ||
429 | 72 | func (env *environ) Config() *config.Config { | 87 | func (env *JoyentEnviron) Config() *config.Config { |
430 | 73 | return env.getSnapshot().ecfg.Config | 88 | return env.getSnapshot().ecfg.Config |
431 | 74 | } | 89 | } |
432 | 75 | 90 | ||
434 | 76 | func (env *environ) Storage() storage.Storage { | 91 | func (env *JoyentEnviron) Storage() storage.Storage { |
435 | 77 | return env.getSnapshot().storage | 92 | return env.getSnapshot().storage |
436 | 78 | } | 93 | } |
437 | 79 | 94 | ||
439 | 80 | func (env *environ) PublicStorage() storage.StorageReader { | 95 | func (env *JoyentEnviron) PublicStorage() storage.StorageReader { |
440 | 81 | return environs.EmptyStorage | 96 | return environs.EmptyStorage |
441 | 82 | } | 97 | } |
442 | 83 | 98 | ||
444 | 84 | func (env *environ) Bootstrap(ctx environs.BootstrapContext, cons constraints.Value) error { | 99 | func (env *JoyentEnviron) Bootstrap(ctx environs.BootstrapContext, cons constraints.Value) error { |
445 | 85 | return common.Bootstrap(ctx, env, cons) | 100 | return common.Bootstrap(ctx, env, cons) |
446 | 86 | } | 101 | } |
447 | 87 | 102 | ||
449 | 88 | func (env *environ) StateInfo() (*state.Info, *api.Info, error) { | 103 | func (env *JoyentEnviron) StateInfo() (*state.Info, *api.Info, error) { |
450 | 89 | return common.StateInfo(env) | 104 | return common.StateInfo(env) |
451 | 90 | } | 105 | } |
452 | 91 | 106 | ||
454 | 92 | func (env *environ) Destroy() error { | 107 | func (env *JoyentEnviron) Destroy() error { |
455 | 93 | return common.Destroy(env) | 108 | return common.Destroy(env) |
456 | 94 | } | 109 | } |
457 | 95 | 110 | ||
458 | === modified file 'provider/joyent/environ_firewall.go' | |||
459 | --- provider/joyent/environ_firewall.go 2013-10-07 10:57:04 +0000 | |||
460 | +++ provider/joyent/environ_firewall.go 2014-02-27 18:08:22 +0000 | |||
461 | @@ -11,19 +11,19 @@ | |||
462 | 11 | // cause `juju expose` to work when the firewall-mode is "global". If you | 11 | // cause `juju expose` to work when the firewall-mode is "global". If you |
463 | 12 | // implement one of them, you should implement them all. | 12 | // implement one of them, you should implement them all. |
464 | 13 | 13 | ||
466 | 14 | func (env *environ) OpenPorts(ports []instance.Port) error { | 14 | func (env *JoyentEnviron) OpenPorts(ports []instance.Port) error { |
467 | 15 | logger.Warningf("pretending to open ports %v for all instances", ports) | 15 | logger.Warningf("pretending to open ports %v for all instances", ports) |
468 | 16 | _ = env.getSnapshot() | 16 | _ = env.getSnapshot() |
469 | 17 | return nil | 17 | return nil |
470 | 18 | } | 18 | } |
471 | 19 | 19 | ||
473 | 20 | func (env *environ) ClosePorts(ports []instance.Port) error { | 20 | func (env *JoyentEnviron) ClosePorts(ports []instance.Port) error { |
474 | 21 | logger.Warningf("pretending to close ports %v for all instances", ports) | 21 | logger.Warningf("pretending to close ports %v for all instances", ports) |
475 | 22 | _ = env.getSnapshot() | 22 | _ = env.getSnapshot() |
476 | 23 | return nil | 23 | return nil |
477 | 24 | } | 24 | } |
478 | 25 | 25 | ||
480 | 26 | func (env *environ) Ports() ([]instance.Port, error) { | 26 | func (env *JoyentEnviron) Ports() ([]instance.Port, error) { |
481 | 27 | _ = env.getSnapshot() | 27 | _ = env.getSnapshot() |
482 | 28 | return nil, nil | 28 | return nil, nil |
483 | 29 | } | 29 | } |
484 | 30 | 30 | ||
485 | === modified file 'provider/joyent/environ_instance.go' | |||
486 | --- provider/joyent/environ_instance.go 2013-10-07 10:57:04 +0000 | |||
487 | +++ provider/joyent/environ_instance.go 2014-02-27 18:08:22 +0000 | |||
488 | @@ -10,7 +10,7 @@ | |||
489 | 10 | "launchpad.net/juju-core/tools" | 10 | "launchpad.net/juju-core/tools" |
490 | 11 | ) | 11 | ) |
491 | 12 | 12 | ||
493 | 13 | func (env *environ) StartInstance( | 13 | func (env *JoyentEnviron) StartInstance( |
494 | 14 | cons constraints.Value, possibleTools tools.List, machineConf *cloudinit.MachineConfig, | 14 | cons constraints.Value, possibleTools tools.List, machineConf *cloudinit.MachineConfig, |
495 | 15 | ) ( | 15 | ) ( |
496 | 16 | instance.Instance, *instance.HardwareCharacteristics, error, | 16 | instance.Instance, *instance.HardwareCharacteristics, error, |
497 | @@ -22,7 +22,7 @@ | |||
498 | 22 | return nil, nil, errNotImplemented | 22 | return nil, nil, errNotImplemented |
499 | 23 | } | 23 | } |
500 | 24 | 24 | ||
502 | 25 | func (env *environ) AllInstances() ([]instance.Instance, error) { | 25 | func (env *JoyentEnviron) AllInstances() ([]instance.Instance, error) { |
503 | 26 | // Please note that this must *not* return instances that have not been | 26 | // Please note that this must *not* return instances that have not been |
504 | 27 | // allocated as part of this environment -- if it does, juju will see they | 27 | // allocated as part of this environment -- if it does, juju will see they |
505 | 28 | // are not tracked in state, assume they're stale/rogue, and shut them down. | 28 | // are not tracked in state, assume they're stale/rogue, and shut them down. |
506 | @@ -30,7 +30,7 @@ | |||
507 | 30 | return nil, errNotImplemented | 30 | return nil, errNotImplemented |
508 | 31 | } | 31 | } |
509 | 32 | 32 | ||
511 | 33 | func (env *environ) Instances(ids []instance.Id) ([]instance.Instance, error) { | 33 | func (env *JoyentEnviron) Instances(ids []instance.Id) ([]instance.Instance, error) { |
512 | 34 | // Please note that this must *not* return instances that have not been | 34 | // Please note that this must *not* return instances that have not been |
513 | 35 | // allocated as part of this environment -- if it does, juju will see they | 35 | // allocated as part of this environment -- if it does, juju will see they |
514 | 36 | // are not tracked in state, assume they're stale/rogue, and shut them down. | 36 | // are not tracked in state, assume they're stale/rogue, and shut them down. |
515 | @@ -41,7 +41,7 @@ | |||
516 | 41 | return nil, errNotImplemented | 41 | return nil, errNotImplemented |
517 | 42 | } | 42 | } |
518 | 43 | 43 | ||
520 | 44 | func (env *environ) StopInstances(instances []instance.Instance) error { | 44 | func (env *JoyentEnviron) StopInstances(instances []instance.Instance) error { |
521 | 45 | _ = env.getSnapshot() | 45 | _ = env.getSnapshot() |
522 | 46 | return errNotImplemented | 46 | return errNotImplemented |
523 | 47 | } | 47 | } |
524 | 48 | 48 | ||
525 | === modified file 'provider/joyent/export_test.go' | |||
526 | --- provider/joyent/export_test.go 2013-10-07 10:57:04 +0000 | |||
527 | +++ provider/joyent/export_test.go 2014-02-27 18:08:22 +0000 | |||
528 | @@ -1,10 +1,11 @@ | |||
529 | 1 | // Copyright 2013 Joyent Inc. | 1 | // Copyright 2013 Joyent Inc. |
530 | 2 | // Licensed under the AGPLv3, see LICENCE file for details. | 2 | // Licensed under the AGPLv3, see LICENCE file for details. |
531 | 3 | 3 | ||
533 | 4 | package joyent | 4 | package joyent_test |
534 | 5 | 5 | ||
535 | 6 | import ( | 6 | import ( |
536 | 7 | "launchpad.net/juju-core/environs" | 7 | "launchpad.net/juju-core/environs" |
537 | 8 | jp "launchpad.net/juju-core/provider/joyent" | ||
538 | 8 | ) | 9 | ) |
539 | 9 | 10 | ||
541 | 10 | var Provider environs.EnvironProvider = providerInstance | 11 | var Provider environs.EnvironProvider = jp.GetProviderInstance() |
542 | 11 | 12 | ||
543 | === modified file 'provider/joyent/instance.go' | |||
544 | --- provider/joyent/instance.go 2013-12-16 09:53:26 +0000 | |||
545 | +++ provider/joyent/instance.go 2014-02-27 18:08:22 +0000 | |||
546 | @@ -10,7 +10,7 @@ | |||
547 | 10 | 10 | ||
548 | 11 | type environInstance struct { | 11 | type environInstance struct { |
549 | 12 | id instance.Id | 12 | id instance.Id |
551 | 13 | env *environ | 13 | env *JoyentEnviron |
552 | 14 | } | 14 | } |
553 | 15 | 15 | ||
554 | 16 | var _ instance.Instance = (*environInstance)(nil) | 16 | var _ instance.Instance = (*environInstance)(nil) |
555 | 17 | 17 | ||
556 | === modified file 'provider/joyent/joyent_test.go' | |||
557 | --- provider/joyent/joyent_test.go 2013-10-10 09:24:18 +0000 | |||
558 | +++ provider/joyent/joyent_test.go 2014-02-27 18:08:22 +0000 | |||
559 | @@ -4,24 +4,177 @@ | |||
560 | 4 | package joyent_test | 4 | package joyent_test |
561 | 5 | 5 | ||
562 | 6 | import ( | 6 | import ( |
564 | 7 | "testing" | 7 | "fmt" |
565 | 8 | "io/ioutil" | ||
566 | 9 | "net/http" | ||
567 | 10 | "net/http/httptest" | ||
568 | 11 | "os" | ||
569 | 12 | stdtesting "testing" | ||
570 | 8 | 13 | ||
571 | 9 | gc "launchpad.net/gocheck" | 14 | gc "launchpad.net/gocheck" |
572 | 10 | 15 | ||
578 | 11 | "launchpad.net/juju-core/environs" | 16 | "launchpad.net/juju-core/environs/config" |
579 | 12 | "launchpad.net/juju-core/provider/joyent" | 17 | envtesting "launchpad.net/juju-core/environs/testing" |
580 | 13 | ) | 18 | jp "launchpad.net/juju-core/provider/joyent" |
581 | 14 | 19 | coretesting "launchpad.net/juju-core/testing" | |
582 | 15 | func TestPackage(t *testing.T) { | 20 | "launchpad.net/juju-core/testing/testbase" |
583 | 21 | |||
584 | 22 | "launchpad.net/gojoyent/jpc" | ||
585 | 23 | localmanta "launchpad.net/gojoyent/localservices/manta" | ||
586 | 24 | ) | ||
587 | 25 | |||
588 | 26 | const ( | ||
589 | 27 | testUser = "test" | ||
590 | 28 | testKeyFileName = "provider_id_rsa" | ||
591 | 29 | testPrivateKey = `-----BEGIN RSA PRIVATE KEY----- | ||
592 | 30 | MIIEpAIBAAKCAQEAza+KvczCrcpQGRq9e347VHx9oEvuhseJt0ydR+UMAveyQprU | ||
593 | 31 | 4JHvzwUUhGnG147GJQYyfQ4nzaSG62az/YThoZJzw8gtxGkVHv0wlAlRkYhxbKbq | ||
594 | 32 | 8WQIh73xDQkHLw2lXLvf7Tt0Mhow0qGEmkOjTb5fPsj2evphrV3jJ15QlhL4cv33 | ||
595 | 33 | t8jVadIrL0iIpwdqWiPqUKpsrSfKJghkoXS6quPy78P820TnuoBG+/Ppr8Kkvn6m | ||
596 | 34 | A7j4xnOQ12QE6jPK4zkikj5ZczSC4fTG0d3BwwX4VYu+4y/T/BX0L9VNUmQU22Y+ | ||
597 | 35 | /MRXAUZxsa8VhNB+xXF5XSubyb2n6loMWWaYGwIDAQABAoIBAQDCJt9JxYxGS+BL | ||
598 | 36 | sigF9+O9Hj3fH42p/5QJR/J2uMgbzP+hS1GCIX9B5MO3MbmWI5j5vd3OmZwMyy7n | ||
599 | 37 | 6Wwg9FufDgTkW4KIEcD0HX7LXfh27VpTe0PuU8SRjUOKUGlNiw36eQUog6Rs3rgT | ||
600 | 38 | Oo9Wpl3xtq9lLoErGEk3QpZ2xNpArTfsN9N3pdmD4sv7wmJq0PZQyej482g9R0g/ | ||
601 | 39 | 5k2ni6JpcEifzBQ6Bzx3EV2l9UipEIqbqDpMOtYFCpnLQhEaDfUribqXINGIsjiq | ||
602 | 40 | VyFa3Mbg/eayqG3UX3rVTCif2NnW2ojl4mMgWCyxgWfb4Jg1trc3v7X4SXfbgPWD | ||
603 | 41 | WcfrOhOhAoGBAP7ZC8KHAnjujwvXf3PxVNm6CTs5evbByQVyxNciGxRuOomJIR4D | ||
604 | 42 | euqepQ4PuNAabnrbMyQWXpibIKpmLnBVoj1q0IMXYvi2MZF5e2tH/Gx01UvxamHh | ||
605 | 43 | bKhHmp9ImHhVl6kObXOdNvLVTt/BI5FZBblvm7qOoiVwImPbqqVHP7Q5AoGBAM6d | ||
606 | 44 | mNsrW0iV/nP1m7d8mcFw74PI0FNlNdfUoePUgokO0t5OU0Ri/lPBDCRGlvVF3pj1 | ||
607 | 45 | HnmwroNtdWr9oPVB6km8193fb2zIWe53tj+6yRFQpz5elrSPfeZaZXlJZAGCCCdN | ||
608 | 46 | gBggWQFPeQiT54aPywPpcTZHIs72XBqQ6QsIPrbzAoGAdW2hg5MeSobyFuzHZ69N | ||
609 | 47 | /70/P7DuvgDxFbeah97JR5K7GmC7h87mtnE/cMlByXJEcgvK9tfv4rWoSZwnzc9H | ||
610 | 48 | oLE1PxJpolyhXnzxp69V2svC9OlasZtjq+7Cip6y0s/twBJL0Lgid6ZeX6/pKbIx | ||
611 | 49 | dw68XSwX/tQ6pHS1ns7DxdECgYBJbBWapNCefbbbjEcWsC+PX0uuABmP2SKGHSie | ||
612 | 50 | ZrEwdVUX7KuIXMlWB/8BkRgp9vdAUbLPuap6R9Z2+8RMA213YKUxUiotdREIPgBE | ||
613 | 51 | q2KyRX/5GPHjHi62Qh9XN25TXtr45ICFklEutwgitTSMS+Lv8+/oQuUquL9ILYCz | ||
614 | 52 | C+4FYwKBgQDE9yZTUpJjG2424z6bl/MHzwl5RB4pMronp0BbeVqPwhCBfj0W5I42 | ||
615 | 53 | 1ZL4+8eniHfUs4GXzf5tb9YwVt3EltIF2JybaBvFsv2o356yJUQmqQ+jyYRoEpT5 | ||
616 | 54 | 2SwilFo/XCotCXxi5n8sm9V94a0oix4ehZrohTA/FZLsggwFCPmXfw== | ||
617 | 55 | -----END RSA PRIVATE KEY-----` | ||
618 | 56 | testKeyFingerprint = "66:ca:1c:09:75:99:35:69:be:91:08:25:03:c0:17:c0" | ||
619 | 57 | ) | ||
620 | 58 | |||
621 | 59 | func TestJoyentProvider(t *stdtesting.T) { | ||
622 | 16 | gc.TestingT(t) | 60 | gc.TestingT(t) |
623 | 17 | } | 61 | } |
624 | 18 | 62 | ||
633 | 19 | type JoyentSuite struct{} | 63 | type localMantaService struct { |
634 | 20 | 64 | creds *jpc.Credentials | |
635 | 21 | var _ = gc.Suite(&JoyentSuite{}) | 65 | Server *httptest.Server |
636 | 22 | 66 | Mux *http.ServeMux | |
637 | 23 | func (*JoyentSuite) TestRegistered(c *gc.C) { | 67 | oldHandler http.Handler |
638 | 24 | provider, err := environs.Provider("joyent") | 68 | manta *localmanta.Manta |
639 | 25 | c.Assert(err, gc.IsNil) | 69 | } |
640 | 26 | c.Assert(provider, gc.Equals, joyent.Provider) | 70 | |
641 | 71 | func (s *localMantaService) Start(c *gc.C) { | ||
642 | 72 | // Set up the HTTP server. | ||
643 | 73 | s.Server = httptest.NewServer(nil) | ||
644 | 74 | c.Assert(s.Server, gc.NotNil) | ||
645 | 75 | s.oldHandler = s.Server.Config.Handler | ||
646 | 76 | s.Mux = http.NewServeMux() | ||
647 | 77 | s.Server.Config.Handler = s.Mux | ||
648 | 78 | |||
649 | 79 | // Set up a Joyent Manta service. | ||
650 | 80 | auth := jpc.Auth{User: testUser, KeyFile: testKeyFileName, Algorithm: "rsa-sha256"} | ||
651 | 81 | |||
652 | 82 | s.creds = &jpc.Credentials{ | ||
653 | 83 | UserAuthentication: auth, | ||
654 | 84 | MantaKeyId: testKeyFingerprint, | ||
655 | 85 | MantaEndpoint: jpc.Endpoint{URL: s.Server.URL}, | ||
656 | 86 | } | ||
657 | 87 | s.manta = localmanta.New(s.creds.MantaEndpoint.URL, s.creds.UserAuthentication.User) | ||
658 | 88 | s.manta.SetupHTTP(s.Mux) | ||
659 | 89 | c.Logf("Started local Manta service at: %v", s.Server.URL) | ||
660 | 90 | } | ||
661 | 91 | |||
662 | 92 | func (s *localMantaService) Stop() { | ||
663 | 93 | s.Mux = nil | ||
664 | 94 | s.Server.Config.Handler = s.oldHandler | ||
665 | 95 | s.Server.Close() | ||
666 | 96 | } | ||
667 | 97 | |||
668 | 98 | type providerSuite struct { | ||
669 | 99 | testbase.LoggingSuite | ||
670 | 100 | envtesting.ToolsFixture | ||
671 | 101 | restoreTimeouts func() | ||
672 | 102 | } | ||
673 | 103 | |||
674 | 104 | var _ = gc.Suite(&providerSuite{}) | ||
675 | 105 | |||
676 | 106 | func (s *providerSuite) SetUpSuite(c *gc.C) { | ||
677 | 107 | s.restoreTimeouts = envtesting.PatchAttemptStrategies() | ||
678 | 108 | s.LoggingSuite.SetUpSuite(c) | ||
679 | 109 | createTestKey() | ||
680 | 110 | } | ||
681 | 111 | |||
682 | 112 | func (s *providerSuite) TearDownSuite(c *gc.C) { | ||
683 | 113 | removeTestKey() | ||
684 | 114 | s.restoreTimeouts() | ||
685 | 115 | s.LoggingSuite.TearDownSuite(c) | ||
686 | 116 | } | ||
687 | 117 | |||
688 | 118 | func (s *providerSuite) SetUpTest(c *gc.C) { | ||
689 | 119 | s.LoggingSuite.SetUpTest(c) | ||
690 | 120 | s.ToolsFixture.SetUpTest(c) | ||
691 | 121 | } | ||
692 | 122 | |||
693 | 123 | func (s *providerSuite) TearDownTest(c *gc.C) { | ||
694 | 124 | s.ToolsFixture.TearDownTest(c) | ||
695 | 125 | s.LoggingSuite.TearDownTest(c) | ||
696 | 126 | } | ||
697 | 127 | |||
698 | 128 | func GetFakeConfig(sdcUrl, mantaUrl string) coretesting.Attrs { | ||
699 | 129 | return coretesting.FakeConfig().Merge(coretesting.Attrs{ | ||
700 | 130 | "name": "joyent test environment", | ||
701 | 131 | "type": "joyent", | ||
702 | 132 | "sdc-user": testUser, | ||
703 | 133 | "sdc-key-id": testKeyFingerprint, | ||
704 | 134 | "sdc-url": sdcUrl, | ||
705 | 135 | "manta-user": testUser, | ||
706 | 136 | "manta-key-id": testKeyFingerprint, | ||
707 | 137 | "manta-url": mantaUrl, | ||
708 | 138 | "key-file": fmt.Sprintf("%s/.ssh/%s", os.Getenv("HOME"), testKeyFileName), | ||
709 | 139 | "algorithm": "rsa-sha256", | ||
710 | 140 | "control-dir": "juju-test", | ||
711 | 141 | }) | ||
712 | 142 | } | ||
713 | 143 | |||
714 | 144 | // makeEnviron creates a functional Joyent environ for a test. | ||
715 | 145 | func (suite *providerSuite) makeEnviron(sdcUrl, mantaUrl string) *jp.JoyentEnviron { | ||
716 | 146 | /*attrs := coretesting.FakeConfig().Merge(coretesting.Attrs{ | ||
717 | 147 | "name": "joyent test environment", | ||
718 | 148 | "type": "joyent", | ||
719 | 149 | "sdc-user": "dstroppa", | ||
720 | 150 | "sdc-key-id": "12:c3:a7:cb:a2:29:e2:90:88:3f:04:53:3b:4e:75:40", | ||
721 | 151 | "sdc-url": "https://us-west-1.api.joyentcloud.com", | ||
722 | 152 | "manta-user": "dstroppa", | ||
723 | 153 | "manta-key-id": "12:c3:a7:cb:a2:29:e2:90:88:3f:04:53:3b:4e:75:40", | ||
724 | 154 | "manta-url": "https://us-east.manta.joyent.com", | ||
725 | 155 | "key-file": fmt.Sprintf("%s/.ssh/id_rsa", os.Getenv("HOME")), | ||
726 | 156 | "algorithm": "rsa-sha256", | ||
727 | 157 | "control-dir": "juju-test", | ||
728 | 158 | })*/ | ||
729 | 159 | |||
730 | 160 | attrs := GetFakeConfig(sdcUrl, mantaUrl) | ||
731 | 161 | cfg, err := config.New(config.NoDefaults, attrs) | ||
732 | 162 | if err != nil { | ||
733 | 163 | panic(err) | ||
734 | 164 | } | ||
735 | 165 | env, err := jp.NewEnviron(cfg) | ||
736 | 166 | if err != nil { | ||
737 | 167 | panic(err) | ||
738 | 168 | } | ||
739 | 169 | return env | ||
740 | 170 | } | ||
741 | 171 | |||
742 | 172 | func createTestKey() error { | ||
743 | 173 | keyFile := fmt.Sprintf("%s/.ssh/%s", os.Getenv("HOME"), testKeyFileName) | ||
744 | 174 | return ioutil.WriteFile(keyFile, []byte(testPrivateKey), 400) | ||
745 | 175 | } | ||
746 | 176 | |||
747 | 177 | func removeTestKey() error { | ||
748 | 178 | keyFile := fmt.Sprintf("%s/.ssh/%s", os.Getenv("HOME"), testKeyFileName) | ||
749 | 179 | return os.Remove(keyFile) | ||
750 | 27 | } | 180 | } |
751 | 28 | 181 | ||
752 | === modified file 'provider/joyent/provider.go' | |||
753 | --- provider/joyent/provider.go 2014-02-13 02:46:58 +0000 | |||
754 | +++ provider/joyent/provider.go 2014-02-27 18:08:22 +0000 | |||
755 | @@ -45,7 +45,7 @@ | |||
756 | 45 | } | 45 | } |
757 | 46 | 46 | ||
758 | 47 | func (environProvider) Open(cfg *config.Config) (environs.Environ, error) { | 47 | func (environProvider) Open(cfg *config.Config) (environs.Environ, error) { |
760 | 48 | env := &environ{name: cfg.Name()} | 48 | env := &JoyentEnviron{name: cfg.Name()} |
761 | 49 | if err := env.SetConfig(cfg); err != nil { | 49 | if err := env.SetConfig(cfg); err != nil { |
762 | 50 | return nil, err | 50 | return nil, err |
763 | 51 | } | 51 | } |
764 | @@ -118,3 +118,7 @@ | |||
765 | 118 | // provider; and it needs to return the address of *that* instance. | 118 | // provider; and it needs to return the address of *that* instance. |
766 | 119 | return "", errNotImplemented | 119 | return "", errNotImplemented |
767 | 120 | } | 120 | } |
768 | 121 | |||
769 | 122 | func GetProviderInstance() environs.EnvironProvider { | ||
770 | 123 | return providerInstance | ||
771 | 124 | } | ||
772 | 121 | 125 | ||
773 | === modified file 'provider/joyent/storage.go' | |||
774 | --- provider/joyent/storage.go 2013-11-21 17:37:18 +0000 | |||
775 | +++ provider/joyent/storage.go 2014-02-27 18:08:22 +0000 | |||
776 | @@ -4,50 +4,194 @@ | |||
777 | 4 | package joyent | 4 | package joyent |
778 | 5 | 5 | ||
779 | 6 | import ( | 6 | import ( |
780 | 7 | "bytes" | ||
781 | 8 | "fmt" | ||
782 | 7 | "io" | 9 | "io" |
783 | 10 | "sync" | ||
784 | 11 | "time" | ||
785 | 8 | 12 | ||
786 | 9 | "launchpad.net/juju-core/environs/storage" | 13 | "launchpad.net/juju-core/environs/storage" |
787 | 10 | "launchpad.net/juju-core/utils" | 14 | "launchpad.net/juju-core/utils" |
788 | 15 | |||
789 | 16 | "launchpad.net/gojoyent/client" | ||
790 | 17 | "launchpad.net/gojoyent/jpc" | ||
791 | 18 | "launchpad.net/gojoyent/manta" | ||
792 | 11 | ) | 19 | ) |
793 | 12 | 20 | ||
799 | 13 | type environStorage struct { | 21 | type JoyentStorage struct { |
800 | 14 | ecfg *environConfig | 22 | sync.Mutex |
801 | 15 | } | 23 | ecfg *environConfig |
802 | 16 | 24 | madeContainer bool | |
803 | 17 | var _ storage.Storage = (*environStorage)(nil) | 25 | containerName string |
804 | 26 | manta *manta.Client | ||
805 | 27 | } | ||
806 | 28 | |||
807 | 29 | type byteCloser struct { | ||
808 | 30 | io.Reader | ||
809 | 31 | } | ||
810 | 32 | |||
811 | 33 | func (byteCloser) Close() error { | ||
812 | 34 | return nil | ||
813 | 35 | } | ||
814 | 36 | |||
815 | 37 | var _ storage.Storage = (*JoyentStorage)(nil) | ||
816 | 38 | |||
817 | 39 | func NewStorage(env *JoyentEnviron) storage.Storage { | ||
818 | 40 | if stor, err := newStorage(env.ecfg); err == nil { | ||
819 | 41 | return stor | ||
820 | 42 | } | ||
821 | 43 | return nil | ||
822 | 44 | } | ||
823 | 45 | |||
824 | 46 | func getCredentials(ecfg *environConfig) *jpc.Credentials { | ||
825 | 47 | auth := jpc.Auth{User: ecfg.mantaUser(), KeyFile: ecfg.keyFile(), Algorithm: ecfg.algorithm()} | ||
826 | 48 | |||
827 | 49 | return &jpc.Credentials{ | ||
828 | 50 | UserAuthentication: auth, | ||
829 | 51 | MantaKeyId: ecfg.mantaKeyId(), | ||
830 | 52 | MantaEndpoint: jpc.Endpoint{URL: ecfg.mantaUrl()}, | ||
831 | 53 | } | ||
832 | 54 | } | ||
833 | 18 | 55 | ||
834 | 19 | func newStorage(ecfg *environConfig) (storage.Storage, error) { | 56 | func newStorage(ecfg *environConfig) (storage.Storage, error) { |
863 | 20 | return &environStorage{ecfg}, nil | 57 | client := client.NewClient(ecfg.mantaUrl(), "", getCredentials(ecfg), &logger) |
864 | 21 | } | 58 | |
865 | 22 | 59 | return &JoyentStorage{ | |
866 | 23 | func (s *environStorage) List(prefix string) ([]string, error) { | 60 | ecfg: ecfg, |
867 | 24 | return nil, errNotImplemented | 61 | containerName: ecfg.controlDir(), |
868 | 25 | } | 62 | manta: manta.New(client)}, nil |
869 | 26 | 63 | } | |
870 | 27 | func (s *environStorage) URL(name string) (string, error) { | 64 | |
871 | 28 | return "", errNotImplemented | 65 | func (s *JoyentStorage) GetContainerName() string { |
872 | 29 | } | 66 | return s.containerName |
873 | 30 | 67 | } | |
874 | 31 | func (s *environStorage) Get(name string) (io.ReadCloser, error) { | 68 | |
875 | 32 | return nil, errNotImplemented | 69 | func (s *JoyentStorage) GetMantaUrl() string { |
876 | 33 | } | 70 | return s.ecfg.mantaUrl() |
877 | 34 | 71 | } | |
878 | 35 | func (s *environStorage) Put(name string, r io.Reader, length int64) error { | 72 | |
879 | 36 | return errNotImplemented | 73 | func (s *JoyentStorage) GetMantaUser() string { |
880 | 37 | } | 74 | return s.ecfg.mantaUser() |
881 | 38 | 75 | } | |
882 | 39 | func (s *environStorage) Remove(name string) error { | 76 | |
883 | 40 | return errNotImplemented | 77 | // CreateContainer makes the environment's control container, the |
884 | 41 | } | 78 | // place where bootstrap information and deployed charms |
885 | 42 | 79 | // are stored. To avoid two round trips on every PUT operation, | |
886 | 43 | func (s *environStorage) RemoveAll() error { | 80 | // we do this only once for each environ. |
887 | 44 | return errNotImplemented | 81 | func (s *JoyentStorage) CreateContainer() error { |
888 | 45 | } | 82 | s.Lock() |
889 | 46 | 83 | defer s.Unlock() | |
890 | 47 | func (s *environStorage) DefaultConsistencyStrategy() utils.AttemptStrategy { | 84 | if s.madeContainer { |
891 | 85 | return nil | ||
892 | 86 | } | ||
893 | 87 | // try to make the container | ||
894 | 88 | err := s.manta.PutDirectory(s.containerName) | ||
895 | 89 | if err == nil { | ||
896 | 90 | s.madeContainer = true | ||
897 | 91 | } | ||
898 | 92 | return err | ||
899 | 93 | } | ||
900 | 94 | |||
901 | 95 | // deleteContainer deletes the named container from the storage account. | ||
902 | 96 | func (s *JoyentStorage) DeleteContainer(containerName string) error { | ||
903 | 97 | err := s.manta.DeleteDirectory(containerName) | ||
904 | 98 | if err == nil { | ||
905 | 99 | s.madeContainer = false | ||
906 | 100 | } | ||
907 | 101 | return err | ||
908 | 102 | } | ||
909 | 103 | |||
910 | 104 | func (s *JoyentStorage) List(prefix string) ([]string, error) { | ||
911 | 105 | // use empty opts, i.e. default values | ||
912 | 106 | // -- might be added in the provider config? | ||
913 | 107 | contents, err := s.manta.ListDirectory(s.containerName, manta.ListDirectoryOpts{}) | ||
914 | 108 | if err != nil { | ||
915 | 109 | return nil, err | ||
916 | 110 | } | ||
917 | 111 | var names []string | ||
918 | 112 | for _, item := range contents { | ||
919 | 113 | names = append(names, item.Name) | ||
920 | 114 | } | ||
921 | 115 | return names, nil | ||
922 | 116 | } | ||
923 | 117 | |||
924 | 118 | //return something that a random wget can retrieve the object at, without any credentials | ||
925 | 119 | func (s *JoyentStorage) URL(name string) (string, error) { | ||
926 | 120 | path := fmt.Sprintf("/%s/stor/%s/%s", s.ecfg.mantaUser(), s.containerName, name) | ||
927 | 121 | return s.manta.SignURL(path, time.Now().AddDate(10, 0, 0)) | ||
928 | 122 | } | ||
929 | 123 | |||
930 | 124 | func (s *JoyentStorage) Get(name string) (io.ReadCloser, error) { | ||
931 | 125 | b, err := s.manta.GetObject(s.containerName, name) | ||
932 | 126 | if err != nil { | ||
933 | 127 | return nil, err | ||
934 | 128 | } | ||
935 | 129 | r := byteCloser{bytes.NewReader(b)} | ||
936 | 130 | return r, nil | ||
937 | 131 | } | ||
938 | 132 | |||
939 | 133 | func (s *JoyentStorage) Put(name string, r io.Reader, length int64) error { | ||
940 | 134 | if err := s.CreateContainer(); err != nil { | ||
941 | 135 | return fmt.Errorf("cannot make Manta control container: %v", err) | ||
942 | 136 | } | ||
943 | 137 | err := s.manta.PutObject(s.containerName, name, r) | ||
944 | 138 | if err != nil { | ||
945 | 139 | return fmt.Errorf("cannot write file %q to control container %q: %v", name, s.containerName, err) | ||
946 | 140 | } | ||
947 | 141 | return nil | ||
948 | 142 | } | ||
949 | 143 | |||
950 | 144 | func (s *JoyentStorage) Remove(name string) error { | ||
951 | 145 | err := s.manta.DeleteObject(s.containerName, name) | ||
952 | 146 | if err != nil { | ||
953 | 147 | return err | ||
954 | 148 | } | ||
955 | 149 | return nil | ||
956 | 150 | } | ||
957 | 151 | |||
958 | 152 | func (s *JoyentStorage) RemoveAll() error { | ||
959 | 153 | names, err := storage.List(s, "") | ||
960 | 154 | if err != nil { | ||
961 | 155 | return err | ||
962 | 156 | } | ||
963 | 157 | // Remove all the objects in parallel so that we incur less round-trips. | ||
964 | 158 | // If we're in danger of having hundreds of objects, | ||
965 | 159 | // we'll want to change this to limit the number | ||
966 | 160 | // of concurrent operations. | ||
967 | 161 | var wg sync.WaitGroup | ||
968 | 162 | wg.Add(len(names)) | ||
969 | 163 | errc := make(chan error, len(names)) | ||
970 | 164 | for _, name := range names { | ||
971 | 165 | name := name | ||
972 | 166 | go func() { | ||
973 | 167 | defer wg.Done() | ||
974 | 168 | if err := s.Remove(name); err != nil { | ||
975 | 169 | errc <- err | ||
976 | 170 | } | ||
977 | 171 | }() | ||
978 | 172 | } | ||
979 | 173 | wg.Wait() | ||
980 | 174 | select { | ||
981 | 175 | case err := <-errc: | ||
982 | 176 | return fmt.Errorf("cannot delete all provider state: %v", err) | ||
983 | 177 | default: | ||
984 | 178 | } | ||
985 | 179 | |||
986 | 180 | s.Lock() | ||
987 | 181 | defer s.Unlock() | ||
988 | 182 | // Even DeleteContainer fails, it won't harm if we try again - the | ||
989 | 183 | // operation might have succeeded even if we get an error. | ||
990 | 184 | s.madeContainer = false | ||
991 | 185 | if err = s.manta.DeleteDirectory(s.containerName); err != nil { | ||
992 | 186 | return err | ||
993 | 187 | } | ||
994 | 188 | return nil | ||
995 | 189 | } | ||
996 | 190 | |||
997 | 191 | func (s *JoyentStorage) DefaultConsistencyStrategy() utils.AttemptStrategy { | ||
998 | 48 | return utils.AttemptStrategy{} | 192 | return utils.AttemptStrategy{} |
999 | 49 | } | 193 | } |
1000 | 50 | 194 | ||
1002 | 51 | func (s *environStorage) ShouldRetry(err error) bool { | 195 | func (s *JoyentStorage) ShouldRetry(err error) bool { |
1003 | 52 | return false | 196 | return false |
1004 | 53 | } | 197 | } |
1005 | 54 | 198 | ||
1006 | === added file 'provider/joyent/storage_test.go' | |||
1007 | --- provider/joyent/storage_test.go 1970-01-01 00:00:00 +0000 | |||
1008 | +++ provider/joyent/storage_test.go 2014-02-27 18:08:22 +0000 | |||
1009 | @@ -0,0 +1,189 @@ | |||
1010 | 1 | // Copyright 2013 Joyent Inc. | ||
1011 | 2 | // Licensed under the AGPLv3, see LICENCE file for details. | ||
1012 | 3 | |||
1013 | 4 | package joyent_test | ||
1014 | 5 | |||
1015 | 6 | import ( | ||
1016 | 7 | "fmt" | ||
1017 | 8 | "io/ioutil" | ||
1018 | 9 | "math/rand" | ||
1019 | 10 | "net/http" | ||
1020 | 11 | "net/url" | ||
1021 | 12 | "strings" | ||
1022 | 13 | |||
1023 | 14 | gc "launchpad.net/gocheck" | ||
1024 | 15 | jp "launchpad.net/juju-core/provider/joyent" | ||
1025 | 16 | jc "launchpad.net/juju-core/testing/checkers" | ||
1026 | 17 | |||
1027 | 18 | "launchpad.net/gojoyent/errors" | ||
1028 | 19 | ) | ||
1029 | 20 | |||
1030 | 21 | type storageSuite struct { | ||
1031 | 22 | providerSuite | ||
1032 | 23 | localMantaService | ||
1033 | 24 | } | ||
1034 | 25 | |||
1035 | 26 | const ( | ||
1036 | 27 | storageName = "testStorage" | ||
1037 | 28 | fileName = "testFile" | ||
1038 | 29 | fileBlobContent = "Juju Joyent Provider Storage - Test" | ||
1039 | 30 | ) | ||
1040 | 31 | |||
1041 | 32 | var _ = gc.Suite(&storageSuite{}) | ||
1042 | 33 | |||
1043 | 34 | func (s *storageSuite) SetUpSuite(c *gc.C) { | ||
1044 | 35 | s.providerSuite.SetUpSuite(c) | ||
1045 | 36 | s.localMantaService.Start(c) | ||
1046 | 37 | } | ||
1047 | 38 | |||
1048 | 39 | func (s *storageSuite) TearDownSuite(c *gc.C) { | ||
1049 | 40 | s.localMantaService.Stop() | ||
1050 | 41 | s.providerSuite.TearDownSuite(c) | ||
1051 | 42 | } | ||
1052 | 43 | |||
1053 | 44 | // s.makeStorage creates a Manta storage object for the running test. | ||
1054 | 45 | func (s *storageSuite) assertStorage(name string, c *gc.C) *jp.JoyentStorage { | ||
1055 | 46 | env := s.makeEnviron("localhost", s.localMantaService.Server.URL) | ||
1056 | 47 | env.SetName(name) | ||
1057 | 48 | storage := jp.NewStorage(env).(*jp.JoyentStorage) | ||
1058 | 49 | c.Assert(storage, gc.NotNil) | ||
1059 | 50 | return storage | ||
1060 | 51 | } | ||
1061 | 52 | |||
1062 | 53 | func (s *storageSuite) assertContainer(storage *jp.JoyentStorage, c *gc.C) { | ||
1063 | 54 | err := storage.CreateContainer() | ||
1064 | 55 | c.Assert(err, gc.IsNil) | ||
1065 | 56 | } | ||
1066 | 57 | |||
1067 | 58 | func (s *storageSuite) assertFile(storage *jp.JoyentStorage, c *gc.C) { | ||
1068 | 59 | err := storage.Put(fileName, strings.NewReader(fileBlobContent), int64(len(fileBlobContent))) | ||
1069 | 60 | c.Assert(err, gc.IsNil) | ||
1070 | 61 | } | ||
1071 | 62 | |||
1072 | 63 | // makeRandomBytes returns an array of arbitrary byte values. | ||
1073 | 64 | func makeRandomBytes(length int) []byte { | ||
1074 | 65 | data := make([]byte, length) | ||
1075 | 66 | for index := range data { | ||
1076 | 67 | data[index] = byte(rand.Intn(256)) | ||
1077 | 68 | } | ||
1078 | 69 | return data | ||
1079 | 70 | } | ||
1080 | 71 | |||
1081 | 72 | func makeResponse(content string, status int) *http.Response { | ||
1082 | 73 | return &http.Response{ | ||
1083 | 74 | Status: fmt.Sprintf("%d", status), | ||
1084 | 75 | StatusCode: status, | ||
1085 | 76 | Body: ioutil.NopCloser(strings.NewReader(content)), | ||
1086 | 77 | } | ||
1087 | 78 | } | ||
1088 | 79 | |||
1089 | 80 | func (s *storageSuite) TestList(c *gc.C) { | ||
1090 | 81 | mantaStorage := s.assertStorage(storageName, c) | ||
1091 | 82 | s.assertContainer(mantaStorage, c) | ||
1092 | 83 | s.assertFile(mantaStorage, c) | ||
1093 | 84 | |||
1094 | 85 | names, err := mantaStorage.List("prefix") | ||
1095 | 86 | c.Assert(err, gc.IsNil) | ||
1096 | 87 | c.Check(names, gc.DeepEquals, []string{fileName}) | ||
1097 | 88 | } | ||
1098 | 89 | |||
1099 | 90 | func (s *storageSuite) TestGet(c *gc.C) { | ||
1100 | 91 | mantaStorage := s.assertStorage(storageName, c) | ||
1101 | 92 | s.assertFile(mantaStorage, c) | ||
1102 | 93 | |||
1103 | 94 | reader, err := mantaStorage.Get(fileName) | ||
1104 | 95 | c.Assert(err, gc.IsNil) | ||
1105 | 96 | c.Assert(reader, gc.NotNil) | ||
1106 | 97 | defer reader.Close() | ||
1107 | 98 | |||
1108 | 99 | data, err := ioutil.ReadAll(reader) | ||
1109 | 100 | c.Assert(err, gc.IsNil) | ||
1110 | 101 | c.Check(string(data), gc.Equals, fileBlobContent) | ||
1111 | 102 | } | ||
1112 | 103 | |||
1113 | 104 | func (s *storageSuite) TestGetFileNotExists(c *gc.C) { | ||
1114 | 105 | mantaStorage := s.assertStorage(storageName, c) | ||
1115 | 106 | |||
1116 | 107 | _, err := mantaStorage.Get("noFile") | ||
1117 | 108 | c.Assert(err, gc.NotNil) | ||
1118 | 109 | c.Assert(err, jc.Satisfies, errors.IsResourceNotFound) | ||
1119 | 110 | } | ||
1120 | 111 | |||
1121 | 112 | func (s *storageSuite) TestPut(c *gc.C) { | ||
1122 | 113 | mantaStorage := s.assertStorage(storageName, c) | ||
1123 | 114 | |||
1124 | 115 | s.assertFile(mantaStorage, c) | ||
1125 | 116 | } | ||
1126 | 117 | |||
1127 | 118 | func (s *storageSuite) TestRemove(c *gc.C) { | ||
1128 | 119 | mantaStorage := s.assertStorage(storageName, c) | ||
1129 | 120 | s.assertFile(mantaStorage, c) | ||
1130 | 121 | |||
1131 | 122 | err := mantaStorage.Remove(fileName) | ||
1132 | 123 | c.Assert(err, gc.IsNil) | ||
1133 | 124 | } | ||
1134 | 125 | |||
1135 | 126 | func (s *storageSuite) TestRemoveFileNotExists(c *gc.C) { | ||
1136 | 127 | mantaStorage := s.assertStorage(storageName, c) | ||
1137 | 128 | |||
1138 | 129 | err := mantaStorage.Remove("nofile") | ||
1139 | 130 | c.Assert(err, gc.NotNil) | ||
1140 | 131 | c.Assert(err, jc.Satisfies, errors.IsResourceNotFound) | ||
1141 | 132 | } | ||
1142 | 133 | |||
1143 | 134 | func (s *storageSuite) TestRemoveAll(c *gc.C) { | ||
1144 | 135 | mantaStorage := s.assertStorage(storageName, c) | ||
1145 | 136 | |||
1146 | 137 | err := mantaStorage.RemoveAll() | ||
1147 | 138 | c.Assert(err, gc.IsNil) | ||
1148 | 139 | } | ||
1149 | 140 | |||
1150 | 141 | func (s *storageSuite) TestURL(c *gc.C) { | ||
1151 | 142 | mantaStorage := s.assertStorage(storageName, c) | ||
1152 | 143 | |||
1153 | 144 | URL, err := mantaStorage.URL(fileName) | ||
1154 | 145 | c.Assert(err, gc.IsNil) | ||
1155 | 146 | parsedURL, err := url.Parse(URL) | ||
1156 | 147 | c.Assert(err, gc.IsNil) | ||
1157 | 148 | c.Check(parsedURL.Host, gc.Matches, mantaStorage.GetMantaUrl()[strings.LastIndex(mantaStorage.GetMantaUrl(), "/")+1:]) | ||
1158 | 149 | c.Check(parsedURL.Path, gc.Matches, fmt.Sprintf("/%s/stor/%s/%s", mantaStorage.GetMantaUser(), mantaStorage.GetContainerName(), fileName)) | ||
1159 | 150 | } | ||
1160 | 151 | |||
1161 | 152 | func (s *storageSuite) TestCreateContainer(c *gc.C) { | ||
1162 | 153 | mantaStorage := s.assertStorage(storageName, c) | ||
1163 | 154 | |||
1164 | 155 | s.assertContainer(mantaStorage, c) | ||
1165 | 156 | } | ||
1166 | 157 | |||
1167 | 158 | func (s *storageSuite) TestCreateContainerAlreadyExists(c *gc.C) { | ||
1168 | 159 | mantaStorage := s.assertStorage(storageName, c) | ||
1169 | 160 | |||
1170 | 161 | s.assertContainer(mantaStorage, c) | ||
1171 | 162 | s.assertContainer(mantaStorage, c) | ||
1172 | 163 | } | ||
1173 | 164 | |||
1174 | 165 | func (s *storageSuite) TestDeleteContainer(c *gc.C) { | ||
1175 | 166 | mantaStorage := s.assertStorage(storageName, c) | ||
1176 | 167 | s.assertContainer(mantaStorage, c) | ||
1177 | 168 | |||
1178 | 169 | err := mantaStorage.DeleteContainer(mantaStorage.GetContainerName()) | ||
1179 | 170 | c.Assert(err, gc.IsNil) | ||
1180 | 171 | } | ||
1181 | 172 | |||
1182 | 173 | func (s *storageSuite) TestDeleteContainerNotEmpty(c *gc.C) { | ||
1183 | 174 | mantaStorage := s.assertStorage(storageName, c) | ||
1184 | 175 | s.assertContainer(mantaStorage, c) | ||
1185 | 176 | s.assertFile(mantaStorage, c) | ||
1186 | 177 | |||
1187 | 178 | err := mantaStorage.DeleteContainer(mantaStorage.GetContainerName()) | ||
1188 | 179 | c.Assert(err, gc.NotNil) | ||
1189 | 180 | c.Assert(err, jc.Satisfies, errors.IsBadRequest) | ||
1190 | 181 | } | ||
1191 | 182 | |||
1192 | 183 | func (s *storageSuite) TestDeleteContainerNotExists(c *gc.C) { | ||
1193 | 184 | mantaStorage := s.assertStorage(storageName, c) | ||
1194 | 185 | |||
1195 | 186 | err := mantaStorage.DeleteContainer("noContainer") | ||
1196 | 187 | c.Assert(err, gc.NotNil) | ||
1197 | 188 | c.Assert(err, jc.Satisfies, errors.IsResourceNotFound) | ||
1198 | 189 | } |
Reviewers: mp+200851_ code.launchpad. net,
Message:
Please take a look.
Description:
Joyent Provider - Storage impl
https:/ /code.launchpad .net/~dstroppa/ juju-core/ joyent- provider- storage/ +merge/ 200851
(do not edit description out of merge proposal)
Please review this at https:/ /codereview. appspot. com/49050044/
Affected files (+566, -151 lines): joyent/ config. go joyent/ config_ test.go joyent/ environ. go joyent/ environ_ firewall. go joyent/ environ_ instance. go joyent/ instance. go joyent/ joyent_ test.go joyent/ provider. go joyent/ storage. go joyent/ storage_ test.go
M .bzrignore
A [revision details]
M dependencies.tsv
M provider/
M provider/
M provider/
M provider/
M provider/
M provider/
M provider/
M provider/
M provider/
A provider/