github.com/mattyw/juju@v0.0.0-20140610034352-732aecd63861/provider/openstack/live_test.go (about) 1 // Copyright 2012, 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package openstack_test 5 6 import ( 7 "crypto/rand" 8 "fmt" 9 "io" 10 "sort" 11 12 gc "launchpad.net/gocheck" 13 "launchpad.net/goose/client" 14 "launchpad.net/goose/identity" 15 "launchpad.net/goose/nova" 16 17 "github.com/juju/juju/environs" 18 "github.com/juju/juju/environs/bootstrap" 19 "github.com/juju/juju/environs/config" 20 "github.com/juju/juju/environs/jujutest" 21 "github.com/juju/juju/environs/storage" 22 envtesting "github.com/juju/juju/environs/testing" 23 jujutesting "github.com/juju/juju/juju/testing" 24 "github.com/juju/juju/provider/openstack" 25 coretesting "github.com/juju/juju/testing" 26 ) 27 28 // generate a different bucket name for each config instance, so that 29 // we are not polluted by previous test state. 30 func randomName() string { 31 buf := make([]byte, 8) 32 _, err := io.ReadFull(rand.Reader, buf) 33 if err != nil { 34 panic(fmt.Sprintf("error from crypto rand: %v", err)) 35 } 36 return fmt.Sprintf("%x", buf) 37 } 38 39 func makeTestConfig(cred *identity.Credentials) map[string]interface{} { 40 // The following attributes hold the environment configuration 41 // for running the OpenStack integration tests. 42 // 43 // This is missing keys for security reasons; set the following 44 // environment variables to make the OpenStack testing work: 45 // access-key: $OS_USERNAME 46 // secret-key: $OS_PASSWORD 47 // 48 attrs := coretesting.FakeConfig().Merge(coretesting.Attrs{ 49 "name": "sample-" + randomName(), 50 "type": "openstack", 51 "auth-mode": "userpass", 52 "control-bucket": "juju-test-" + randomName(), 53 "username": cred.User, 54 "password": cred.Secrets, 55 "region": cred.Region, 56 "auth-url": cred.URL, 57 "tenant-name": cred.TenantName, 58 }) 59 return attrs 60 } 61 62 // Register tests to run against a real Openstack instance. 63 func registerLiveTests(cred *identity.Credentials) { 64 config := makeTestConfig(cred) 65 gc.Suite(&LiveTests{ 66 cred: cred, 67 LiveTests: jujutest.LiveTests{ 68 TestConfig: config, 69 Attempt: *openstack.ShortAttempt, 70 CanOpenState: true, 71 HasProvisioner: true, 72 }, 73 }) 74 } 75 76 // LiveTests contains tests that can be run against OpenStack deployments. 77 // The deployment can be a real live instance or service doubles. 78 // Each test runs using the same connection. 79 type LiveTests struct { 80 coretesting.BaseSuite 81 jujutest.LiveTests 82 cred *identity.Credentials 83 metadataStorage storage.Storage 84 } 85 86 func (t *LiveTests) SetUpSuite(c *gc.C) { 87 t.BaseSuite.SetUpSuite(c) 88 // Update some Config items now that we have services running. 89 // This is setting the simplestreams urls and auth-url because that 90 // information is set during startup of the localLiveSuite 91 cl := client.NewClient(t.cred, identity.AuthUserPass, nil) 92 err := cl.Authenticate() 93 c.Assert(err, gc.IsNil) 94 containerURL, err := cl.MakeServiceURL("object-store", nil) 95 c.Assert(err, gc.IsNil) 96 t.TestConfig = t.TestConfig.Merge(coretesting.Attrs{ 97 "tools-metadata-url": containerURL + "/juju-dist-test/tools", 98 "image-metadata-url": containerURL + "/juju-dist-test", 99 "auth-url": t.cred.URL, 100 }) 101 t.LiveTests.SetUpSuite(c) 102 // For testing, we create a storage instance to which is uploaded tools and image metadata. 103 t.PrepareOnce(c) 104 t.metadataStorage = openstack.MetadataStorage(t.Env) 105 // Put some fake tools metadata in place so that tests that are simply 106 // starting instances without any need to check if those instances 107 // are running can find the metadata. 108 envtesting.UploadFakeTools(c, t.metadataStorage) 109 } 110 111 func (t *LiveTests) TearDownSuite(c *gc.C) { 112 if t.Env == nil { 113 // This can happen if SetUpSuite fails. 114 return 115 } 116 if t.metadataStorage != nil { 117 envtesting.RemoveFakeToolsMetadata(c, t.metadataStorage) 118 } 119 t.LiveTests.TearDownSuite(c) 120 t.BaseSuite.TearDownSuite(c) 121 } 122 123 func (t *LiveTests) SetUpTest(c *gc.C) { 124 t.BaseSuite.SetUpTest(c) 125 t.LiveTests.SetUpTest(c) 126 } 127 128 func (t *LiveTests) TearDownTest(c *gc.C) { 129 t.LiveTests.TearDownTest(c) 130 t.BaseSuite.TearDownTest(c) 131 } 132 133 func (t *LiveTests) TestEnsureGroupSetsGroupId(c *gc.C) { 134 t.PrepareOnce(c) 135 rules := []nova.RuleInfo{ 136 { // First group explicitly asks for all services 137 IPProtocol: "tcp", 138 FromPort: 22, 139 ToPort: 22, 140 Cidr: "0.0.0.0/0", 141 }, 142 { // Second group should only allow access from within the group 143 IPProtocol: "tcp", 144 FromPort: 1, 145 ToPort: 65535, 146 }, 147 } 148 groupName := "juju-test-group-" + randomName() 149 // Make sure things are clean before we start, and clean when we are done 150 cleanup := func() { 151 c.Check(openstack.DiscardSecurityGroup(t.Env, groupName), gc.IsNil) 152 } 153 cleanup() 154 defer cleanup() 155 group, err := openstack.EnsureGroup(t.Env, groupName, rules) 156 c.Assert(err, gc.IsNil) 157 c.Check(group.Rules, gc.HasLen, 2) 158 c.Check(*group.Rules[0].IPProtocol, gc.Equals, "tcp") 159 c.Check(*group.Rules[0].FromPort, gc.Equals, 22) 160 c.Check(*group.Rules[0].ToPort, gc.Equals, 22) 161 c.Check(group.Rules[0].IPRange["cidr"], gc.Equals, "0.0.0.0/0") 162 c.Check(group.Rules[0].Group.Name, gc.Equals, "") 163 c.Check(group.Rules[0].Group.TenantId, gc.Equals, "") 164 c.Check(*group.Rules[1].IPProtocol, gc.Equals, "tcp") 165 c.Check(*group.Rules[1].FromPort, gc.Equals, 1) 166 c.Check(*group.Rules[1].ToPort, gc.Equals, 65535) 167 c.Check(group.Rules[1].IPRange, gc.HasLen, 0) 168 c.Check(group.Rules[1].Group.Name, gc.Equals, groupName) 169 c.Check(group.Rules[1].Group.TenantId, gc.Equals, group.TenantId) 170 } 171 172 func (t *LiveTests) TestSetupGlobalGroupExposesCorrectPorts(c *gc.C) { 173 t.PrepareOnce(c) 174 groupName := "juju-test-group-" + randomName() 175 // Make sure things are clean before we start, and will be clean when we finish 176 cleanup := func() { 177 c.Check(openstack.DiscardSecurityGroup(t.Env, groupName), gc.IsNil) 178 } 179 cleanup() 180 defer cleanup() 181 statePort := 12345 // Default 37017 182 apiPort := 34567 // Default 17070 183 group, err := openstack.SetUpGlobalGroup(t.Env, groupName, statePort, apiPort) 184 c.Assert(err, gc.IsNil) 185 c.Assert(err, gc.IsNil) 186 // We default to exporting 22, statePort, apiPort, and icmp/udp/tcp on 187 // all ports to other machines inside the same group 188 // TODO(jam): 2013-09-18 http://pad.lv/1227142 189 // We shouldn't be exposing the API and State ports on all the machines 190 // that *aren't* hosting the state server. (And once we finish 191 // client-via-API we can disable the State port as well.) 192 stringRules := make([]string, 0, len(group.Rules)) 193 for _, rule := range group.Rules { 194 ruleStr := fmt.Sprintf("%s %d %d %q %q", 195 *rule.IPProtocol, 196 *rule.FromPort, 197 *rule.ToPort, 198 rule.IPRange["cidr"], 199 rule.Group.Name, 200 ) 201 stringRules = append(stringRules, ruleStr) 202 } 203 // We don't care about the ordering, so we sort the result, and compare it. 204 expectedRules := []string{ 205 `tcp 22 22 "0.0.0.0/0" ""`, 206 fmt.Sprintf(`tcp %d %d "0.0.0.0/0" ""`, statePort, statePort), 207 fmt.Sprintf(`tcp %d %d "0.0.0.0/0" ""`, apiPort, apiPort), 208 fmt.Sprintf(`tcp 1 65535 "" "%s"`, groupName), 209 fmt.Sprintf(`udp 1 65535 "" "%s"`, groupName), 210 fmt.Sprintf(`icmp -1 -1 "" "%s"`, groupName), 211 } 212 sort.Strings(stringRules) 213 sort.Strings(expectedRules) 214 c.Check(stringRules, gc.DeepEquals, expectedRules) 215 } 216 217 func (s *LiveTests) assertStartInstanceDefaultSecurityGroup(c *gc.C, useDefault bool) { 218 attrs := s.TestConfig.Merge(coretesting.Attrs{ 219 "name": "sample-" + randomName(), 220 "control-bucket": "juju-test-" + randomName(), 221 "use-default-secgroup": useDefault, 222 }) 223 cfg, err := config.New(config.NoDefaults, attrs) 224 c.Assert(err, gc.IsNil) 225 // Set up a test environment. 226 env, err := environs.New(cfg) 227 c.Assert(err, gc.IsNil) 228 c.Assert(env, gc.NotNil) 229 defer env.Destroy() 230 // Bootstrap and start an instance. 231 err = bootstrap.Bootstrap(coretesting.Context(c), env, environs.BootstrapParams{}) 232 c.Assert(err, gc.IsNil) 233 inst, _ := jujutesting.AssertStartInstance(c, env, "100") 234 // Check whether the instance has the default security group assigned. 235 novaClient := openstack.GetNovaClient(env) 236 groups, err := novaClient.GetServerSecurityGroups(string(inst.Id())) 237 c.Assert(err, gc.IsNil) 238 defaultGroupFound := false 239 for _, group := range groups { 240 if group.Name == "default" { 241 defaultGroupFound = true 242 break 243 } 244 } 245 c.Assert(defaultGroupFound, gc.Equals, useDefault) 246 } 247 248 func (s *LiveTests) TestStartInstanceWithDefaultSecurityGroup(c *gc.C) { 249 s.assertStartInstanceDefaultSecurityGroup(c, true) 250 } 251 252 func (s *LiveTests) TestStartInstanceWithoutDefaultSecurityGroup(c *gc.C) { 253 s.assertStartInstanceDefaultSecurityGroup(c, false) 254 }