Skip to content

Commit

Permalink
Merge pull request #4106 from davecheney/fixedbugs/1533792
Browse files Browse the repository at this point in the history
Rewrite AddSubnetsWithTemplate to work around gccgo bug

Fixes LP 1533792

gccgo-4.9 as shipped in Trusty has a number of issues when interfaces
and reflection are combined. In an ideal world these bugs would not
happen, but they do, so the most expedient course of action is to
work around them in our code.

This change replaces the reflection driven construction of a state.SubnetInfo
structure with a more straight forward method which permutes the string
fields known to the structure today. This isn't as future proof as the
previous method, but avoiding the Faustian combination of interfaces and
reflection should make this code more reliable on buggy compilers.

(Review request: http://reviews.vapour.ws/r/3527/)
  • Loading branch information
jujubot committed Jan 14, 2016
2 parents 31b548a + c90180f commit 36b2604
Showing 1 changed file with 13 additions and 14 deletions.
27 changes: 13 additions & 14 deletions juju/testing/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ package testing

import (
"bytes"
"fmt"
"reflect"
"text/template"

jc "github.com/juju/testing/checkers"
Expand Down Expand Up @@ -75,27 +73,28 @@ func AddStateServerMachine(c *gc.C, st *state.State) *state.Machine {
// VLANTag: 42,
// })
func AddSubnetsWithTemplate(c *gc.C, st *state.State, numSubnets uint, infoTemplate state.SubnetInfo) {
infot := reflect.TypeOf(infoTemplate)
for subnetIndex := 0; subnetIndex < int(numSubnets); subnetIndex++ {
info := infoTemplate // make a copy each time.

for fieldIndex := 0; fieldIndex < infot.NumField(); fieldIndex++ {
fieldv := reflect.ValueOf(&info).Elem().Field(fieldIndex)

if fieldv.Kind() != reflect.String {
// Skip non string fields.
continue
}

text := fmt.Sprint(fieldv.Interface())
t, err := template.New("").Parse(text)
// permute replaces the contents of *s with the result of interpreting
// *s as a template.
permute := func(s *string) {
t, err := template.New("").Parse(*s)
c.Assert(err, jc.ErrorIsNil)

var buf bytes.Buffer
err = t.Execute(&buf, subnetIndex)
c.Assert(err, jc.ErrorIsNil)
fieldv.SetString(buf.String())
*s = buf.String()
}

permute(&info.ProviderId)
permute(&info.CIDR)
permute(&info.AllocatableIPHigh)
permute(&info.AllocatableIPLow)
permute(&info.AvailabilityZone)
permute(&info.SpaceName)

_, err := st.AddSubnet(info)
c.Assert(err, jc.ErrorIsNil)
}
Expand Down

0 comments on commit 36b2604

Please sign in to comment.