Move to vendor

As we walk away from 1.4, godep no longer requires to have stuff into workspace and we no longer need the symlink.

Signed-off-by: Olivier Gambier <olivier@docker.com>
This commit is contained in:
Olivier Gambier
2015-11-03 21:14:39 -08:00
parent b3e83da3e6
commit c9117af080
1059 changed files with 0 additions and 1 deletions

View File

@@ -0,0 +1,7 @@
// Package images provides information and interaction with the image API
// resource in the OpenStack Compute service.
//
// An image is a collection of files used to create or rebuild a server.
// Operators provide a number of pre-built OS images by default. You may also
// create custom images from cloud servers you have launched.
package images

View File

@@ -0,0 +1,65 @@
package images
import (
"github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/pagination"
)
// ListOptsBuilder allows extensions to add additional parameters to the
// List request.
type ListOptsBuilder interface {
ToImageListQuery() (string, error)
}
// ListOpts contain options for limiting the number of Images returned from a call to ListDetail.
type ListOpts struct {
// When the image last changed status (in date-time format).
ChangesSince string `q:"changes-since"`
// The number of Images to return.
Limit int `q:"limit"`
// UUID of the Image at which to set a marker.
Marker string `q:"marker"`
// The name of the Image.
Name string `q:"name"`
// The name of the Server (in URL format).
Server string `q:"server"`
// The current status of the Image.
Status string `q:"status"`
// The value of the type of image (e.g. BASE, SERVER, ALL)
Type string `q:"type"`
}
// ToImageListQuery formats a ListOpts into a query string.
func (opts ListOpts) ToImageListQuery() (string, error) {
q, err := gophercloud.BuildQueryString(opts)
if err != nil {
return "", err
}
return q.String(), nil
}
// ListDetail enumerates the available images.
func ListDetail(client *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager {
url := listDetailURL(client)
if opts != nil {
query, err := opts.ToImageListQuery()
if err != nil {
return pagination.Pager{Err: err}
}
url += query
}
createPage := func(r pagination.PageResult) pagination.Page {
return ImagePage{pagination.LinkedPageBase{PageResult: r}}
}
return pagination.NewPager(client, url, createPage)
}
// Get acquires additional detail about a specific image by ID.
// Use ExtractImage() to interpret the result as an openstack Image.
func Get(client *gophercloud.ServiceClient, id string) GetResult {
var result GetResult
_, result.Err = client.Get(getURL(client, id), &result.Body, nil)
return result
}

View File

@@ -0,0 +1,175 @@
package images
import (
"encoding/json"
"fmt"
"net/http"
"reflect"
"testing"
"github.com/rackspace/gophercloud/pagination"
th "github.com/rackspace/gophercloud/testhelper"
fake "github.com/rackspace/gophercloud/testhelper/client"
)
func TestListImages(t *testing.T) {
th.SetupHTTP()
defer th.TeardownHTTP()
th.Mux.HandleFunc("/images/detail", func(w http.ResponseWriter, r *http.Request) {
th.TestMethod(t, r, "GET")
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
w.Header().Add("Content-Type", "application/json")
r.ParseForm()
marker := r.Form.Get("marker")
switch marker {
case "":
fmt.Fprintf(w, `
{
"images": [
{
"status": "ACTIVE",
"updated": "2014-09-23T12:54:56Z",
"id": "f3e4a95d-1f4f-4989-97ce-f3a1fb8c04d7",
"OS-EXT-IMG-SIZE:size": 476704768,
"name": "F17-x86_64-cfntools",
"created": "2014-09-23T12:54:52Z",
"minDisk": 0,
"progress": 100,
"minRam": 0,
"metadata": {}
},
{
"status": "ACTIVE",
"updated": "2014-09-23T12:51:43Z",
"id": "f90f6034-2570-4974-8351-6b49732ef2eb",
"OS-EXT-IMG-SIZE:size": 13167616,
"name": "cirros-0.3.2-x86_64-disk",
"created": "2014-09-23T12:51:42Z",
"minDisk": 0,
"progress": 100,
"minRam": 0,
"metadata": {}
}
]
}
`)
case "2":
fmt.Fprintf(w, `{ "images": [] }`)
default:
t.Fatalf("Unexpected marker: [%s]", marker)
}
})
pages := 0
options := &ListOpts{Limit: 2}
err := ListDetail(fake.ServiceClient(), options).EachPage(func(page pagination.Page) (bool, error) {
pages++
actual, err := ExtractImages(page)
if err != nil {
return false, err
}
expected := []Image{
Image{
ID: "f3e4a95d-1f4f-4989-97ce-f3a1fb8c04d7",
Name: "F17-x86_64-cfntools",
Created: "2014-09-23T12:54:52Z",
Updated: "2014-09-23T12:54:56Z",
MinDisk: 0,
MinRAM: 0,
Progress: 100,
Status: "ACTIVE",
},
Image{
ID: "f90f6034-2570-4974-8351-6b49732ef2eb",
Name: "cirros-0.3.2-x86_64-disk",
Created: "2014-09-23T12:51:42Z",
Updated: "2014-09-23T12:51:43Z",
MinDisk: 0,
MinRAM: 0,
Progress: 100,
Status: "ACTIVE",
},
}
if !reflect.DeepEqual(expected, actual) {
t.Errorf("Unexpected page contents: expected %#v, got %#v", expected, actual)
}
return false, nil
})
if err != nil {
t.Fatalf("EachPage error: %v", err)
}
if pages != 1 {
t.Errorf("Expected one page, got %d", pages)
}
}
func TestGetImage(t *testing.T) {
th.SetupHTTP()
defer th.TeardownHTTP()
th.Mux.HandleFunc("/images/12345678", func(w http.ResponseWriter, r *http.Request) {
th.TestMethod(t, r, "GET")
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
w.Header().Add("Content-Type", "application/json")
fmt.Fprintf(w, `
{
"image": {
"status": "ACTIVE",
"updated": "2014-09-23T12:54:56Z",
"id": "f3e4a95d-1f4f-4989-97ce-f3a1fb8c04d7",
"OS-EXT-IMG-SIZE:size": 476704768,
"name": "F17-x86_64-cfntools",
"created": "2014-09-23T12:54:52Z",
"minDisk": 0,
"progress": 100,
"minRam": 0,
"metadata": {}
}
}
`)
})
actual, err := Get(fake.ServiceClient(), "12345678").Extract()
if err != nil {
t.Fatalf("Unexpected error from Get: %v", err)
}
expected := &Image{
Status: "ACTIVE",
Updated: "2014-09-23T12:54:56Z",
ID: "f3e4a95d-1f4f-4989-97ce-f3a1fb8c04d7",
Name: "F17-x86_64-cfntools",
Created: "2014-09-23T12:54:52Z",
MinDisk: 0,
Progress: 100,
MinRAM: 0,
}
if !reflect.DeepEqual(expected, actual) {
t.Errorf("Expected %#v, but got %#v", expected, actual)
}
}
func TestNextPageURL(t *testing.T) {
var page ImagePage
var body map[string]interface{}
bodyString := []byte(`{"images":{"links":[{"href":"http://192.154.23.87/12345/images/image3","rel":"bookmark"}]}, "images_links":[{"href":"http://192.154.23.87/12345/images/image4","rel":"next"}]}`)
err := json.Unmarshal(bodyString, &body)
if err != nil {
t.Fatalf("Error unmarshaling data into page body: %v", err)
}
page.Body = body
expected := "http://192.154.23.87/12345/images/image4"
actual, err := page.NextPageURL()
th.AssertNoErr(t, err)
th.CheckEquals(t, expected, actual)
}

View File

@@ -0,0 +1,90 @@
package images
import (
"github.com/mitchellh/mapstructure"
"github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/pagination"
)
// GetResult temporarily stores a Get response.
type GetResult struct {
gophercloud.Result
}
// Extract interprets a GetResult as an Image.
func (gr GetResult) Extract() (*Image, error) {
if gr.Err != nil {
return nil, gr.Err
}
var decoded struct {
Image Image `mapstructure:"image"`
}
err := mapstructure.Decode(gr.Body, &decoded)
return &decoded.Image, err
}
// Image is used for JSON (un)marshalling.
// It provides a description of an OS image.
type Image struct {
// ID contains the image's unique identifier.
ID string
Created string
// MinDisk and MinRAM specify the minimum resources a server must provide to be able to install the image.
MinDisk int
MinRAM int
// Name provides a human-readable moniker for the OS image.
Name string
// The Progress and Status fields indicate image-creation status.
// Any usable image will have 100% progress.
Progress int
Status string
Updated string
}
// ImagePage contains a single page of results from a List operation.
// Use ExtractImages to convert it into a slice of usable structs.
type ImagePage struct {
pagination.LinkedPageBase
}
// IsEmpty returns true if a page contains no Image results.
func (page ImagePage) IsEmpty() (bool, error) {
images, err := ExtractImages(page)
if err != nil {
return true, err
}
return len(images) == 0, nil
}
// NextPageURL uses the response's embedded link reference to navigate to the next page of results.
func (page ImagePage) NextPageURL() (string, error) {
type resp struct {
Links []gophercloud.Link `mapstructure:"images_links"`
}
var r resp
err := mapstructure.Decode(page.Body, &r)
if err != nil {
return "", err
}
return gophercloud.ExtractNextURL(r.Links)
}
// ExtractImages converts a page of List results into a slice of usable Image structs.
func ExtractImages(page pagination.Page) ([]Image, error) {
casted := page.(ImagePage).Body
var results struct {
Images []Image `mapstructure:"images"`
}
err := mapstructure.Decode(casted, &results)
return results.Images, err
}

View File

@@ -0,0 +1,11 @@
package images
import "github.com/rackspace/gophercloud"
func listDetailURL(client *gophercloud.ServiceClient) string {
return client.ServiceURL("images", "detail")
}
func getURL(client *gophercloud.ServiceClient, id string) string {
return client.ServiceURL("images", id)
}

View File

@@ -0,0 +1,26 @@
package images
import (
"testing"
"github.com/rackspace/gophercloud"
th "github.com/rackspace/gophercloud/testhelper"
)
const endpoint = "http://localhost:57909/"
func endpointClient() *gophercloud.ServiceClient {
return &gophercloud.ServiceClient{Endpoint: endpoint}
}
func TestGetURL(t *testing.T) {
actual := getURL(endpointClient(), "foo")
expected := endpoint + "images/foo"
th.CheckEquals(t, expected, actual)
}
func TestListDetailURL(t *testing.T) {
actual := listDetailURL(endpointClient())
expected := endpoint + "images/detail"
th.CheckEquals(t, expected, actual)
}