Create server to get details of if no other available.
If you attempted to run 03-get-server-details.go on a cloud account
without a pre-existing cloud server, it would fail. Clearly, this isn't
intended, as it doesn't exercise the get-server-details functionality.
I alter the code, as a last resort, create a new server.
We check first to see if a -i parameter has been set, and if so, we use
it directly. Otherwise, we attempt to list servers available for the
user, and if at least one exists, we pick the first one we find. Only
if those two conditions fail do we attempt to create a new server.
diff --git a/acceptance/03-get-server-details.go b/acceptance/03-get-server-details.go
index 3fda268..77fa522 100644
--- a/acceptance/03-get-server-details.go
+++ b/acceptance/03-get-server-details.go
@@ -15,20 +15,26 @@
withIdentity(func(auth gophercloud.AccessProvider) {
withServerApi(auth, func(servers gophercloud.CloudServersProvider) {
- serverId := ""
+ var (
+ err error
+ serverId string
+ deleteAfterwards bool
+ )
+
+ // Figure out which server to provide server details for.
if *id == "" {
- ss, err := servers.ListServers()
+ deleteAfterwards, serverId, err = locateAServer(servers)
if err != nil {
panic(err)
}
- // We could just cheat and dump the server details from ss[0].
- // But, that tests ListServers(), and not ServerById(). So, we
- // elect not to cheat.
- serverId = ss[0].Id
+ if deleteAfterwards {
+ defer servers.DeleteServerById(serverId)
+ }
} else {
serverId = *id
}
+ // Grab server details by ID, and provide a report.
s, err := servers.ServerById(serverId)
if err != nil {
panic(err)
@@ -75,3 +81,30 @@
})
})
}
+
+// locateAServer queries the set of servers owned by the user. If at least one
+// exists, the first found is picked, and its ID is returned. Otherwise, a new
+// server will be created, and its ID returned.
+//
+// deleteAfter will be true if the caller should schedule a call to DeleteServerById()
+// to clean up.
+func locateAServer(servers gophercloud.CloudServersProvider) (deleteAfter bool, id string, err error) {
+ ss, err := servers.ListServers()
+ if err != nil {
+ return false, "", err
+ }
+
+ if len(ss) > 0 {
+ // We could just cheat and dump the server details from ss[0].
+ // But, that tests ListServers(), and not ServerById(). So, we
+ // elect not to cheat.
+ return false, ss[0].Id, nil
+ }
+
+ serverId, err := createServer(servers, "", "", "", "")
+ if err != nil {
+ return false, "", err
+ }
+ err = waitForServerState(servers, serverId, "ACTIVE")
+ return true, serverId, err
+}
\ No newline at end of file
diff --git a/acceptance/libargs.go b/acceptance/libargs.go
index 5daea21..d9eae11 100644
--- a/acceptance/libargs.go
+++ b/acceptance/libargs.go
@@ -5,6 +5,7 @@
"os"
"crypto/rand"
"github.com/rackspace/gophercloud"
+ "time"
)
// getCredentials will verify existence of needed credential information
@@ -161,3 +162,20 @@
f(api)
}
+
+// waitForServerState polls, every 10 seconds, for a given server to appear in the indicated state.
+// This call will block forever if it never appears in the desired state, so if a timeout is required,
+// make sure to call this function in a goroutine.
+func waitForServerState(api gophercloud.CloudServersProvider, id, state string) error {
+ for {
+ s, err := api.ServerById(id)
+ if err != nil {
+ return err
+ }
+ if s.Status == state {
+ return nil
+ }
+ time.Sleep(10 * time.Second)
+ }
+ panic("Impossible")
+}
\ No newline at end of file