launchpad.net/~rogpeppe/juju-core/500-errgo-fix@v0.0.0-20140213181702-000000002356/provider/openstack/export_test.go (about)

     1  // Copyright 2012, 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package openstack
     5  
     6  import (
     7  	"bytes"
     8  	"fmt"
     9  	"strings"
    10  	"text/template"
    11  
    12  	"launchpad.net/goose/errors"
    13  	"launchpad.net/goose/identity"
    14  	"launchpad.net/goose/nova"
    15  	"launchpad.net/goose/swift"
    16  
    17  	"launchpad.net/juju-core/constraints"
    18  	"launchpad.net/juju-core/environs"
    19  	"launchpad.net/juju-core/environs/instances"
    20  	"launchpad.net/juju-core/environs/jujutest"
    21  	"launchpad.net/juju-core/environs/simplestreams"
    22  	"launchpad.net/juju-core/environs/storage"
    23  	"launchpad.net/juju-core/instance"
    24  )
    25  
    26  // This provides the content for code accessing test:///... URLs. This allows
    27  // us to set the responses for things like the Metadata server, by pointing
    28  // metadata requests at test:///... rather than http://169.254.169.254
    29  var testRoundTripper = &jujutest.ProxyRoundTripper{}
    30  
    31  func init() {
    32  	testRoundTripper.RegisterForScheme("test")
    33  }
    34  
    35  var origMetadataHost = metadataHost
    36  
    37  var metadataContent = `"availability_zone": "nova", "hostname": "test.novalocal", ` +
    38  	`"launch_index": 0, "meta": {"priority": "low", "role": "webserver"}, ` +
    39  	`"public_keys": {"mykey": "ssh-rsa fake-key\n"}, "name": "test"}`
    40  
    41  // A group of canned responses for the "metadata server". These match
    42  // reasonably well with the results of making those requests on a Folsom+
    43  // Openstack service
    44  var MetadataTesting = map[string]string{
    45  	"/latest/meta-data/local-ipv4":         "10.1.1.2",
    46  	"/latest/meta-data/public-ipv4":        "203.1.1.2",
    47  	"/openstack/2012-08-10/meta_data.json": metadataContent,
    48  }
    49  
    50  // Set Metadata requests to be served by the filecontent supplied.
    51  func UseTestMetadata(metadata map[string]string) {
    52  	if len(metadata) != 0 {
    53  		testRoundTripper.Sub = jujutest.NewCannedRoundTripper(metadata, nil)
    54  		metadataHost = "test:"
    55  	} else {
    56  		testRoundTripper.Sub = nil
    57  		metadataHost = origMetadataHost
    58  	}
    59  }
    60  
    61  var (
    62  	ShortAttempt   = &shortAttempt
    63  	StorageAttempt = &storageAttempt
    64  )
    65  
    66  // MetadataStorage returns a Storage instance which is used to store simplestreams metadata for tests.
    67  func MetadataStorage(e environs.Environ) storage.Storage {
    68  	ecfg := e.(*environ).ecfg()
    69  	authModeCfg := AuthMode(ecfg.authMode())
    70  	container := "juju-dist-test"
    71  	metadataStorage := &openstackstorage{
    72  		containerName: container,
    73  		swift:         swift.New(e.(*environ).authClient(ecfg, authModeCfg)),
    74  	}
    75  
    76  	// Ensure the container exists.
    77  	err := metadataStorage.makeContainer(container, swift.PublicRead)
    78  	if err != nil {
    79  		panic(fmt.Errorf("cannot create %s container: %v", container, err))
    80  	}
    81  	return metadataStorage
    82  }
    83  
    84  func InstanceAddress(addresses map[string][]nova.IPAddress) string {
    85  	return instance.SelectPublicAddress(convertNovaAddresses(addresses))
    86  }
    87  
    88  var indexData = `
    89  		{
    90  		 "index": {
    91  		  "com.ubuntu.cloud:released:openstack": {
    92  		   "updated": "Wed, 01 May 2013 13:31:26 +0000",
    93  		   "clouds": [
    94  			{
    95  			 "region": "{{.Region}}",
    96  			 "endpoint": "{{.URL}}"
    97  			}
    98  		   ],
    99  		   "cloudname": "test",
   100  		   "datatype": "image-ids",
   101  		   "format": "products:1.0",
   102  		   "products": [
   103  			"com.ubuntu.cloud:server:12.04:amd64",
   104  			"com.ubuntu.cloud:server:12.10:amd64",
   105  			"com.ubuntu.cloud:server:13.04:amd64"
   106  		   ],
   107  		   "path": "image-metadata/products.json"
   108  		  }
   109  		 },
   110  		 "updated": "Wed, 01 May 2013 13:31:26 +0000",
   111  		 "format": "index:1.0"
   112  		}
   113  `
   114  
   115  var imagesData = `
   116  {
   117   "content_id": "com.ubuntu.cloud:released:openstack",
   118   "products": {
   119     "com.ubuntu.cloud:server:12.04:amd64": {
   120       "release": "precise",
   121       "version": "12.04",
   122       "arch": "amd64",
   123       "versions": {
   124         "20121218": {
   125           "items": {
   126             "inst1": {
   127               "root_store": "ebs",
   128               "virt": "pv",
   129               "region": "some-region",
   130               "id": "1"
   131             },
   132             "inst2": {
   133               "root_store": "ebs",
   134               "virt": "pv",
   135               "region": "another-region",
   136               "id": "2"
   137             }
   138           },
   139           "pubname": "ubuntu-precise-12.04-amd64-server-20121218",
   140           "label": "release"
   141         },
   142         "20121111": {
   143           "items": {
   144             "inst3": {
   145               "root_store": "ebs",
   146               "virt": "pv",
   147               "region": "some-region",
   148               "id": "3"
   149             }
   150           },
   151           "pubname": "ubuntu-precise-12.04-amd64-server-20121111",
   152           "label": "release"
   153         }
   154       }
   155     },
   156     "com.ubuntu.cloud:server:12.10:amd64": {
   157       "release": "quantal",
   158       "version": "12.10",
   159       "arch": "amd64",
   160       "versions": {
   161         "20121218": {
   162           "items": {
   163             "inst3": {
   164               "root_store": "ebs",
   165               "virt": "pv",
   166               "region": "region-1",
   167               "id": "id-1"
   168             },
   169             "inst4": {
   170               "root_store": "ebs",
   171               "virt": "pv",
   172               "region": "region-2",
   173               "id": "id-2"
   174             }
   175           },
   176           "pubname": "ubuntu-quantal-12.14-amd64-server-20121218",
   177           "label": "release"
   178         }
   179       }
   180     },
   181     "com.ubuntu.cloud:server:13.04:amd64": {
   182       "release": "raring",
   183       "version": "13.04",
   184       "arch": "amd64",
   185       "versions": {
   186         "20121218": {
   187           "items": {
   188             "inst5": {
   189               "root_store": "ebs",
   190               "virt": "pv",
   191               "region": "some-region",
   192               "id": "id-y"
   193             },
   194             "inst6": {
   195               "root_store": "ebs",
   196               "virt": "pv",
   197               "region": "another-region",
   198               "id": "id-z"
   199             }
   200           },
   201           "pubname": "ubuntu-raring-13.04-amd64-server-20121218",
   202           "label": "release"
   203         }
   204       }
   205     }
   206   },
   207   "format": "products:1.0"
   208  }
   209  `
   210  
   211  const productMetadatafile = "image-metadata/products.json"
   212  
   213  func UseTestImageData(stor storage.Storage, cred *identity.Credentials) {
   214  	// Put some image metadata files into the public storage.
   215  	t := template.Must(template.New("").Parse(indexData))
   216  	var metadata bytes.Buffer
   217  	if err := t.Execute(&metadata, cred); err != nil {
   218  		panic(fmt.Errorf("cannot generate index metdata: %v", err))
   219  	}
   220  	data := metadata.Bytes()
   221  	stor.Put(simplestreams.DefaultIndexPath+".json", bytes.NewReader(data), int64(len(data)))
   222  	stor.Put(
   223  		productMetadatafile, strings.NewReader(imagesData), int64(len(imagesData)))
   224  }
   225  
   226  func RemoveTestImageData(stor storage.Storage) {
   227  	stor.Remove(simplestreams.DefaultIndexPath + ".json")
   228  	stor.Remove(productMetadatafile)
   229  }
   230  
   231  // DiscardSecurityGroup cleans up a security group, it is not an error to
   232  // delete something that doesn't exist.
   233  func DiscardSecurityGroup(e environs.Environ, name string) error {
   234  	env := e.(*environ)
   235  	novaClient := env.nova()
   236  	group, err := novaClient.SecurityGroupByName(name)
   237  	if err != nil {
   238  		if errors.IsNotFound(err) {
   239  			// Group already deleted, done
   240  			return nil
   241  		}
   242  	}
   243  	err = novaClient.DeleteSecurityGroup(group.Id)
   244  	if err != nil {
   245  		return err
   246  	}
   247  	return nil
   248  }
   249  
   250  func FindInstanceSpec(e environs.Environ, series, arch, cons string) (spec *instances.InstanceSpec, err error) {
   251  	env := e.(*environ)
   252  	spec, err = findInstanceSpec(env, &instances.InstanceConstraint{
   253  		Series:      series,
   254  		Arches:      []string{arch},
   255  		Region:      env.ecfg().region(),
   256  		Constraints: constraints.MustParse(cons),
   257  	})
   258  	return
   259  }
   260  
   261  func ControlBucketName(e environs.Environ) string {
   262  	env := e.(*environ)
   263  	return env.ecfg().controlBucket()
   264  }
   265  
   266  func GetSwiftURL(e environs.Environ) (string, error) {
   267  	return e.(*environ).client.MakeServiceURL("object-store", nil)
   268  }
   269  
   270  func SetUseFloatingIP(e environs.Environ, val bool) {
   271  	env := e.(*environ)
   272  	env.ecfg().attrs["use-floating-ip"] = val
   273  }
   274  
   275  func SetUpGlobalGroup(e environs.Environ, name string, statePort, apiPort int) (nova.SecurityGroup, error) {
   276  	return e.(*environ).setUpGlobalGroup(name, statePort, apiPort)
   277  }
   278  
   279  func EnsureGroup(e environs.Environ, name string, rules []nova.RuleInfo) (nova.SecurityGroup, error) {
   280  	return e.(*environ).ensureGroup(name, rules)
   281  }
   282  
   283  func CollectInstances(e environs.Environ, ids []instance.Id, out map[instance.Id]instance.Instance) []instance.Id {
   284  	return e.(*environ).collectInstances(ids, out)
   285  }
   286  
   287  // ImageMetadataStorage returns a Storage object pointing where the goose
   288  // infrastructure sets up its keystone entry for image metadata
   289  func ImageMetadataStorage(e environs.Environ) storage.Storage {
   290  	env := e.(*environ)
   291  	return &openstackstorage{
   292  		containerName: "imagemetadata",
   293  		swift:         swift.New(env.client),
   294  	}
   295  }
   296  
   297  // CreateCustomStorage creates a swift container and returns the Storage object
   298  // so you can put data into it.
   299  func CreateCustomStorage(e environs.Environ, containerName string) storage.Storage {
   300  	env := e.(*environ)
   301  	swiftClient := swift.New(env.client)
   302  	if err := swiftClient.CreateContainer(containerName, swift.PublicRead); err != nil {
   303  		panic(err)
   304  	}
   305  	return &openstackstorage{
   306  		containerName: containerName,
   307  		swift:         swiftClient,
   308  	}
   309  }
   310  
   311  func GetNovaClient(e environs.Environ) *nova.Client {
   312  	return e.(*environ).nova()
   313  }
   314  
   315  // ResolveNetwork exposes environ helper function resolveNetwork for testing
   316  func ResolveNetwork(e environs.Environ, networkName string) (string, error) {
   317  	return e.(*environ).resolveNetwork(networkName)
   318  }