Merge lp:~natefinch/juju-core/005-azure-address into lp:~go-bot/juju-core/trunk

Proposed by Nate Finch
Status: Merged
Approved by: John A Meinel
Approved revision: no longer in the source branch.
Merged at revision: 1767
Proposed branch: lp:~natefinch/juju-core/005-azure-address
Merge into: lp:~go-bot/juju-core/trunk
Diff against target: 222 lines (+120/-34)
2 files modified
provider/azure/instance.go (+73/-32)
provider/azure/instance_test.go (+47/-2)
To merge this branch: bzr merge lp:~natefinch/juju-core/005-azure-address
Reviewer Review Type Date Requested Status
Juju Engineering Pending
Review via email: mp+181117@code.launchpad.net

Commit message

azure addressability changes

Implement Addresses()

https://codereview.appspot.com/13082044/

Description of the change

azure addressability changes

Implement Addresses()

https://codereview.appspot.com/13082044/

To post a comment you must log in.
Revision history for this message
Nate Finch (natefinch) wrote :

Reviewers: mp+181117_code.launchpad.net,

Message:
Please take a look.

Description:
azure addressability changes

Implement Addresses()

https://code.launchpad.net/~natefinch/juju-core/005-azure-address/+merge/181117

(do not edit description out of merge proposal)

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

Affected files:
   A [revision details]
   M environs/azure/instance.go
   M environs/azure/instance_test.go
   M testing/checkers/checker.go
   M testing/checkers/checker_test.go

Revision history for this message
John A Meinel (jameinel) wrote :
Download full text (3.5 KiB)

the code and tests for Addresses looks sane to me, though it might be
good to have someone on Red squad confirm the actual APIs you are
calling.

I have some questions about the Checker you implemented. The only bit
I'm genuinely worried about is mutating slices passed in by the caller.
If you add a test to reassure me we aren't changing them, the rest is
all just suggestions.

https://codereview.appspot.com/13082044/diff/1/testing/checkers/checker.go
File testing/checkers/checker.go (right):

https://codereview.appspot.com/13082044/diff/1/testing/checkers/checker.go#newcode157
testing/checkers/checker.go:157: // use it on very large slices
Is it hard to create a smart implementation that notices if the types
are hashable and can then just insert them into a map with counts and
then compare it?

counts := make(map[TYPE]int)
for i, v := range expected:
   counts[v] += 1
countsObtained := make(map[TYPE]int)
for i, v := range obtained:
   countsObtained[v] += 1

Obviously you need a bit more reflect magic than I've typed here, but
you also end up with nice summaries of the contents and what is
different. (You could even do it as a delta map and count up with
expected, and down with obtained.)

If it is "cheap" to determine if something is hashable, I think the
algorithm to count them is nice and short and reasonably obvious. And
probably most things we're doing are strings, structs, and ints anyway.

https://codereview.appspot.com/13082044/diff/1/testing/checkers/checker.go#newcode198
testing/checkers/checker.go:198: // that way we make sure the count of
duplicate items is the same
I'm a little concerned if removing them would mutate the caller's
slices. (You might compare to make sure they match, and then do other
things with the slice.)

Can you confirm that it doesn't?

Even better, add it as a test case so we ensure that we don't grow that
behavior accidentally in the future.

Another option that avoids rewriting the array N times would be to just
allocate a 'bool' array of the same length, and flag each entry with
True once you've seen it. When you iterate later, you can just check and
'continue' if that entry has already been seen.

You still end up with N^2 comparisons, but you have a lot fewer
reallocations.

My theoretical mind wonders if optimizing for the case of "lists are
identical" is worthwhile and starting the nested search at the offset of
the outer search. Or just doing one pass against all items until we have
something that doesn't match, and only then switch to the N^2 form.
Certainly not terribly important here.

https://codereview.appspot.com/13082044/diff/1/testing/checkers/checker_test.go
File testing/checkers/checker_test.go (right):

https://codereview.appspot.com/13082044/diff/1/testing/checkers/checker_test.go#newcode37
testing/checkers/checker_test.go:37: func (s *CheckerSuite)
TestSameContents(c *gc.C) {
I personally would rather see these split out as separate "Test*" cases,
rather than just commented sections. So a new suite for SameContents and
then test cases in that.

func (s *SameContentsSuite) TestSame(c *gc.C) {
   c.Check([]int(1, 2, 3), jc.SameContents, []int(1,2,3))
}

func (s *SameContentsSuite) TestE...

Read more...

Revision history for this message
Nate Finch (natefinch) wrote :
Revision history for this message
Nate Finch (natefinch) wrote :
Revision history for this message
Nate Finch (natefinch) wrote :

Somehow my last message contents got dropped on the floor... not sure
how that happened.

The checker stuff was moved into a different branch, and the diffs now
reflect that (and I had implemented the changes john mentioned there).

This code was looked at by allenap, since I was having difficulty
figuring out how to mock out the server responses for the tests, so I'm
pretty sure they're good to go.

https://codereview.appspot.com/13082044/

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

LGTM as long as it has been tested live.

https://codereview.appspot.com/13082044/

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

On 2013/08/23 13:33:18, jameinel wrote:
> LGTM as long as it has been tested live.

You commented that this has been reviewed by others, but then didn't
land this. Is it blocked on something else?

https://codereview.appspot.com/13082044/

Revision history for this message
Nate Finch (natefinch) wrote :
Revision history for this message
Martin Packman (gz) wrote :

LGTM.

https://codereview.appspot.com/13082044/diff/18001/provider/azure/instance.go
File provider/azure/instance.go (right):

https://codereview.appspot.com/13082044/diff/18001/provider/azure/instance.go#newcode64
provider/azure/instance.go:64: err = azInstance.apiCall(false, func(c
*azureManagementContext) error {
I find this closure pretty hard to read, what with it being most of the
outer function and has differing return spelling.

https://codereview.appspot.com/13082044/diff/18001/provider/azure/instance_test.go
File provider/azure/instance_test.go (right):

https://codereview.appspot.com/13082044/diff/18001/provider/azure/instance_test.go#newcode174
provider/azure/instance_test.go:174: instance.Address{
You don't actually need to repeat the type here.

https://codereview.appspot.com/13082044/

Revision history for this message
Go Bot (go-bot) wrote :
Download full text (7.2 KiB)

The attempt to merge lp:~natefinch/juju-core/005-azure-address into lp:juju-core failed. Below is the output from the failed tests.

ok launchpad.net/juju-core/agent 0.764s
ok launchpad.net/juju-core/agent/tools 0.240s
ok launchpad.net/juju-core/bzr 7.547s
ok launchpad.net/juju-core/cert 2.411s
ok launchpad.net/juju-core/charm 0.551s
? launchpad.net/juju-core/charm/hooks [no test files]
ok launchpad.net/juju-core/cloudinit 0.021s
ok launchpad.net/juju-core/cmd 0.201s
? launchpad.net/juju-core/cmd/builddb [no test files]
? launchpad.net/juju-core/cmd/charmd [no test files]
? launchpad.net/juju-core/cmd/charmload [no test files]
ok launchpad.net/juju-core/cmd/juju 120.106s
ok launchpad.net/juju-core/cmd/jujud 37.565s
ok launchpad.net/juju-core/cmd/plugins/juju-metadata 1.570s
ok launchpad.net/juju-core/constraints 0.029s
ok launchpad.net/juju-core/container/lxc 0.365s
? launchpad.net/juju-core/container/lxc/mock [no test files]
ok launchpad.net/juju-core/downloader 5.298s
ok launchpad.net/juju-core/environs 1.228s
ok launchpad.net/juju-core/environs/bootstrap 6.613s
ok launchpad.net/juju-core/environs/cloudinit 0.438s
ok launchpad.net/juju-core/environs/config 0.708s
? launchpad.net/juju-core/environs/filestorage [no test files]
ok launchpad.net/juju-core/environs/imagemetadata 0.377s
ok launchpad.net/juju-core/environs/instances 0.221s
ok launchpad.net/juju-core/environs/jujutest 0.254s
ok launchpad.net/juju-core/environs/localstorage 0.246s
ok launchpad.net/juju-core/environs/manual 1.039s
ok launchpad.net/juju-core/environs/simplestreams 0.255s
? launchpad.net/juju-core/environs/simplestreams/testing [no test files]
ok launchpad.net/juju-core/environs/sync 0.247s
ok launchpad.net/juju-core/environs/testing 0.010s
ok launchpad.net/juju-core/environs/tools 27.439s
? launchpad.net/juju-core/errors [no test files]
ok launchpad.net/juju-core/instance 0.019s
ok launchpad.net/juju-core/juju 14.954s
ok launchpad.net/juju-core/juju/osenv 0.247s
? launchpad.net/juju-core/juju/testing [no test files]
ok launchpad.net/juju-core/log 0.016s
ok launchpad.net/juju-core/log/syslog 0.017s
ok launchpad.net/juju-core/names 0.031s
ok launchpad.net/juju-core/provider 0.250s
? launchpad.net/juju-core/provider/all [no test files]
ok launchpad.net/juju-core/provider/azure 4.455s
ok launchpad.net/juju-core/provider/dummy 17.648s
ok launchpad.net/juju-core/provider/ec2 4.427s
ok launchpad.net/juju-core/provider/local 1.301s
? launchpad.net/juju-core/provider/local/storage [no test files]
ok launchpad.net/juju-core/provider/maas 2.115s
ok launchpad.net/juju-core/provider/openstack 3.982s
ok launchpad.net/juju-core/rpc 0.258s
ok launchpad.net/juju-core/rpc/jsoncodec 0.259s
ok launchpad.net/juju-core/schema 0.018s

----------------------------------------------------------------------
FAIL: relationunit_test.go:555: RelationUnitSuite.TestContainerWatchScope

[LOG] 93.14353 INFO juju.state opening state; mongo addresses: ["localhost:51340"]; entity ""
[LOG] 93.14798 INFO juju.state connection established
[LOG] 93.16266 INFO juju.state initializing environme...

Read more...

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'provider/azure/instance.go'
--- provider/azure/instance.go 2013-08-27 18:33:36 +0000
+++ provider/azure/instance.go 2013-09-04 15:14:28 +0000
@@ -38,8 +38,54 @@
3838
39// Addresses is specified in the Instance interface.39// Addresses is specified in the Instance interface.
40func (azInstance *azureInstance) Addresses() ([]instance.Address, error) {40func (azInstance *azureInstance) Addresses() ([]instance.Address, error) {
41 logger.Errorf("azureInstance.Addresses not implemented")41 addrs := []instance.Address{}
42 return nil, nil42 ip, netname, err := azInstance.netInfo()
43 if err != nil {
44 return nil, err
45 }
46 if ip != "" {
47 addrs = append(addrs, instance.Address{
48 ip,
49 instance.Ipv4Address,
50 netname,
51 instance.NetworkCloudLocal})
52 }
53
54 name, err := azInstance.DNSName()
55 if err != nil {
56 return nil, err
57 }
58 host := instance.Address{name, instance.HostName, "", instance.NetworkPublic}
59 addrs = append(addrs, host)
60 return addrs, nil
61}
62
63func (azInstance *azureInstance) netInfo() (ip, netname string, err error) {
64 err = azInstance.apiCall(false, func(c *azureManagementContext) error {
65 d, err := c.GetDeployment(&gwacl.GetDeploymentRequest{
66 ServiceName: azInstance.ServiceName,
67 DeploymentName: azInstance.ServiceName,
68 })
69 if err != nil {
70 return err
71 }
72 switch len(d.RoleInstanceList) {
73 case 0:
74 // nothing to do, this can happen if the instances aren't finished deploying
75 return nil
76 case 1:
77 // success
78 ip = d.RoleInstanceList[0].IPAddress
79 netname = d.VirtualNetworkName
80 return nil
81 default:
82 return fmt.Errorf("Too many instances, expected one, got %d", len(d.RoleInstanceList))
83 }
84 })
85 if err != nil {
86 return "", "", err
87 }
88 return ip, netname, nil
43}89}
4490
45// DNSName is specified in the Instance interface.91// DNSName is specified in the Instance interface.
@@ -60,6 +106,14 @@
60106
61// OpenPorts is specified in the Instance interface.107// OpenPorts is specified in the Instance interface.
62func (azInstance *azureInstance) OpenPorts(machineId string, ports []instance.Port) error {108func (azInstance *azureInstance) OpenPorts(machineId string, ports []instance.Port) error {
109 return azInstance.apiCall(true, func(context *azureManagementContext) error {
110 return azInstance.openEndpoints(context, ports)
111 })
112}
113
114// apiCall wraps a call to the azure API to ensure it is properly disposed, optionally locking
115// the environment
116func (azInstance *azureInstance) apiCall(lock bool, f func(*azureManagementContext) error) error {
63 env := azInstance.environ117 env := azInstance.environ
64118
65 context, err := env.getManagementAPI()119 context, err := env.getManagementAPI()
@@ -68,10 +122,11 @@
68 }122 }
69 defer env.releaseManagementAPI(context)123 defer env.releaseManagementAPI(context)
70124
71 env.Lock()125 if lock {
72 defer env.Unlock()126 env.Lock()
73127 defer env.Unlock()
74 return azInstance.openEndpoints(context, ports)128 }
129 return f(context)
75}130}
76131
77// openEndpoints opens the endpoints in the Azure deployment. The caller is132// openEndpoints opens the endpoints in the Azure deployment. The caller is
@@ -113,18 +168,9 @@
113168
114// ClosePorts is specified in the Instance interface.169// ClosePorts is specified in the Instance interface.
115func (azInstance *azureInstance) ClosePorts(machineId string, ports []instance.Port) error {170func (azInstance *azureInstance) ClosePorts(machineId string, ports []instance.Port) error {
116 env := azInstance.environ171 return azInstance.apiCall(true, func(context *azureManagementContext) error {
117172 return azInstance.closeEndpoints(context, ports)
118 context, err := env.getManagementAPI()173 })
119 if err != nil {
120 return err
121 }
122 defer env.releaseManagementAPI(context)
123
124 env.Lock()
125 defer env.Unlock()
126
127 return azInstance.closeEndpoints(context, ports)
128}174}
129175
130// closeEndpoints closes the endpoints in the Azure deployment. The caller is176// closeEndpoints closes the endpoints in the Azure deployment. The caller is
@@ -185,20 +231,15 @@
185}231}
186232
187// Ports is specified in the Instance interface.233// Ports is specified in the Instance interface.
188func (azInstance *azureInstance) Ports(machineId string) ([]instance.Port, error) {234func (azInstance *azureInstance) Ports(machineId string) (ports []instance.Port, err error) {
189 env := azInstance.environ235 err = azInstance.apiCall(false, func(context *azureManagementContext) error {
190 context, err := env.getManagementAPI()236 ports, err = azInstance.listPorts(context)
191 if err != nil {237 return err
192 return nil, err238 })
193 }239 if ports != nil {
194 defer env.releaseManagementAPI(context)240 state.SortPorts(ports)
195241 }
196 ports, err := azInstance.listPorts(context)242 return ports, err
197 if err != nil {
198 return nil, err
199 }
200 state.SortPorts(ports)
201 return ports, nil
202}243}
203244
204// listPorts returns the slice of ports (instance.Port) that this machine245// listPorts returns the slice of ports (instance.Port) that this machine
205246
=== modified file 'provider/azure/instance_test.go'
--- provider/azure/instance_test.go 2013-08-09 15:13:09 +0000
+++ provider/azure/instance_test.go 2013-09-04 15:14:28 +0000
@@ -5,13 +5,14 @@
55
6import (6import (
7 "encoding/base64"7 "encoding/base64"
8 "fmt"
9 "net/http"
810
9 gc "launchpad.net/gocheck"11 gc "launchpad.net/gocheck"
10 "launchpad.net/gwacl"12 "launchpad.net/gwacl"
1113
12 "fmt"
13 "launchpad.net/juju-core/instance"14 "launchpad.net/juju-core/instance"
14 "net/http"15 jc "launchpad.net/juju-core/testing/checkers"
15)16)
1617
17type instanceSuite struct{}18type instanceSuite struct{}
@@ -95,6 +96,14 @@
95 return []byte(xml)96 return []byte(xml)
96}97}
9798
99func prepareDeploymentInfoResponse(
100 c *gc.C, dep gwacl.Deployment) []gwacl.DispatcherResponse {
101 return []gwacl.DispatcherResponse{
102 gwacl.NewDispatcherResponse(
103 serialize(c, &dep), http.StatusOK, nil),
104 }
105}
106
98func preparePortChangeConversation(107func preparePortChangeConversation(
99 c *gc.C, service *gwacl.HostedServiceDescriptor,108 c *gc.C, service *gwacl.HostedServiceDescriptor,
100 deployments ...gwacl.Deployment) []gwacl.DispatcherResponse {109 deployments ...gwacl.Deployment) []gwacl.DispatcherResponse {
@@ -146,6 +155,42 @@
146 }155 }
147}156}
148157
158func (*instanceSuite) TestAddresses(c *gc.C) {
159 name := "service-name"
160 vnn := "Virt Net Name"
161 service := makeHostedServiceDescriptor(name)
162 responses := prepareDeploymentInfoResponse(c,
163 gwacl.Deployment{
164 RoleInstanceList: []gwacl.RoleInstance{
165 gwacl.RoleInstance{IPAddress: "1.2.3.4"},
166 },
167 VirtualNetworkName: vnn,
168 })
169
170 gwacl.PatchManagementAPIResponses(responses)
171 inst := azureInstance{*service, makeEnviron(c)}
172
173 expected := []instance.Address{
174 instance.Address{
175 "1.2.3.4",
176 instance.Ipv4Address,
177 vnn,
178 instance.NetworkCloudLocal,
179 },
180 instance.Address{
181 name + "." + AZURE_DOMAIN_NAME,
182 instance.HostName,
183 "",
184 instance.NetworkPublic,
185 },
186 }
187
188 addrs, err := inst.Addresses()
189 c.Check(err, gc.IsNil)
190
191 c.Check(addrs, jc.SameContents, expected)
192}
193
149func (*instanceSuite) TestOpenPorts(c *gc.C) {194func (*instanceSuite) TestOpenPorts(c *gc.C) {
150 service := makeHostedServiceDescriptor("service-name")195 service := makeHostedServiceDescriptor("service-name")
151 responses := preparePortChangeConversation(c, service,196 responses := preparePortChangeConversation(c, service,

Subscribers

People subscribed via source and target branches

to status/vote changes: