| package main |
| |
| import ( |
| "fmt" |
| "os" |
| "crypto/rand" |
| "github.com/rackspace/gophercloud" |
| ) |
| |
| // getCredentials will verify existence of needed credential information |
| // provided through environment variables. This function will not return |
| // if at least one piece of required information is missing. |
| func getCredentials() (provider, username, password string) { |
| provider = os.Getenv("SDK_PROVIDER") |
| username = os.Getenv("SDK_USERNAME") |
| password = os.Getenv("SDK_PASSWORD") |
| |
| if (provider == "") || (username == "") || (password == "") { |
| fmt.Fprintf(os.Stderr, "One or more of the following environment variables aren't set:\n") |
| fmt.Fprintf(os.Stderr, " SDK_PROVIDER=\"%s\"\n", provider) |
| fmt.Fprintf(os.Stderr, " SDK_USERNAME=\"%s\"\n", username) |
| fmt.Fprintf(os.Stderr, " SDK_PASSWORD=\"%s\"\n", password) |
| os.Exit(1) |
| } |
| |
| return |
| } |
| |
| // randomString generates a string of given length, but random content. |
| // All content will be within the ASCII graphic character set. |
| // (Implementation from Even Shaw's contribution on |
| // http://stackoverflow.com/questions/12771930/what-is-the-fastest-way-to-generate-a-long-random-string-in-go). |
| func randomString(prefix string, n int) string { |
| const alphanum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" |
| var bytes = make([]byte, n) |
| rand.Read(bytes) |
| for i, b := range bytes { |
| bytes[i] = alphanum[b % byte(len(alphanum))] |
| } |
| return prefix + string(bytes) |
| } |
| |
| // aSuitableImage finds a minimal image for use in dynamically creating servers. |
| // If none can be found, this function will panic. |
| func aSuitableImage(api gophercloud.CloudServersProvider) string { |
| images, err := api.ListImages() |
| if err != nil { |
| panic(err) |
| } |
| |
| // TODO(sfalvo): |
| // Works for Rackspace, might not work for your provider! |
| // Need to figure out why ListImages() provides 0 values for |
| // Ram and Disk fields. |
| // |
| // Until then, just return Ubuntu 12.04 LTS. |
| for i := 0; i < len(images); i++ { |
| if images[i].Id == "23b564c9-c3e6-49f9-bc68-86c7a9ab5018" { |
| return images[i].Id |
| } |
| } |
| panic("Image 23b564c9-c3e6-49f9-bc68-86c7a9ab5018 (Ubuntu 12.04 LTS) not found.") |
| } |
| |
| // aSuitableFlavor finds the minimum flavor capable of running the test image |
| // chosen by aSuitableImage. If none can be found, this function will panic. |
| func aSuitableFlavor(api gophercloud.CloudServersProvider) string { |
| flavors, err := api.ListFlavors() |
| if err != nil { |
| panic(err) |
| } |
| |
| // TODO(sfalvo): |
| // Works for Rackspace, might not work for your provider! |
| // Need to figure out why ListFlavors() provides 0 values for |
| // Ram and Disk fields. |
| // |
| // Until then, just return Ubuntu 12.04 LTS. |
| for i := 0; i < len(flavors); i++ { |
| if flavors[i].Id == "2" { |
| return flavors[i].Id |
| } |
| } |
| panic("Flavor 2 (512MB 1-core 20GB machine) not found.") |
| } |
| |
| // createServer creates a new server in a manner compatible with acceptance testing. |
| // In particular, it ensures that the name of the server always starts with "ACPTTEST--", |
| // which the delete servers acceptance test relies on to identify servers to delete. |
| // Passing in empty image and flavor references will force the use of reasonable defaults. |
| // An empty name string will result in a dynamically created name prefixed with "ACPTTEST--". |
| // A blank admin password will cause a password to be automatically generated; however, |
| // at present no means of recovering this password exists, as no acceptance tests yet require |
| // this data. |
| func createServer(servers gophercloud.CloudServersProvider, imageRef, flavorRef, name, adminPass string) (string, error) { |
| if imageRef == "" { |
| imageRef = aSuitableImage(servers) |
| } |
| |
| if flavorRef == "" { |
| flavorRef = aSuitableFlavor(servers) |
| } |
| |
| if len(name) < 1 { |
| name = randomString("ACPTTEST", 16) |
| } |
| |
| if (len(name) < 8) || (name[0:8] != "ACPTTEST") { |
| name = fmt.Sprintf("ACPTTEST--%s", name) |
| } |
| |
| newServer, err := servers.CreateServer(gophercloud.NewServer{ |
| Name: name, |
| ImageRef: imageRef, |
| FlavorRef: flavorRef, |
| AdminPass: adminPass, |
| }) |
| |
| if err != nil { |
| return "", err |
| } |
| |
| return newServer.Id, nil |
| } |
| |
| // findAlternativeFlavor locates a flavor to resize a server to. It is guaranteed to be different |
| // than what aSuitableFlavor() returns. If none could be found, this function will panic. |
| func findAlternativeFlavor() string { |
| return "3" // 1GB image, up from 512MB image |
| } |