Remove unused dependencies; see godep v54
This commit is contained in:
parent
484404f223
commit
588f9f30b2
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/mitchellh/packer",
|
"ImportPath": "github.com/mitchellh/packer",
|
||||||
"GoVersion": "go1.5",
|
"GoVersion": "go1.6",
|
||||||
"Deps": [
|
"Deps": [
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/ActiveState/tail",
|
"ImportPath": "github.com/ActiveState/tail",
|
||||||
|
@ -16,6 +16,61 @@
|
||||||
"Comment": "v1.1.2",
|
"Comment": "v1.1.2",
|
||||||
"Rev": "8041be5461786460d86b4358305fbdf32d37cfb2"
|
"Rev": "8041be5461786460d86b4358305fbdf32d37cfb2"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/aws/aws-sdk-go/aws/awserr",
|
||||||
|
"Comment": "v1.1.2",
|
||||||
|
"Rev": "8041be5461786460d86b4358305fbdf32d37cfb2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/aws/aws-sdk-go/aws/awsutil",
|
||||||
|
"Comment": "v1.1.2",
|
||||||
|
"Rev": "8041be5461786460d86b4358305fbdf32d37cfb2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/aws/aws-sdk-go/aws/client",
|
||||||
|
"Comment": "v1.1.2",
|
||||||
|
"Rev": "8041be5461786460d86b4358305fbdf32d37cfb2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/aws/aws-sdk-go/aws/client/metadata",
|
||||||
|
"Comment": "v1.1.2",
|
||||||
|
"Rev": "8041be5461786460d86b4358305fbdf32d37cfb2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/aws/aws-sdk-go/aws/corehandlers",
|
||||||
|
"Comment": "v1.1.2",
|
||||||
|
"Rev": "8041be5461786460d86b4358305fbdf32d37cfb2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/aws/aws-sdk-go/aws/credentials",
|
||||||
|
"Comment": "v1.1.2",
|
||||||
|
"Rev": "8041be5461786460d86b4358305fbdf32d37cfb2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds",
|
||||||
|
"Comment": "v1.1.2",
|
||||||
|
"Rev": "8041be5461786460d86b4358305fbdf32d37cfb2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/aws/aws-sdk-go/aws/defaults",
|
||||||
|
"Comment": "v1.1.2",
|
||||||
|
"Rev": "8041be5461786460d86b4358305fbdf32d37cfb2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/aws/aws-sdk-go/aws/ec2metadata",
|
||||||
|
"Comment": "v1.1.2",
|
||||||
|
"Rev": "8041be5461786460d86b4358305fbdf32d37cfb2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/aws/aws-sdk-go/aws/request",
|
||||||
|
"Comment": "v1.1.2",
|
||||||
|
"Rev": "8041be5461786460d86b4358305fbdf32d37cfb2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/aws/aws-sdk-go/aws/session",
|
||||||
|
"Comment": "v1.1.2",
|
||||||
|
"Rev": "8041be5461786460d86b4358305fbdf32d37cfb2"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/private/endpoints",
|
"ImportPath": "github.com/aws/aws-sdk-go/private/endpoints",
|
||||||
"Comment": "v1.1.2",
|
"Comment": "v1.1.2",
|
||||||
|
@ -26,6 +81,36 @@
|
||||||
"Comment": "v1.1.2",
|
"Comment": "v1.1.2",
|
||||||
"Rev": "8041be5461786460d86b4358305fbdf32d37cfb2"
|
"Rev": "8041be5461786460d86b4358305fbdf32d37cfb2"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/aws/aws-sdk-go/private/protocol/ec2query",
|
||||||
|
"Comment": "v1.1.2",
|
||||||
|
"Rev": "8041be5461786460d86b4358305fbdf32d37cfb2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/aws/aws-sdk-go/private/protocol/query",
|
||||||
|
"Comment": "v1.1.2",
|
||||||
|
"Rev": "8041be5461786460d86b4358305fbdf32d37cfb2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/aws/aws-sdk-go/private/protocol/query/queryutil",
|
||||||
|
"Comment": "v1.1.2",
|
||||||
|
"Rev": "8041be5461786460d86b4358305fbdf32d37cfb2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/aws/aws-sdk-go/private/protocol/rest",
|
||||||
|
"Comment": "v1.1.2",
|
||||||
|
"Rev": "8041be5461786460d86b4358305fbdf32d37cfb2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/aws/aws-sdk-go/private/protocol/restxml",
|
||||||
|
"Comment": "v1.1.2",
|
||||||
|
"Rev": "8041be5461786460d86b4358305fbdf32d37cfb2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil",
|
||||||
|
"Comment": "v1.1.2",
|
||||||
|
"Rev": "8041be5461786460d86b4358305fbdf32d37cfb2"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/private/signer/v4",
|
"ImportPath": "github.com/aws/aws-sdk-go/private/signer/v4",
|
||||||
"Comment": "v1.1.2",
|
"Comment": "v1.1.2",
|
||||||
|
@ -46,6 +131,16 @@
|
||||||
"Comment": "v1.1.2",
|
"Comment": "v1.1.2",
|
||||||
"Rev": "8041be5461786460d86b4358305fbdf32d37cfb2"
|
"Rev": "8041be5461786460d86b4358305fbdf32d37cfb2"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/aws/aws-sdk-go/service/s3/s3iface",
|
||||||
|
"Comment": "v1.1.2",
|
||||||
|
"Rev": "8041be5461786460d86b4358305fbdf32d37cfb2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/aws/aws-sdk-go/service/s3/s3manager",
|
||||||
|
"Comment": "v1.1.2",
|
||||||
|
"Rev": "8041be5461786460d86b4358305fbdf32d37cfb2"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/service/sts",
|
"ImportPath": "github.com/aws/aws-sdk-go/service/sts",
|
||||||
"Comment": "v1.1.2",
|
"Comment": "v1.1.2",
|
||||||
|
@ -192,6 +287,10 @@
|
||||||
"ImportPath": "github.com/mitchellh/go-fs",
|
"ImportPath": "github.com/mitchellh/go-fs",
|
||||||
"Rev": "a34c1b9334e86165685a9449b782f20465eb8c69"
|
"Rev": "a34c1b9334e86165685a9449b782f20465eb8c69"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/mitchellh/go-fs/fat",
|
||||||
|
"Rev": "a34c1b9334e86165685a9449b782f20465eb8c69"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/mitchellh/go-homedir",
|
"ImportPath": "github.com/mitchellh/go-homedir",
|
||||||
"Rev": "d682a8f0cf139663a984ff12528da460ca963de9"
|
"Rev": "d682a8f0cf139663a984ff12528da460ca963de9"
|
||||||
|
@ -249,6 +348,86 @@
|
||||||
"Comment": "v1.0.0-810-g53d1dc4",
|
"Comment": "v1.0.0-810-g53d1dc4",
|
||||||
"Rev": "53d1dc4400e1ebcd37a0e01d8c1fe2f4db3b99d2"
|
"Rev": "53d1dc4400e1ebcd37a0e01d8c1fe2f4db3b99d2"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/rackspace/gophercloud/openstack",
|
||||||
|
"Comment": "v1.0.0-810-g53d1dc4",
|
||||||
|
"Rev": "53d1dc4400e1ebcd37a0e01d8c1fe2f4db3b99d2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/rackspace/gophercloud/openstack/common/extensions",
|
||||||
|
"Comment": "v1.0.0-810-g53d1dc4",
|
||||||
|
"Rev": "53d1dc4400e1ebcd37a0e01d8c1fe2f4db3b99d2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/rackspace/gophercloud/openstack/compute/v2/extensions",
|
||||||
|
"Comment": "v1.0.0-810-g53d1dc4",
|
||||||
|
"Rev": "53d1dc4400e1ebcd37a0e01d8c1fe2f4db3b99d2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/floatingip",
|
||||||
|
"Comment": "v1.0.0-810-g53d1dc4",
|
||||||
|
"Rev": "53d1dc4400e1ebcd37a0e01d8c1fe2f4db3b99d2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs",
|
||||||
|
"Comment": "v1.0.0-810-g53d1dc4",
|
||||||
|
"Rev": "53d1dc4400e1ebcd37a0e01d8c1fe2f4db3b99d2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/startstop",
|
||||||
|
"Comment": "v1.0.0-810-g53d1dc4",
|
||||||
|
"Rev": "53d1dc4400e1ebcd37a0e01d8c1fe2f4db3b99d2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/rackspace/gophercloud/openstack/compute/v2/flavors",
|
||||||
|
"Comment": "v1.0.0-810-g53d1dc4",
|
||||||
|
"Rev": "53d1dc4400e1ebcd37a0e01d8c1fe2f4db3b99d2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/rackspace/gophercloud/openstack/compute/v2/images",
|
||||||
|
"Comment": "v1.0.0-810-g53d1dc4",
|
||||||
|
"Rev": "53d1dc4400e1ebcd37a0e01d8c1fe2f4db3b99d2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/rackspace/gophercloud/openstack/compute/v2/servers",
|
||||||
|
"Comment": "v1.0.0-810-g53d1dc4",
|
||||||
|
"Rev": "53d1dc4400e1ebcd37a0e01d8c1fe2f4db3b99d2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/rackspace/gophercloud/openstack/identity/v2/tenants",
|
||||||
|
"Comment": "v1.0.0-810-g53d1dc4",
|
||||||
|
"Rev": "53d1dc4400e1ebcd37a0e01d8c1fe2f4db3b99d2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/rackspace/gophercloud/openstack/identity/v2/tokens",
|
||||||
|
"Comment": "v1.0.0-810-g53d1dc4",
|
||||||
|
"Rev": "53d1dc4400e1ebcd37a0e01d8c1fe2f4db3b99d2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/rackspace/gophercloud/openstack/identity/v3/tokens",
|
||||||
|
"Comment": "v1.0.0-810-g53d1dc4",
|
||||||
|
"Rev": "53d1dc4400e1ebcd37a0e01d8c1fe2f4db3b99d2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/rackspace/gophercloud/openstack/utils",
|
||||||
|
"Comment": "v1.0.0-810-g53d1dc4",
|
||||||
|
"Rev": "53d1dc4400e1ebcd37a0e01d8c1fe2f4db3b99d2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/rackspace/gophercloud/pagination",
|
||||||
|
"Comment": "v1.0.0-810-g53d1dc4",
|
||||||
|
"Rev": "53d1dc4400e1ebcd37a0e01d8c1fe2f4db3b99d2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/rackspace/gophercloud/testhelper",
|
||||||
|
"Comment": "v1.0.0-810-g53d1dc4",
|
||||||
|
"Rev": "53d1dc4400e1ebcd37a0e01d8c1fe2f4db3b99d2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/rackspace/gophercloud/testhelper/client",
|
||||||
|
"Comment": "v1.0.0-810-g53d1dc4",
|
||||||
|
"Rev": "53d1dc4400e1ebcd37a0e01d8c1fe2f4db3b99d2"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/satori/go.uuid",
|
"ImportPath": "github.com/satori/go.uuid",
|
||||||
"Rev": "d41af8bb6a7704f00bc3b7cba9355ae6a5a80048"
|
"Rev": "d41af8bb6a7704f00bc3b7cba9355ae6a5a80048"
|
||||||
|
@ -269,18 +448,46 @@
|
||||||
"ImportPath": "golang.org/x/crypto/ssh",
|
"ImportPath": "golang.org/x/crypto/ssh",
|
||||||
"Rev": "1f22c0103821b9390939b6776727195525381532"
|
"Rev": "1f22c0103821b9390939b6776727195525381532"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "golang.org/x/crypto/ssh/agent",
|
||||||
|
"Rev": "1f22c0103821b9390939b6776727195525381532"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "golang.org/x/net/context",
|
"ImportPath": "golang.org/x/net/context",
|
||||||
"Rev": "6ccd6698c634f5d835c40c1c31848729e0cecda1"
|
"Rev": "6ccd6698c634f5d835c40c1c31848729e0cecda1"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "golang.org/x/net/context/ctxhttp",
|
||||||
|
"Rev": "6ccd6698c634f5d835c40c1c31848729e0cecda1"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "golang.org/x/net/html",
|
"ImportPath": "golang.org/x/net/html",
|
||||||
"Rev": "6ccd6698c634f5d835c40c1c31848729e0cecda1"
|
"Rev": "6ccd6698c634f5d835c40c1c31848729e0cecda1"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "golang.org/x/net/html/atom",
|
||||||
|
"Rev": "6ccd6698c634f5d835c40c1c31848729e0cecda1"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "golang.org/x/oauth2",
|
"ImportPath": "golang.org/x/oauth2",
|
||||||
"Rev": "8a57ed94ffd43444c0879fe75701732a38afc985"
|
"Rev": "8a57ed94ffd43444c0879fe75701732a38afc985"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "golang.org/x/oauth2/google",
|
||||||
|
"Rev": "8a57ed94ffd43444c0879fe75701732a38afc985"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "golang.org/x/oauth2/internal",
|
||||||
|
"Rev": "8a57ed94ffd43444c0879fe75701732a38afc985"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "golang.org/x/oauth2/jws",
|
||||||
|
"Rev": "8a57ed94ffd43444c0879fe75701732a38afc985"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "golang.org/x/oauth2/jwt",
|
||||||
|
"Rev": "8a57ed94ffd43444c0879fe75701732a38afc985"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "golang.org/x/sys/unix",
|
"ImportPath": "golang.org/x/sys/unix",
|
||||||
"Rev": "50c6bc5e4292a1d4e65c6e9be5f53be28bcbe28e"
|
"Rev": "50c6bc5e4292a1d4e65c6e9be5f53be28bcbe28e"
|
||||||
|
@ -297,10 +504,42 @@
|
||||||
"ImportPath": "google.golang.org/api/googleapi",
|
"ImportPath": "google.golang.org/api/googleapi",
|
||||||
"Rev": "ddff2aff599105a55549cf173852507dfa094b7f"
|
"Rev": "ddff2aff599105a55549cf173852507dfa094b7f"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "google.golang.org/api/googleapi/internal/uritemplates",
|
||||||
|
"Rev": "ddff2aff599105a55549cf173852507dfa094b7f"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "google.golang.org/appengine",
|
"ImportPath": "google.golang.org/appengine",
|
||||||
"Rev": "6bde959377a90acb53366051d7d587bfd7171354"
|
"Rev": "6bde959377a90acb53366051d7d587bfd7171354"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "google.golang.org/appengine/internal",
|
||||||
|
"Rev": "6bde959377a90acb53366051d7d587bfd7171354"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "google.golang.org/appengine/internal/app_identity",
|
||||||
|
"Rev": "6bde959377a90acb53366051d7d587bfd7171354"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "google.golang.org/appengine/internal/base",
|
||||||
|
"Rev": "6bde959377a90acb53366051d7d587bfd7171354"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "google.golang.org/appengine/internal/datastore",
|
||||||
|
"Rev": "6bde959377a90acb53366051d7d587bfd7171354"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "google.golang.org/appengine/internal/log",
|
||||||
|
"Rev": "6bde959377a90acb53366051d7d587bfd7171354"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "google.golang.org/appengine/internal/modules",
|
||||||
|
"Rev": "6bde959377a90acb53366051d7d587bfd7171354"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "google.golang.org/appengine/internal/remote_api",
|
||||||
|
"Rev": "6bde959377a90acb53366051d7d587bfd7171354"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "google.golang.org/cloud/compute/metadata",
|
"ImportPath": "google.golang.org/cloud/compute/metadata",
|
||||||
"Rev": "5a3b06f8b5da3b7c3a93da43163b872c86c509ef"
|
"Rev": "5a3b06f8b5da3b7c3a93da43163b872c86c509ef"
|
||||||
|
|
134
vendor/github.com/aws/aws-sdk-go/aws/credentials/stscreds/assume_role_provider.go
generated
vendored
134
vendor/github.com/aws/aws-sdk-go/aws/credentials/stscreds/assume_role_provider.go
generated
vendored
|
@ -1,134 +0,0 @@
|
||||||
// Package stscreds are credential Providers to retrieve STS AWS credentials.
|
|
||||||
//
|
|
||||||
// STS provides multiple ways to retrieve credentials which can be used when making
|
|
||||||
// future AWS service API operation calls.
|
|
||||||
package stscreds
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/aws/aws-sdk-go/aws"
|
|
||||||
"github.com/aws/aws-sdk-go/aws/client"
|
|
||||||
"github.com/aws/aws-sdk-go/aws/credentials"
|
|
||||||
"github.com/aws/aws-sdk-go/service/sts"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ProviderName provides a name of AssumeRole provider
|
|
||||||
const ProviderName = "AssumeRoleProvider"
|
|
||||||
|
|
||||||
// AssumeRoler represents the minimal subset of the STS client API used by this provider.
|
|
||||||
type AssumeRoler interface {
|
|
||||||
AssumeRole(input *sts.AssumeRoleInput) (*sts.AssumeRoleOutput, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DefaultDuration is the default amount of time in minutes that the credentials
|
|
||||||
// will be valid for.
|
|
||||||
var DefaultDuration = time.Duration(15) * time.Minute
|
|
||||||
|
|
||||||
// AssumeRoleProvider retrieves temporary credentials from the STS service, and
|
|
||||||
// keeps track of their expiration time. This provider must be used explicitly,
|
|
||||||
// as it is not included in the credentials chain.
|
|
||||||
type AssumeRoleProvider struct {
|
|
||||||
credentials.Expiry
|
|
||||||
|
|
||||||
// STS client to make assume role request with.
|
|
||||||
Client AssumeRoler
|
|
||||||
|
|
||||||
// Role to be assumed.
|
|
||||||
RoleARN string
|
|
||||||
|
|
||||||
// Session name, if you wish to reuse the credentials elsewhere.
|
|
||||||
RoleSessionName string
|
|
||||||
|
|
||||||
// Expiry duration of the STS credentials. Defaults to 15 minutes if not set.
|
|
||||||
Duration time.Duration
|
|
||||||
|
|
||||||
// Optional ExternalID to pass along, defaults to nil if not set.
|
|
||||||
ExternalID *string
|
|
||||||
|
|
||||||
// ExpiryWindow will allow the credentials to trigger refreshing prior to
|
|
||||||
// the credentials actually expiring. This is beneficial so race conditions
|
|
||||||
// with expiring credentials do not cause request to fail unexpectedly
|
|
||||||
// due to ExpiredTokenException exceptions.
|
|
||||||
//
|
|
||||||
// So a ExpiryWindow of 10s would cause calls to IsExpired() to return true
|
|
||||||
// 10 seconds before the credentials are actually expired.
|
|
||||||
//
|
|
||||||
// If ExpiryWindow is 0 or less it will be ignored.
|
|
||||||
ExpiryWindow time.Duration
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewCredentials returns a pointer to a new Credentials object wrapping the
|
|
||||||
// AssumeRoleProvider. The credentials will expire every 15 minutes and the
|
|
||||||
// role will be named after a nanosecond timestamp of this operation.
|
|
||||||
//
|
|
||||||
// Takes a Config provider to create the STS client. The ConfigProvider is
|
|
||||||
// satisfied by the session.Session type.
|
|
||||||
func NewCredentials(c client.ConfigProvider, roleARN string, options ...func(*AssumeRoleProvider)) *credentials.Credentials {
|
|
||||||
p := &AssumeRoleProvider{
|
|
||||||
Client: sts.New(c),
|
|
||||||
RoleARN: roleARN,
|
|
||||||
Duration: DefaultDuration,
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, option := range options {
|
|
||||||
option(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
return credentials.NewCredentials(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewCredentialsWithClient returns a pointer to a new Credentials object wrapping the
|
|
||||||
// AssumeRoleProvider. The credentials will expire every 15 minutes and the
|
|
||||||
// role will be named after a nanosecond timestamp of this operation.
|
|
||||||
//
|
|
||||||
// Takes an AssumeRoler which can be satisfiede by the STS client.
|
|
||||||
func NewCredentialsWithClient(svc AssumeRoler, roleARN string, options ...func(*AssumeRoleProvider)) *credentials.Credentials {
|
|
||||||
p := &AssumeRoleProvider{
|
|
||||||
Client: svc,
|
|
||||||
RoleARN: roleARN,
|
|
||||||
Duration: DefaultDuration,
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, option := range options {
|
|
||||||
option(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
return credentials.NewCredentials(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Retrieve generates a new set of temporary credentials using STS.
|
|
||||||
func (p *AssumeRoleProvider) Retrieve() (credentials.Value, error) {
|
|
||||||
|
|
||||||
// Apply defaults where parameters are not set.
|
|
||||||
if p.RoleSessionName == "" {
|
|
||||||
// Try to work out a role name that will hopefully end up unique.
|
|
||||||
p.RoleSessionName = fmt.Sprintf("%d", time.Now().UTC().UnixNano())
|
|
||||||
}
|
|
||||||
if p.Duration == 0 {
|
|
||||||
// Expire as often as AWS permits.
|
|
||||||
p.Duration = DefaultDuration
|
|
||||||
}
|
|
||||||
|
|
||||||
roleOutput, err := p.Client.AssumeRole(&sts.AssumeRoleInput{
|
|
||||||
DurationSeconds: aws.Int64(int64(p.Duration / time.Second)),
|
|
||||||
RoleArn: aws.String(p.RoleARN),
|
|
||||||
RoleSessionName: aws.String(p.RoleSessionName),
|
|
||||||
ExternalId: p.ExternalID,
|
|
||||||
})
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return credentials.Value{ProviderName: ProviderName}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// We will proactively generate new credentials before they expire.
|
|
||||||
p.SetExpiration(*roleOutput.Credentials.Expiration, p.ExpiryWindow)
|
|
||||||
|
|
||||||
return credentials.Value{
|
|
||||||
AccessKeyID: *roleOutput.Credentials.AccessKeyId,
|
|
||||||
SecretAccessKey: *roleOutput.Credentials.SecretAccessKey,
|
|
||||||
SessionToken: *roleOutput.Credentials.SessionToken,
|
|
||||||
ProviderName: ProviderName,
|
|
||||||
}, nil
|
|
||||||
}
|
|
23
vendor/github.com/aws/aws-sdk-go/service/s3/s3manager/s3manageriface/interface.go
generated
vendored
23
vendor/github.com/aws/aws-sdk-go/service/s3/s3manager/s3manageriface/interface.go
generated
vendored
|
@ -1,23 +0,0 @@
|
||||||
// Package s3manageriface provides an interface for the s3manager package
|
|
||||||
package s3manageriface
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
|
|
||||||
"github.com/aws/aws-sdk-go/service/s3"
|
|
||||||
"github.com/aws/aws-sdk-go/service/s3/s3manager"
|
|
||||||
)
|
|
||||||
|
|
||||||
// DownloaderAPI is the interface type for s3manager.Downloader.
|
|
||||||
type DownloaderAPI interface {
|
|
||||||
Download(io.WriterAt, *s3.GetObjectInput, ...func(*s3manager.Downloader)) (int64, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ DownloaderAPI = (*s3manager.Downloader)(nil)
|
|
||||||
|
|
||||||
// UploaderAPI is the interface type for s3manager.Uploader.
|
|
||||||
type UploaderAPI interface {
|
|
||||||
Upload(*s3manager.UploadInput, ...func(*s3manager.Uploader)) (*s3manager.UploadOutput, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ UploaderAPI = (*s3manager.Uploader)(nil)
|
|
3
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/apiversions/doc.go
generated
vendored
3
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/apiversions/doc.go
generated
vendored
|
@ -1,3 +0,0 @@
|
||||||
// Package apiversions provides information and interaction with the different
|
|
||||||
// API versions for the OpenStack Block Storage service, code-named Cinder.
|
|
||||||
package apiversions
|
|
|
@ -1,21 +0,0 @@
|
||||||
package apiversions
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/rackspace/gophercloud"
|
|
||||||
"github.com/rackspace/gophercloud/pagination"
|
|
||||||
)
|
|
||||||
|
|
||||||
// List lists all the Cinder API versions available to end-users.
|
|
||||||
func List(c *gophercloud.ServiceClient) pagination.Pager {
|
|
||||||
return pagination.NewPager(c, listURL(c), func(r pagination.PageResult) pagination.Page {
|
|
||||||
return APIVersionPage{pagination.SinglePageBase(r)}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get will retrieve the volume type with the provided ID. To extract the volume
|
|
||||||
// type from the result, call the Extract method on the GetResult.
|
|
||||||
func Get(client *gophercloud.ServiceClient, v string) GetResult {
|
|
||||||
var res GetResult
|
|
||||||
_, res.Err = client.Get(getURL(client, v), &res.Body, nil)
|
|
||||||
return res
|
|
||||||
}
|
|
58
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/apiversions/results.go
generated
vendored
58
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/apiversions/results.go
generated
vendored
|
@ -1,58 +0,0 @@
|
||||||
package apiversions
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/rackspace/gophercloud"
|
|
||||||
"github.com/rackspace/gophercloud/pagination"
|
|
||||||
|
|
||||||
"github.com/mitchellh/mapstructure"
|
|
||||||
)
|
|
||||||
|
|
||||||
// APIVersion represents an API version for Cinder.
|
|
||||||
type APIVersion struct {
|
|
||||||
ID string `json:"id" mapstructure:"id"` // unique identifier
|
|
||||||
Status string `json:"status" mapstructure:"status"` // current status
|
|
||||||
Updated string `json:"updated" mapstructure:"updated"` // date last updated
|
|
||||||
}
|
|
||||||
|
|
||||||
// APIVersionPage is the page returned by a pager when traversing over a
|
|
||||||
// collection of API versions.
|
|
||||||
type APIVersionPage struct {
|
|
||||||
pagination.SinglePageBase
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsEmpty checks whether an APIVersionPage struct is empty.
|
|
||||||
func (r APIVersionPage) IsEmpty() (bool, error) {
|
|
||||||
is, err := ExtractAPIVersions(r)
|
|
||||||
if err != nil {
|
|
||||||
return true, err
|
|
||||||
}
|
|
||||||
return len(is) == 0, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExtractAPIVersions takes a collection page, extracts all of the elements,
|
|
||||||
// and returns them a slice of APIVersion structs. It is effectively a cast.
|
|
||||||
func ExtractAPIVersions(page pagination.Page) ([]APIVersion, error) {
|
|
||||||
var resp struct {
|
|
||||||
Versions []APIVersion `mapstructure:"versions"`
|
|
||||||
}
|
|
||||||
|
|
||||||
err := mapstructure.Decode(page.(APIVersionPage).Body, &resp)
|
|
||||||
|
|
||||||
return resp.Versions, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetResult represents the result of a get operation.
|
|
||||||
type GetResult struct {
|
|
||||||
gophercloud.Result
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract is a function that accepts a result and extracts an API version resource.
|
|
||||||
func (r GetResult) Extract() (*APIVersion, error) {
|
|
||||||
var resp struct {
|
|
||||||
Version *APIVersion `mapstructure:"version"`
|
|
||||||
}
|
|
||||||
|
|
||||||
err := mapstructure.Decode(r.Body, &resp)
|
|
||||||
|
|
||||||
return resp.Version, err
|
|
||||||
}
|
|
15
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/apiversions/urls.go
generated
vendored
15
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/apiversions/urls.go
generated
vendored
|
@ -1,15 +0,0 @@
|
||||||
package apiversions
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/rackspace/gophercloud"
|
|
||||||
)
|
|
||||||
|
|
||||||
func getURL(c *gophercloud.ServiceClient, version string) string {
|
|
||||||
return c.ServiceURL(strings.TrimRight(version, "/") + "/")
|
|
||||||
}
|
|
||||||
|
|
||||||
func listURL(c *gophercloud.ServiceClient) string {
|
|
||||||
return c.ServiceURL("")
|
|
||||||
}
|
|
5
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/snapshots/doc.go
generated
vendored
5
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/snapshots/doc.go
generated
vendored
|
@ -1,5 +0,0 @@
|
||||||
// Package snapshots provides information and interaction with snapshots in the
|
|
||||||
// OpenStack Block Storage service. A snapshot is a point in time copy of the
|
|
||||||
// data contained in an external storage volume, and can be controlled
|
|
||||||
// programmatically.
|
|
||||||
package snapshots
|
|
114
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/snapshots/fixtures.go
generated
vendored
114
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/snapshots/fixtures.go
generated
vendored
|
@ -1,114 +0,0 @@
|
||||||
package snapshots
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
th "github.com/rackspace/gophercloud/testhelper"
|
|
||||||
fake "github.com/rackspace/gophercloud/testhelper/client"
|
|
||||||
)
|
|
||||||
|
|
||||||
func MockListResponse(t *testing.T) {
|
|
||||||
th.Mux.HandleFunc("/snapshots", 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")
|
|
||||||
w.WriteHeader(http.StatusOK)
|
|
||||||
|
|
||||||
fmt.Fprintf(w, `
|
|
||||||
{
|
|
||||||
"snapshots": [
|
|
||||||
{
|
|
||||||
"id": "289da7f8-6440-407c-9fb4-7db01ec49164",
|
|
||||||
"display_name": "snapshot-001"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "96c3bda7-c82a-4f50-be73-ca7621794835",
|
|
||||||
"display_name": "snapshot-002"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
`)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func MockGetResponse(t *testing.T) {
|
|
||||||
th.Mux.HandleFunc("/snapshots/d32019d3-bc6e-4319-9c1d-6722fc136a22", 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")
|
|
||||||
w.WriteHeader(http.StatusOK)
|
|
||||||
fmt.Fprintf(w, `
|
|
||||||
{
|
|
||||||
"snapshot": {
|
|
||||||
"display_name": "snapshot-001",
|
|
||||||
"id": "d32019d3-bc6e-4319-9c1d-6722fc136a22"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func MockCreateResponse(t *testing.T) {
|
|
||||||
th.Mux.HandleFunc("/snapshots", func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
th.TestMethod(t, r, "POST")
|
|
||||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
|
||||||
th.TestHeader(t, r, "Content-Type", "application/json")
|
|
||||||
th.TestHeader(t, r, "Accept", "application/json")
|
|
||||||
th.TestJSONRequest(t, r, `
|
|
||||||
{
|
|
||||||
"snapshot": {
|
|
||||||
"volume_id": "1234",
|
|
||||||
"display_name": "snapshot-001"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`)
|
|
||||||
|
|
||||||
w.Header().Add("Content-Type", "application/json")
|
|
||||||
w.WriteHeader(http.StatusCreated)
|
|
||||||
|
|
||||||
fmt.Fprintf(w, `
|
|
||||||
{
|
|
||||||
"snapshot": {
|
|
||||||
"volume_id": "1234",
|
|
||||||
"display_name": "snapshot-001",
|
|
||||||
"id": "d32019d3-bc6e-4319-9c1d-6722fc136a22"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func MockUpdateMetadataResponse(t *testing.T) {
|
|
||||||
th.Mux.HandleFunc("/snapshots/123/metadata", func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
th.TestMethod(t, r, "PUT")
|
|
||||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
|
||||||
th.TestHeader(t, r, "Content-Type", "application/json")
|
|
||||||
th.TestJSONRequest(t, r, `
|
|
||||||
{
|
|
||||||
"metadata": {
|
|
||||||
"key": "v1"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`)
|
|
||||||
|
|
||||||
fmt.Fprintf(w, `
|
|
||||||
{
|
|
||||||
"metadata": {
|
|
||||||
"key": "v1"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func MockDeleteResponse(t *testing.T) {
|
|
||||||
th.Mux.HandleFunc("/snapshots/d32019d3-bc6e-4319-9c1d-6722fc136a22", func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
th.TestMethod(t, r, "DELETE")
|
|
||||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
|
||||||
w.WriteHeader(http.StatusNoContent)
|
|
||||||
})
|
|
||||||
}
|
|
206
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/snapshots/requests.go
generated
vendored
206
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/snapshots/requests.go
generated
vendored
|
@ -1,206 +0,0 @@
|
||||||
package snapshots
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/rackspace/gophercloud"
|
|
||||||
"github.com/rackspace/gophercloud/pagination"
|
|
||||||
)
|
|
||||||
|
|
||||||
// CreateOptsBuilder allows extensions to add additional parameters to the
|
|
||||||
// Create request.
|
|
||||||
type CreateOptsBuilder interface {
|
|
||||||
ToSnapshotCreateMap() (map[string]interface{}, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateOpts contains options for creating a Snapshot. This object is passed to
|
|
||||||
// the snapshots.Create function. For more information about these parameters,
|
|
||||||
// see the Snapshot object.
|
|
||||||
type CreateOpts struct {
|
|
||||||
// OPTIONAL
|
|
||||||
Description string
|
|
||||||
// OPTIONAL
|
|
||||||
Force bool
|
|
||||||
// OPTIONAL
|
|
||||||
Metadata map[string]interface{}
|
|
||||||
// OPTIONAL
|
|
||||||
Name string
|
|
||||||
// REQUIRED
|
|
||||||
VolumeID string
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToSnapshotCreateMap assembles a request body based on the contents of a
|
|
||||||
// CreateOpts.
|
|
||||||
func (opts CreateOpts) ToSnapshotCreateMap() (map[string]interface{}, error) {
|
|
||||||
s := make(map[string]interface{})
|
|
||||||
|
|
||||||
if opts.VolumeID == "" {
|
|
||||||
return nil, fmt.Errorf("Required CreateOpts field 'VolumeID' not set.")
|
|
||||||
}
|
|
||||||
s["volume_id"] = opts.VolumeID
|
|
||||||
|
|
||||||
if opts.Description != "" {
|
|
||||||
s["display_description"] = opts.Description
|
|
||||||
}
|
|
||||||
if opts.Force == true {
|
|
||||||
s["force"] = opts.Force
|
|
||||||
}
|
|
||||||
if opts.Metadata != nil {
|
|
||||||
s["metadata"] = opts.Metadata
|
|
||||||
}
|
|
||||||
if opts.Name != "" {
|
|
||||||
s["display_name"] = opts.Name
|
|
||||||
}
|
|
||||||
|
|
||||||
return map[string]interface{}{"snapshot": s}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create will create a new Snapshot based on the values in CreateOpts. To
|
|
||||||
// extract the Snapshot object from the response, call the Extract method on the
|
|
||||||
// CreateResult.
|
|
||||||
func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
|
|
||||||
var res CreateResult
|
|
||||||
|
|
||||||
reqBody, err := opts.ToSnapshotCreateMap()
|
|
||||||
if err != nil {
|
|
||||||
res.Err = err
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
_, res.Err = client.Post(createURL(client), reqBody, &res.Body, &gophercloud.RequestOpts{
|
|
||||||
OkCodes: []int{200, 201},
|
|
||||||
})
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete will delete the existing Snapshot with the provided ID.
|
|
||||||
func Delete(client *gophercloud.ServiceClient, id string) DeleteResult {
|
|
||||||
var res DeleteResult
|
|
||||||
_, res.Err = client.Delete(deleteURL(client, id), nil)
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get retrieves the Snapshot with the provided ID. To extract the Snapshot
|
|
||||||
// object from the response, call the Extract method on the GetResult.
|
|
||||||
func Get(client *gophercloud.ServiceClient, id string) GetResult {
|
|
||||||
var res GetResult
|
|
||||||
_, res.Err = client.Get(getURL(client, id), &res.Body, nil)
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListOptsBuilder allows extensions to add additional parameters to the List
|
|
||||||
// request.
|
|
||||||
type ListOptsBuilder interface {
|
|
||||||
ToSnapshotListQuery() (string, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListOpts hold options for listing Snapshots. It is passed to the
|
|
||||||
// snapshots.List function.
|
|
||||||
type ListOpts struct {
|
|
||||||
Name string `q:"display_name"`
|
|
||||||
Status string `q:"status"`
|
|
||||||
VolumeID string `q:"volume_id"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToSnapshotListQuery formats a ListOpts into a query string.
|
|
||||||
func (opts ListOpts) ToSnapshotListQuery() (string, error) {
|
|
||||||
q, err := gophercloud.BuildQueryString(opts)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return q.String(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// List returns Snapshots optionally limited by the conditions provided in
|
|
||||||
// ListOpts.
|
|
||||||
func List(client *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager {
|
|
||||||
url := listURL(client)
|
|
||||||
if opts != nil {
|
|
||||||
query, err := opts.ToSnapshotListQuery()
|
|
||||||
if err != nil {
|
|
||||||
return pagination.Pager{Err: err}
|
|
||||||
}
|
|
||||||
url += query
|
|
||||||
}
|
|
||||||
|
|
||||||
createPage := func(r pagination.PageResult) pagination.Page {
|
|
||||||
return ListResult{pagination.SinglePageBase(r)}
|
|
||||||
}
|
|
||||||
return pagination.NewPager(client, url, createPage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateMetadataOptsBuilder allows extensions to add additional parameters to
|
|
||||||
// the Update request.
|
|
||||||
type UpdateMetadataOptsBuilder interface {
|
|
||||||
ToSnapshotUpdateMetadataMap() (map[string]interface{}, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateMetadataOpts contain options for updating an existing Snapshot. This
|
|
||||||
// object is passed to the snapshots.Update function. For more information
|
|
||||||
// about the parameters, see the Snapshot object.
|
|
||||||
type UpdateMetadataOpts struct {
|
|
||||||
Metadata map[string]interface{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToSnapshotUpdateMetadataMap assembles a request body based on the contents of
|
|
||||||
// an UpdateMetadataOpts.
|
|
||||||
func (opts UpdateMetadataOpts) ToSnapshotUpdateMetadataMap() (map[string]interface{}, error) {
|
|
||||||
v := make(map[string]interface{})
|
|
||||||
|
|
||||||
if opts.Metadata != nil {
|
|
||||||
v["metadata"] = opts.Metadata
|
|
||||||
}
|
|
||||||
|
|
||||||
return v, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateMetadata will update the Snapshot with provided information. To
|
|
||||||
// extract the updated Snapshot from the response, call the ExtractMetadata
|
|
||||||
// method on the UpdateMetadataResult.
|
|
||||||
func UpdateMetadata(client *gophercloud.ServiceClient, id string, opts UpdateMetadataOptsBuilder) UpdateMetadataResult {
|
|
||||||
var res UpdateMetadataResult
|
|
||||||
|
|
||||||
reqBody, err := opts.ToSnapshotUpdateMetadataMap()
|
|
||||||
if err != nil {
|
|
||||||
res.Err = err
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
_, res.Err = client.Put(updateMetadataURL(client, id), reqBody, &res.Body, &gophercloud.RequestOpts{
|
|
||||||
OkCodes: []int{200},
|
|
||||||
})
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
// IDFromName is a convienience function that returns a snapshot's ID given its name.
|
|
||||||
func IDFromName(client *gophercloud.ServiceClient, name string) (string, error) {
|
|
||||||
snapshotCount := 0
|
|
||||||
snapshotID := ""
|
|
||||||
if name == "" {
|
|
||||||
return "", fmt.Errorf("A snapshot name must be provided.")
|
|
||||||
}
|
|
||||||
pager := List(client, nil)
|
|
||||||
pager.EachPage(func(page pagination.Page) (bool, error) {
|
|
||||||
snapshotList, err := ExtractSnapshots(page)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, s := range snapshotList {
|
|
||||||
if s.Name == name {
|
|
||||||
snapshotCount++
|
|
||||||
snapshotID = s.ID
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true, nil
|
|
||||||
})
|
|
||||||
|
|
||||||
switch snapshotCount {
|
|
||||||
case 0:
|
|
||||||
return "", fmt.Errorf("Unable to find snapshot: %s", name)
|
|
||||||
case 1:
|
|
||||||
return snapshotID, nil
|
|
||||||
default:
|
|
||||||
return "", fmt.Errorf("Found %d snapshots matching %s", snapshotCount, name)
|
|
||||||
}
|
|
||||||
}
|
|
123
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/snapshots/results.go
generated
vendored
123
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/snapshots/results.go
generated
vendored
|
@ -1,123 +0,0 @@
|
||||||
package snapshots
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/rackspace/gophercloud"
|
|
||||||
"github.com/rackspace/gophercloud/pagination"
|
|
||||||
|
|
||||||
"github.com/mitchellh/mapstructure"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Snapshot contains all the information associated with an OpenStack Snapshot.
|
|
||||||
type Snapshot struct {
|
|
||||||
// Currect status of the Snapshot.
|
|
||||||
Status string `mapstructure:"status"`
|
|
||||||
|
|
||||||
// Display name.
|
|
||||||
Name string `mapstructure:"display_name"`
|
|
||||||
|
|
||||||
// Instances onto which the Snapshot is attached.
|
|
||||||
Attachments []string `mapstructure:"attachments"`
|
|
||||||
|
|
||||||
// Logical group.
|
|
||||||
AvailabilityZone string `mapstructure:"availability_zone"`
|
|
||||||
|
|
||||||
// Is the Snapshot bootable?
|
|
||||||
Bootable string `mapstructure:"bootable"`
|
|
||||||
|
|
||||||
// Date created.
|
|
||||||
CreatedAt string `mapstructure:"created_at"`
|
|
||||||
|
|
||||||
// Display description.
|
|
||||||
Description string `mapstructure:"display_discription"`
|
|
||||||
|
|
||||||
// See VolumeType object for more information.
|
|
||||||
VolumeType string `mapstructure:"volume_type"`
|
|
||||||
|
|
||||||
// ID of the Snapshot from which this Snapshot was created.
|
|
||||||
SnapshotID string `mapstructure:"snapshot_id"`
|
|
||||||
|
|
||||||
// ID of the Volume from which this Snapshot was created.
|
|
||||||
VolumeID string `mapstructure:"volume_id"`
|
|
||||||
|
|
||||||
// User-defined key-value pairs.
|
|
||||||
Metadata map[string]string `mapstructure:"metadata"`
|
|
||||||
|
|
||||||
// Unique identifier.
|
|
||||||
ID string `mapstructure:"id"`
|
|
||||||
|
|
||||||
// Size of the Snapshot, in GB.
|
|
||||||
Size int `mapstructure:"size"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateResult contains the response body and error from a Create request.
|
|
||||||
type CreateResult struct {
|
|
||||||
commonResult
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetResult contains the response body and error from a Get request.
|
|
||||||
type GetResult struct {
|
|
||||||
commonResult
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteResult contains the response body and error from a Delete request.
|
|
||||||
type DeleteResult struct {
|
|
||||||
gophercloud.ErrResult
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListResult is a pagination.Pager that is returned from a call to the List function.
|
|
||||||
type ListResult struct {
|
|
||||||
pagination.SinglePageBase
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsEmpty returns true if a ListResult contains no Snapshots.
|
|
||||||
func (r ListResult) IsEmpty() (bool, error) {
|
|
||||||
volumes, err := ExtractSnapshots(r)
|
|
||||||
if err != nil {
|
|
||||||
return true, err
|
|
||||||
}
|
|
||||||
return len(volumes) == 0, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExtractSnapshots extracts and returns Snapshots. It is used while iterating over a snapshots.List call.
|
|
||||||
func ExtractSnapshots(page pagination.Page) ([]Snapshot, error) {
|
|
||||||
var response struct {
|
|
||||||
Snapshots []Snapshot `json:"snapshots"`
|
|
||||||
}
|
|
||||||
|
|
||||||
err := mapstructure.Decode(page.(ListResult).Body, &response)
|
|
||||||
return response.Snapshots, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateMetadataResult contains the response body and error from an UpdateMetadata request.
|
|
||||||
type UpdateMetadataResult struct {
|
|
||||||
commonResult
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExtractMetadata returns the metadata from a response from snapshots.UpdateMetadata.
|
|
||||||
func (r UpdateMetadataResult) ExtractMetadata() (map[string]interface{}, error) {
|
|
||||||
if r.Err != nil {
|
|
||||||
return nil, r.Err
|
|
||||||
}
|
|
||||||
|
|
||||||
m := r.Body.(map[string]interface{})["metadata"]
|
|
||||||
return m.(map[string]interface{}), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type commonResult struct {
|
|
||||||
gophercloud.Result
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract will get the Snapshot object out of the commonResult object.
|
|
||||||
func (r commonResult) Extract() (*Snapshot, error) {
|
|
||||||
if r.Err != nil {
|
|
||||||
return nil, r.Err
|
|
||||||
}
|
|
||||||
|
|
||||||
var res struct {
|
|
||||||
Snapshot *Snapshot `json:"snapshot"`
|
|
||||||
}
|
|
||||||
|
|
||||||
err := mapstructure.Decode(r.Body, &res)
|
|
||||||
|
|
||||||
return res.Snapshot, err
|
|
||||||
}
|
|
27
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/snapshots/urls.go
generated
vendored
27
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/snapshots/urls.go
generated
vendored
|
@ -1,27 +0,0 @@
|
||||||
package snapshots
|
|
||||||
|
|
||||||
import "github.com/rackspace/gophercloud"
|
|
||||||
|
|
||||||
func createURL(c *gophercloud.ServiceClient) string {
|
|
||||||
return c.ServiceURL("snapshots")
|
|
||||||
}
|
|
||||||
|
|
||||||
func deleteURL(c *gophercloud.ServiceClient, id string) string {
|
|
||||||
return c.ServiceURL("snapshots", id)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getURL(c *gophercloud.ServiceClient, id string) string {
|
|
||||||
return deleteURL(c, id)
|
|
||||||
}
|
|
||||||
|
|
||||||
func listURL(c *gophercloud.ServiceClient) string {
|
|
||||||
return createURL(c)
|
|
||||||
}
|
|
||||||
|
|
||||||
func metadataURL(c *gophercloud.ServiceClient, id string) string {
|
|
||||||
return c.ServiceURL("snapshots", id, "metadata")
|
|
||||||
}
|
|
||||||
|
|
||||||
func updateMetadataURL(c *gophercloud.ServiceClient, id string) string {
|
|
||||||
return metadataURL(c, id)
|
|
||||||
}
|
|
22
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/snapshots/util.go
generated
vendored
22
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/snapshots/util.go
generated
vendored
|
@ -1,22 +0,0 @@
|
||||||
package snapshots
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/rackspace/gophercloud"
|
|
||||||
)
|
|
||||||
|
|
||||||
// WaitForStatus will continually poll the resource, checking for a particular
|
|
||||||
// status. It will do this for the amount of seconds defined.
|
|
||||||
func WaitForStatus(c *gophercloud.ServiceClient, id, status string, secs int) error {
|
|
||||||
return gophercloud.WaitFor(secs, func() (bool, error) {
|
|
||||||
current, err := Get(c, id).Extract()
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if current.Status == status {
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return false, nil
|
|
||||||
})
|
|
||||||
}
|
|
5
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes/doc.go
generated
vendored
5
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes/doc.go
generated
vendored
|
@ -1,5 +0,0 @@
|
||||||
// Package volumes provides information and interaction with volumes in the
|
|
||||||
// OpenStack Block Storage service. A volume is a detachable block storage
|
|
||||||
// device, akin to a USB hard drive. It can only be attached to one instance at
|
|
||||||
// a time.
|
|
||||||
package volumes
|
|
236
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes/requests.go
generated
vendored
236
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes/requests.go
generated
vendored
|
@ -1,236 +0,0 @@
|
||||||
package volumes
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/rackspace/gophercloud"
|
|
||||||
"github.com/rackspace/gophercloud/pagination"
|
|
||||||
)
|
|
||||||
|
|
||||||
// CreateOptsBuilder allows extensions to add additional parameters to the
|
|
||||||
// Create request.
|
|
||||||
type CreateOptsBuilder interface {
|
|
||||||
ToVolumeCreateMap() (map[string]interface{}, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateOpts contains options for creating a Volume. This object is passed to
|
|
||||||
// the volumes.Create function. For more information about these parameters,
|
|
||||||
// see the Volume object.
|
|
||||||
type CreateOpts struct {
|
|
||||||
// OPTIONAL
|
|
||||||
Availability string
|
|
||||||
// OPTIONAL
|
|
||||||
Description string
|
|
||||||
// OPTIONAL
|
|
||||||
Metadata map[string]string
|
|
||||||
// OPTIONAL
|
|
||||||
Name string
|
|
||||||
// REQUIRED
|
|
||||||
Size int
|
|
||||||
// OPTIONAL
|
|
||||||
SnapshotID, SourceVolID, ImageID string
|
|
||||||
// OPTIONAL
|
|
||||||
VolumeType string
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToVolumeCreateMap assembles a request body based on the contents of a
|
|
||||||
// CreateOpts.
|
|
||||||
func (opts CreateOpts) ToVolumeCreateMap() (map[string]interface{}, error) {
|
|
||||||
v := make(map[string]interface{})
|
|
||||||
|
|
||||||
if opts.Size == 0 {
|
|
||||||
return nil, fmt.Errorf("Required CreateOpts field 'Size' not set.")
|
|
||||||
}
|
|
||||||
v["size"] = opts.Size
|
|
||||||
|
|
||||||
if opts.Availability != "" {
|
|
||||||
v["availability_zone"] = opts.Availability
|
|
||||||
}
|
|
||||||
if opts.Description != "" {
|
|
||||||
v["display_description"] = opts.Description
|
|
||||||
}
|
|
||||||
if opts.ImageID != "" {
|
|
||||||
v["imageRef"] = opts.ImageID
|
|
||||||
}
|
|
||||||
if opts.Metadata != nil {
|
|
||||||
v["metadata"] = opts.Metadata
|
|
||||||
}
|
|
||||||
if opts.Name != "" {
|
|
||||||
v["display_name"] = opts.Name
|
|
||||||
}
|
|
||||||
if opts.SourceVolID != "" {
|
|
||||||
v["source_volid"] = opts.SourceVolID
|
|
||||||
}
|
|
||||||
if opts.SnapshotID != "" {
|
|
||||||
v["snapshot_id"] = opts.SnapshotID
|
|
||||||
}
|
|
||||||
if opts.VolumeType != "" {
|
|
||||||
v["volume_type"] = opts.VolumeType
|
|
||||||
}
|
|
||||||
|
|
||||||
return map[string]interface{}{"volume": v}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create will create a new Volume based on the values in CreateOpts. To extract
|
|
||||||
// the Volume object from the response, call the Extract method on the
|
|
||||||
// CreateResult.
|
|
||||||
func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
|
|
||||||
var res CreateResult
|
|
||||||
|
|
||||||
reqBody, err := opts.ToVolumeCreateMap()
|
|
||||||
if err != nil {
|
|
||||||
res.Err = err
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
_, res.Err = client.Post(createURL(client), reqBody, &res.Body, &gophercloud.RequestOpts{
|
|
||||||
OkCodes: []int{200, 201},
|
|
||||||
})
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete will delete the existing Volume with the provided ID.
|
|
||||||
func Delete(client *gophercloud.ServiceClient, id string) DeleteResult {
|
|
||||||
var res DeleteResult
|
|
||||||
_, res.Err = client.Delete(deleteURL(client, id), nil)
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get retrieves the Volume with the provided ID. To extract the Volume object
|
|
||||||
// from the response, call the Extract method on the GetResult.
|
|
||||||
func Get(client *gophercloud.ServiceClient, id string) GetResult {
|
|
||||||
var res GetResult
|
|
||||||
_, res.Err = client.Get(getURL(client, id), &res.Body, nil)
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListOptsBuilder allows extensions to add additional parameters to the List
|
|
||||||
// request.
|
|
||||||
type ListOptsBuilder interface {
|
|
||||||
ToVolumeListQuery() (string, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListOpts holds options for listing Volumes. It is passed to the volumes.List
|
|
||||||
// function.
|
|
||||||
type ListOpts struct {
|
|
||||||
// admin-only option. Set it to true to see all tenant volumes.
|
|
||||||
AllTenants bool `q:"all_tenants"`
|
|
||||||
// List only volumes that contain Metadata.
|
|
||||||
Metadata map[string]string `q:"metadata"`
|
|
||||||
// List only volumes that have Name as the display name.
|
|
||||||
Name string `q:"name"`
|
|
||||||
// List only volumes that have a status of Status.
|
|
||||||
Status string `q:"status"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToVolumeListQuery formats a ListOpts into a query string.
|
|
||||||
func (opts ListOpts) ToVolumeListQuery() (string, error) {
|
|
||||||
q, err := gophercloud.BuildQueryString(opts)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return q.String(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// List returns Volumes optionally limited by the conditions provided in ListOpts.
|
|
||||||
func List(client *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager {
|
|
||||||
url := listURL(client)
|
|
||||||
if opts != nil {
|
|
||||||
query, err := opts.ToVolumeListQuery()
|
|
||||||
if err != nil {
|
|
||||||
return pagination.Pager{Err: err}
|
|
||||||
}
|
|
||||||
url += query
|
|
||||||
}
|
|
||||||
createPage := func(r pagination.PageResult) pagination.Page {
|
|
||||||
return ListResult{pagination.SinglePageBase(r)}
|
|
||||||
}
|
|
||||||
|
|
||||||
return pagination.NewPager(client, url, createPage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateOptsBuilder allows extensions to add additional parameters to the
|
|
||||||
// Update request.
|
|
||||||
type UpdateOptsBuilder interface {
|
|
||||||
ToVolumeUpdateMap() (map[string]interface{}, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateOpts contain options for updating an existing Volume. This object is passed
|
|
||||||
// to the volumes.Update function. For more information about the parameters, see
|
|
||||||
// the Volume object.
|
|
||||||
type UpdateOpts struct {
|
|
||||||
// OPTIONAL
|
|
||||||
Name string
|
|
||||||
// OPTIONAL
|
|
||||||
Description string
|
|
||||||
// OPTIONAL
|
|
||||||
Metadata map[string]string
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToVolumeUpdateMap assembles a request body based on the contents of an
|
|
||||||
// UpdateOpts.
|
|
||||||
func (opts UpdateOpts) ToVolumeUpdateMap() (map[string]interface{}, error) {
|
|
||||||
v := make(map[string]interface{})
|
|
||||||
|
|
||||||
if opts.Description != "" {
|
|
||||||
v["display_description"] = opts.Description
|
|
||||||
}
|
|
||||||
if opts.Metadata != nil {
|
|
||||||
v["metadata"] = opts.Metadata
|
|
||||||
}
|
|
||||||
if opts.Name != "" {
|
|
||||||
v["display_name"] = opts.Name
|
|
||||||
}
|
|
||||||
|
|
||||||
return map[string]interface{}{"volume": v}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update will update the Volume with provided information. To extract the updated
|
|
||||||
// Volume from the response, call the Extract method on the UpdateResult.
|
|
||||||
func Update(client *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) UpdateResult {
|
|
||||||
var res UpdateResult
|
|
||||||
|
|
||||||
reqBody, err := opts.ToVolumeUpdateMap()
|
|
||||||
if err != nil {
|
|
||||||
res.Err = err
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
_, res.Err = client.Put(updateURL(client, id), reqBody, &res.Body, &gophercloud.RequestOpts{
|
|
||||||
OkCodes: []int{200},
|
|
||||||
})
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
// IDFromName is a convienience function that returns a server's ID given its name.
|
|
||||||
func IDFromName(client *gophercloud.ServiceClient, name string) (string, error) {
|
|
||||||
volumeCount := 0
|
|
||||||
volumeID := ""
|
|
||||||
if name == "" {
|
|
||||||
return "", fmt.Errorf("A volume name must be provided.")
|
|
||||||
}
|
|
||||||
pager := List(client, nil)
|
|
||||||
pager.EachPage(func(page pagination.Page) (bool, error) {
|
|
||||||
volumeList, err := ExtractVolumes(page)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, s := range volumeList {
|
|
||||||
if s.Name == name {
|
|
||||||
volumeCount++
|
|
||||||
volumeID = s.ID
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true, nil
|
|
||||||
})
|
|
||||||
|
|
||||||
switch volumeCount {
|
|
||||||
case 0:
|
|
||||||
return "", fmt.Errorf("Unable to find volume: %s", name)
|
|
||||||
case 1:
|
|
||||||
return volumeID, nil
|
|
||||||
default:
|
|
||||||
return "", fmt.Errorf("Found %d volumes matching %s", volumeCount, name)
|
|
||||||
}
|
|
||||||
}
|
|
113
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes/results.go
generated
vendored
113
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes/results.go
generated
vendored
|
@ -1,113 +0,0 @@
|
||||||
package volumes
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/rackspace/gophercloud"
|
|
||||||
"github.com/rackspace/gophercloud/pagination"
|
|
||||||
|
|
||||||
"github.com/mitchellh/mapstructure"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Volume contains all the information associated with an OpenStack Volume.
|
|
||||||
type Volume struct {
|
|
||||||
// Current status of the volume.
|
|
||||||
Status string `mapstructure:"status"`
|
|
||||||
|
|
||||||
// Human-readable display name for the volume.
|
|
||||||
Name string `mapstructure:"display_name"`
|
|
||||||
|
|
||||||
// Instances onto which the volume is attached.
|
|
||||||
Attachments []map[string]interface{} `mapstructure:"attachments"`
|
|
||||||
|
|
||||||
// This parameter is no longer used.
|
|
||||||
AvailabilityZone string `mapstructure:"availability_zone"`
|
|
||||||
|
|
||||||
// Indicates whether this is a bootable volume.
|
|
||||||
Bootable string `mapstructure:"bootable"`
|
|
||||||
|
|
||||||
// The date when this volume was created.
|
|
||||||
CreatedAt string `mapstructure:"created_at"`
|
|
||||||
|
|
||||||
// Human-readable description for the volume.
|
|
||||||
Description string `mapstructure:"display_description"`
|
|
||||||
|
|
||||||
// The type of volume to create, either SATA or SSD.
|
|
||||||
VolumeType string `mapstructure:"volume_type"`
|
|
||||||
|
|
||||||
// The ID of the snapshot from which the volume was created
|
|
||||||
SnapshotID string `mapstructure:"snapshot_id"`
|
|
||||||
|
|
||||||
// The ID of another block storage volume from which the current volume was created
|
|
||||||
SourceVolID string `mapstructure:"source_volid"`
|
|
||||||
|
|
||||||
// Arbitrary key-value pairs defined by the user.
|
|
||||||
Metadata map[string]string `mapstructure:"metadata"`
|
|
||||||
|
|
||||||
// Unique identifier for the volume.
|
|
||||||
ID string `mapstructure:"id"`
|
|
||||||
|
|
||||||
// Size of the volume in GB.
|
|
||||||
Size int `mapstructure:"size"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateResult contains the response body and error from a Create request.
|
|
||||||
type CreateResult struct {
|
|
||||||
commonResult
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetResult contains the response body and error from a Get request.
|
|
||||||
type GetResult struct {
|
|
||||||
commonResult
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteResult contains the response body and error from a Delete request.
|
|
||||||
type DeleteResult struct {
|
|
||||||
gophercloud.ErrResult
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListResult is a pagination.pager that is returned from a call to the List function.
|
|
||||||
type ListResult struct {
|
|
||||||
pagination.SinglePageBase
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsEmpty returns true if a ListResult contains no Volumes.
|
|
||||||
func (r ListResult) IsEmpty() (bool, error) {
|
|
||||||
volumes, err := ExtractVolumes(r)
|
|
||||||
if err != nil {
|
|
||||||
return true, err
|
|
||||||
}
|
|
||||||
return len(volumes) == 0, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExtractVolumes extracts and returns Volumes. It is used while iterating over a volumes.List call.
|
|
||||||
func ExtractVolumes(page pagination.Page) ([]Volume, error) {
|
|
||||||
var response struct {
|
|
||||||
Volumes []Volume `json:"volumes"`
|
|
||||||
}
|
|
||||||
|
|
||||||
err := mapstructure.Decode(page.(ListResult).Body, &response)
|
|
||||||
return response.Volumes, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateResult contains the response body and error from an Update request.
|
|
||||||
type UpdateResult struct {
|
|
||||||
commonResult
|
|
||||||
}
|
|
||||||
|
|
||||||
type commonResult struct {
|
|
||||||
gophercloud.Result
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract will get the Volume object out of the commonResult object.
|
|
||||||
func (r commonResult) Extract() (*Volume, error) {
|
|
||||||
if r.Err != nil {
|
|
||||||
return nil, r.Err
|
|
||||||
}
|
|
||||||
|
|
||||||
var res struct {
|
|
||||||
Volume *Volume `json:"volume"`
|
|
||||||
}
|
|
||||||
|
|
||||||
err := mapstructure.Decode(r.Body, &res)
|
|
||||||
|
|
||||||
return res.Volume, err
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
/*
|
|
||||||
This is package created is to hold fixtures (which imports testing),
|
|
||||||
so that importing volumes package does not inadvertently import testing into production code
|
|
||||||
More information here:
|
|
||||||
https://github.com/rackspace/gophercloud/issues/473
|
|
||||||
*/
|
|
||||||
package testing
|
|
|
@ -1,113 +0,0 @@
|
||||||
package testing
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
th "github.com/rackspace/gophercloud/testhelper"
|
|
||||||
fake "github.com/rackspace/gophercloud/testhelper/client"
|
|
||||||
)
|
|
||||||
|
|
||||||
func MockListResponse(t *testing.T) {
|
|
||||||
th.Mux.HandleFunc("/volumes", 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")
|
|
||||||
w.WriteHeader(http.StatusOK)
|
|
||||||
|
|
||||||
fmt.Fprintf(w, `
|
|
||||||
{
|
|
||||||
"volumes": [
|
|
||||||
{
|
|
||||||
"id": "289da7f8-6440-407c-9fb4-7db01ec49164",
|
|
||||||
"display_name": "vol-001"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "96c3bda7-c82a-4f50-be73-ca7621794835",
|
|
||||||
"display_name": "vol-002"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
`)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func MockGetResponse(t *testing.T) {
|
|
||||||
th.Mux.HandleFunc("/volumes/d32019d3-bc6e-4319-9c1d-6722fc136a22", 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")
|
|
||||||
w.WriteHeader(http.StatusOK)
|
|
||||||
fmt.Fprintf(w, `
|
|
||||||
{
|
|
||||||
"volume": {
|
|
||||||
"display_name": "vol-001",
|
|
||||||
"id": "d32019d3-bc6e-4319-9c1d-6722fc136a22",
|
|
||||||
"attachments": [
|
|
||||||
{
|
|
||||||
"device": "/dev/vde",
|
|
||||||
"server_id": "a740d24b-dc5b-4d59-ac75-53971c2920ba",
|
|
||||||
"id": "d6da11e5-2ed3-413e-88d8-b772ba62193d",
|
|
||||||
"volume_id": "d6da11e5-2ed3-413e-88d8-b772ba62193d"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func MockCreateResponse(t *testing.T) {
|
|
||||||
th.Mux.HandleFunc("/volumes", func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
th.TestMethod(t, r, "POST")
|
|
||||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
|
||||||
th.TestHeader(t, r, "Content-Type", "application/json")
|
|
||||||
th.TestHeader(t, r, "Accept", "application/json")
|
|
||||||
th.TestJSONRequest(t, r, `
|
|
||||||
{
|
|
||||||
"volume": {
|
|
||||||
"size": 75
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`)
|
|
||||||
|
|
||||||
w.Header().Add("Content-Type", "application/json")
|
|
||||||
w.WriteHeader(http.StatusCreated)
|
|
||||||
|
|
||||||
fmt.Fprintf(w, `
|
|
||||||
{
|
|
||||||
"volume": {
|
|
||||||
"size": 4,
|
|
||||||
"id": "d32019d3-bc6e-4319-9c1d-6722fc136a22"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func MockDeleteResponse(t *testing.T) {
|
|
||||||
th.Mux.HandleFunc("/volumes/d32019d3-bc6e-4319-9c1d-6722fc136a22", func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
th.TestMethod(t, r, "DELETE")
|
|
||||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
|
||||||
w.WriteHeader(http.StatusNoContent)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func MockUpdateResponse(t *testing.T) {
|
|
||||||
th.Mux.HandleFunc("/volumes/d32019d3-bc6e-4319-9c1d-6722fc136a22", func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
th.TestMethod(t, r, "PUT")
|
|
||||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
|
||||||
w.WriteHeader(http.StatusOK)
|
|
||||||
fmt.Fprintf(w, `
|
|
||||||
{
|
|
||||||
"volume": {
|
|
||||||
"display_name": "vol-002",
|
|
||||||
"id": "d32019d3-bc6e-4319-9c1d-6722fc136a22"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`)
|
|
||||||
})
|
|
||||||
}
|
|
23
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes/urls.go
generated
vendored
23
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes/urls.go
generated
vendored
|
@ -1,23 +0,0 @@
|
||||||
package volumes
|
|
||||||
|
|
||||||
import "github.com/rackspace/gophercloud"
|
|
||||||
|
|
||||||
func createURL(c *gophercloud.ServiceClient) string {
|
|
||||||
return c.ServiceURL("volumes")
|
|
||||||
}
|
|
||||||
|
|
||||||
func listURL(c *gophercloud.ServiceClient) string {
|
|
||||||
return createURL(c)
|
|
||||||
}
|
|
||||||
|
|
||||||
func deleteURL(c *gophercloud.ServiceClient, id string) string {
|
|
||||||
return c.ServiceURL("volumes", id)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getURL(c *gophercloud.ServiceClient, id string) string {
|
|
||||||
return deleteURL(c, id)
|
|
||||||
}
|
|
||||||
|
|
||||||
func updateURL(c *gophercloud.ServiceClient, id string) string {
|
|
||||||
return deleteURL(c, id)
|
|
||||||
}
|
|
22
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes/util.go
generated
vendored
22
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes/util.go
generated
vendored
|
@ -1,22 +0,0 @@
|
||||||
package volumes
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/rackspace/gophercloud"
|
|
||||||
)
|
|
||||||
|
|
||||||
// WaitForStatus will continually poll the resource, checking for a particular
|
|
||||||
// status. It will do this for the amount of seconds defined.
|
|
||||||
func WaitForStatus(c *gophercloud.ServiceClient, id, status string, secs int) error {
|
|
||||||
return gophercloud.WaitFor(secs, func() (bool, error) {
|
|
||||||
current, err := Get(c, id).Extract()
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if current.Status == status {
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return false, nil
|
|
||||||
})
|
|
||||||
}
|
|
9
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumetypes/doc.go
generated
vendored
9
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumetypes/doc.go
generated
vendored
|
@ -1,9 +0,0 @@
|
||||||
// Package volumetypes provides information and interaction with volume types
|
|
||||||
// in the OpenStack Block Storage service. A volume type indicates the type of
|
|
||||||
// a block storage volume, such as SATA, SCSCI, SSD, etc. These can be
|
|
||||||
// customized or defined by the OpenStack admin.
|
|
||||||
//
|
|
||||||
// You can also define extra_specs associated with your volume types. For
|
|
||||||
// instance, you could have a VolumeType=SATA, with extra_specs (RPM=10000,
|
|
||||||
// RAID-Level=5) . Extra_specs are defined and customized by the admin.
|
|
||||||
package volumetypes
|
|
|
@ -1,60 +0,0 @@
|
||||||
package volumetypes
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
th "github.com/rackspace/gophercloud/testhelper"
|
|
||||||
fake "github.com/rackspace/gophercloud/testhelper/client"
|
|
||||||
)
|
|
||||||
|
|
||||||
func MockListResponse(t *testing.T) {
|
|
||||||
th.Mux.HandleFunc("/types", 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")
|
|
||||||
w.WriteHeader(http.StatusOK)
|
|
||||||
|
|
||||||
fmt.Fprintf(w, `
|
|
||||||
{
|
|
||||||
"volume_types": [
|
|
||||||
{
|
|
||||||
"id": "289da7f8-6440-407c-9fb4-7db01ec49164",
|
|
||||||
"name": "vol-type-001",
|
|
||||||
"extra_specs": {
|
|
||||||
"capabilities": "gpu"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "96c3bda7-c82a-4f50-be73-ca7621794835",
|
|
||||||
"name": "vol-type-002",
|
|
||||||
"extra_specs": {}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
`)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func MockGetResponse(t *testing.T) {
|
|
||||||
th.Mux.HandleFunc("/types/d32019d3-bc6e-4319-9c1d-6722fc136a22", 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")
|
|
||||||
w.WriteHeader(http.StatusOK)
|
|
||||||
fmt.Fprintf(w, `
|
|
||||||
{
|
|
||||||
"volume_type": {
|
|
||||||
"name": "vol-type-001",
|
|
||||||
"id": "d32019d3-bc6e-4319-9c1d-6722fc136a22",
|
|
||||||
"extra_specs": {
|
|
||||||
"serverNumber": "2"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`)
|
|
||||||
})
|
|
||||||
}
|
|
|
@ -1,76 +0,0 @@
|
||||||
package volumetypes
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/rackspace/gophercloud"
|
|
||||||
"github.com/rackspace/gophercloud/pagination"
|
|
||||||
)
|
|
||||||
|
|
||||||
// CreateOptsBuilder allows extensions to add additional parameters to the
|
|
||||||
// Create request.
|
|
||||||
type CreateOptsBuilder interface {
|
|
||||||
ToVolumeTypeCreateMap() (map[string]interface{}, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateOpts are options for creating a volume type.
|
|
||||||
type CreateOpts struct {
|
|
||||||
// OPTIONAL. See VolumeType.
|
|
||||||
ExtraSpecs map[string]interface{}
|
|
||||||
// OPTIONAL. See VolumeType.
|
|
||||||
Name string
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToVolumeTypeCreateMap casts a CreateOpts struct to a map.
|
|
||||||
func (opts CreateOpts) ToVolumeTypeCreateMap() (map[string]interface{}, error) {
|
|
||||||
vt := make(map[string]interface{})
|
|
||||||
|
|
||||||
if opts.ExtraSpecs != nil {
|
|
||||||
vt["extra_specs"] = opts.ExtraSpecs
|
|
||||||
}
|
|
||||||
if opts.Name != "" {
|
|
||||||
vt["name"] = opts.Name
|
|
||||||
}
|
|
||||||
|
|
||||||
return map[string]interface{}{"volume_type": vt}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create will create a new volume. To extract the created volume type object,
|
|
||||||
// call the Extract method on the CreateResult.
|
|
||||||
func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
|
|
||||||
var res CreateResult
|
|
||||||
|
|
||||||
reqBody, err := opts.ToVolumeTypeCreateMap()
|
|
||||||
if err != nil {
|
|
||||||
res.Err = err
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
_, res.Err = client.Post(createURL(client), reqBody, &res.Body, &gophercloud.RequestOpts{
|
|
||||||
OkCodes: []int{200, 201},
|
|
||||||
})
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete will delete the volume type with the provided ID.
|
|
||||||
func Delete(client *gophercloud.ServiceClient, id string) DeleteResult {
|
|
||||||
var res DeleteResult
|
|
||||||
_, res.Err = client.Delete(deleteURL(client, id), nil)
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get will retrieve the volume type with the provided ID. To extract the volume
|
|
||||||
// type from the result, call the Extract method on the GetResult.
|
|
||||||
func Get(client *gophercloud.ServiceClient, id string) GetResult {
|
|
||||||
var res GetResult
|
|
||||||
_, err := client.Get(getURL(client, id), &res.Body, nil)
|
|
||||||
res.Err = err
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
// List returns all volume types.
|
|
||||||
func List(client *gophercloud.ServiceClient) pagination.Pager {
|
|
||||||
createPage := func(r pagination.PageResult) pagination.Page {
|
|
||||||
return ListResult{pagination.SinglePageBase(r)}
|
|
||||||
}
|
|
||||||
|
|
||||||
return pagination.NewPager(client, listURL(client), createPage)
|
|
||||||
}
|
|
72
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumetypes/results.go
generated
vendored
72
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumetypes/results.go
generated
vendored
|
@ -1,72 +0,0 @@
|
||||||
package volumetypes
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/mitchellh/mapstructure"
|
|
||||||
"github.com/rackspace/gophercloud"
|
|
||||||
"github.com/rackspace/gophercloud/pagination"
|
|
||||||
)
|
|
||||||
|
|
||||||
// VolumeType contains all information associated with an OpenStack Volume Type.
|
|
||||||
type VolumeType struct {
|
|
||||||
ExtraSpecs map[string]interface{} `json:"extra_specs" mapstructure:"extra_specs"` // user-defined metadata
|
|
||||||
ID string `json:"id" mapstructure:"id"` // unique identifier
|
|
||||||
Name string `json:"name" mapstructure:"name"` // display name
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateResult contains the response body and error from a Create request.
|
|
||||||
type CreateResult struct {
|
|
||||||
commonResult
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetResult contains the response body and error from a Get request.
|
|
||||||
type GetResult struct {
|
|
||||||
commonResult
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteResult contains the response error from a Delete request.
|
|
||||||
type DeleteResult struct {
|
|
||||||
gophercloud.ErrResult
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListResult is a pagination.Pager that is returned from a call to the List function.
|
|
||||||
type ListResult struct {
|
|
||||||
pagination.SinglePageBase
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsEmpty returns true if a ListResult contains no Volume Types.
|
|
||||||
func (r ListResult) IsEmpty() (bool, error) {
|
|
||||||
volumeTypes, err := ExtractVolumeTypes(r)
|
|
||||||
if err != nil {
|
|
||||||
return true, err
|
|
||||||
}
|
|
||||||
return len(volumeTypes) == 0, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExtractVolumeTypes extracts and returns Volume Types.
|
|
||||||
func ExtractVolumeTypes(page pagination.Page) ([]VolumeType, error) {
|
|
||||||
var response struct {
|
|
||||||
VolumeTypes []VolumeType `mapstructure:"volume_types"`
|
|
||||||
}
|
|
||||||
|
|
||||||
err := mapstructure.Decode(page.(ListResult).Body, &response)
|
|
||||||
return response.VolumeTypes, err
|
|
||||||
}
|
|
||||||
|
|
||||||
type commonResult struct {
|
|
||||||
gophercloud.Result
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract will get the Volume Type object out of the commonResult object.
|
|
||||||
func (r commonResult) Extract() (*VolumeType, error) {
|
|
||||||
if r.Err != nil {
|
|
||||||
return nil, r.Err
|
|
||||||
}
|
|
||||||
|
|
||||||
var res struct {
|
|
||||||
VolumeType *VolumeType `json:"volume_type" mapstructure:"volume_type"`
|
|
||||||
}
|
|
||||||
|
|
||||||
err := mapstructure.Decode(r.Body, &res)
|
|
||||||
|
|
||||||
return res.VolumeType, err
|
|
||||||
}
|
|
19
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumetypes/urls.go
generated
vendored
19
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumetypes/urls.go
generated
vendored
|
@ -1,19 +0,0 @@
|
||||||
package volumetypes
|
|
||||||
|
|
||||||
import "github.com/rackspace/gophercloud"
|
|
||||||
|
|
||||||
func listURL(c *gophercloud.ServiceClient) string {
|
|
||||||
return c.ServiceURL("types")
|
|
||||||
}
|
|
||||||
|
|
||||||
func createURL(c *gophercloud.ServiceClient) string {
|
|
||||||
return listURL(c)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getURL(c *gophercloud.ServiceClient, id string) string {
|
|
||||||
return c.ServiceURL("types", id)
|
|
||||||
}
|
|
||||||
|
|
||||||
func deleteURL(c *gophercloud.ServiceClient, id string) string {
|
|
||||||
return getURL(c, id)
|
|
||||||
}
|
|
|
@ -1,4 +0,0 @@
|
||||||
// Package base provides information and interaction with the base API
|
|
||||||
// resource in the OpenStack CDN service. This API resource allows for
|
|
||||||
// retrieving the Home Document and pinging the root URL.
|
|
||||||
package base
|
|
|
@ -1,53 +0,0 @@
|
||||||
package base
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
th "github.com/rackspace/gophercloud/testhelper"
|
|
||||||
fake "github.com/rackspace/gophercloud/testhelper/client"
|
|
||||||
)
|
|
||||||
|
|
||||||
// HandleGetSuccessfully creates an HTTP handler at `/` on the test handler mux
|
|
||||||
// that responds with a `Get` response.
|
|
||||||
func HandleGetSuccessfully(t *testing.T) {
|
|
||||||
th.Mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
th.TestMethod(t, r, "GET")
|
|
||||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
|
||||||
th.TestHeader(t, r, "Accept", "application/json")
|
|
||||||
w.WriteHeader(http.StatusOK)
|
|
||||||
fmt.Fprintf(w, `
|
|
||||||
{
|
|
||||||
"resources": {
|
|
||||||
"rel/cdn": {
|
|
||||||
"href-template": "services{?marker,limit}",
|
|
||||||
"href-vars": {
|
|
||||||
"marker": "param/marker",
|
|
||||||
"limit": "param/limit"
|
|
||||||
},
|
|
||||||
"hints": {
|
|
||||||
"allow": [
|
|
||||||
"GET"
|
|
||||||
],
|
|
||||||
"formats": {
|
|
||||||
"application/json": {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`)
|
|
||||||
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// HandlePingSuccessfully creates an HTTP handler at `/ping` on the test handler
|
|
||||||
// mux that responds with a `Ping` response.
|
|
||||||
func HandlePingSuccessfully(t *testing.T) {
|
|
||||||
th.Mux.HandleFunc("/ping", func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
th.TestMethod(t, r, "GET")
|
|
||||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
|
||||||
w.WriteHeader(http.StatusNoContent)
|
|
||||||
})
|
|
||||||
}
|
|
|
@ -1,21 +0,0 @@
|
||||||
package base
|
|
||||||
|
|
||||||
import "github.com/rackspace/gophercloud"
|
|
||||||
|
|
||||||
// Get retrieves the home document, allowing the user to discover the
|
|
||||||
// entire API.
|
|
||||||
func Get(c *gophercloud.ServiceClient) GetResult {
|
|
||||||
var res GetResult
|
|
||||||
_, res.Err = c.Get(getURL(c), &res.Body, nil)
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ping retrieves a ping to the server.
|
|
||||||
func Ping(c *gophercloud.ServiceClient) PingResult {
|
|
||||||
var res PingResult
|
|
||||||
_, res.Err = c.Get(pingURL(c), nil, &gophercloud.RequestOpts{
|
|
||||||
OkCodes: []int{204},
|
|
||||||
MoreHeaders: map[string]string{"Accept": ""},
|
|
||||||
})
|
|
||||||
return res
|
|
||||||
}
|
|
|
@ -1,35 +0,0 @@
|
||||||
package base
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
|
|
||||||
"github.com/rackspace/gophercloud"
|
|
||||||
)
|
|
||||||
|
|
||||||
// HomeDocument is a resource that contains all the resources for the CDN API.
|
|
||||||
type HomeDocument map[string]interface{}
|
|
||||||
|
|
||||||
// GetResult represents the result of a Get operation.
|
|
||||||
type GetResult struct {
|
|
||||||
gophercloud.Result
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract is a function that accepts a result and extracts a home document resource.
|
|
||||||
func (r GetResult) Extract() (*HomeDocument, error) {
|
|
||||||
if r.Err != nil {
|
|
||||||
return nil, r.Err
|
|
||||||
}
|
|
||||||
|
|
||||||
submap, ok := r.Body.(map[string]interface{})["resources"]
|
|
||||||
if !ok {
|
|
||||||
return nil, errors.New("Unexpected HomeDocument structure")
|
|
||||||
}
|
|
||||||
casted := HomeDocument(submap.(map[string]interface{}))
|
|
||||||
|
|
||||||
return &casted, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// PingResult represents the result of a Ping operation.
|
|
||||||
type PingResult struct {
|
|
||||||
gophercloud.ErrResult
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
package base
|
|
||||||
|
|
||||||
import "github.com/rackspace/gophercloud"
|
|
||||||
|
|
||||||
func getURL(c *gophercloud.ServiceClient) string {
|
|
||||||
return c.ServiceURL()
|
|
||||||
}
|
|
||||||
|
|
||||||
func pingURL(c *gophercloud.ServiceClient) string {
|
|
||||||
return c.ServiceURL("ping")
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
// Package flavors provides information and interaction with the flavors API
|
|
||||||
// resource in the OpenStack CDN service. This API resource allows for
|
|
||||||
// listing flavors and retrieving a specific flavor.
|
|
||||||
//
|
|
||||||
// A flavor is a mapping configuration to a CDN provider.
|
|
||||||
package flavors
|
|
|
@ -1,82 +0,0 @@
|
||||||
package flavors
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
th "github.com/rackspace/gophercloud/testhelper"
|
|
||||||
fake "github.com/rackspace/gophercloud/testhelper/client"
|
|
||||||
)
|
|
||||||
|
|
||||||
// HandleListCDNFlavorsSuccessfully creates an HTTP handler at `/flavors` on the test handler mux
|
|
||||||
// that responds with a `List` response.
|
|
||||||
func HandleListCDNFlavorsSuccessfully(t *testing.T) {
|
|
||||||
th.Mux.HandleFunc("/flavors", func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
th.TestMethod(t, r, "GET")
|
|
||||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
|
||||||
w.WriteHeader(http.StatusOK)
|
|
||||||
fmt.Fprintf(w, `
|
|
||||||
{
|
|
||||||
"flavors": [
|
|
||||||
{
|
|
||||||
"id": "europe",
|
|
||||||
"providers": [
|
|
||||||
{
|
|
||||||
"provider": "Fastly",
|
|
||||||
"links": [
|
|
||||||
{
|
|
||||||
"href": "http://www.fastly.com",
|
|
||||||
"rel": "provider_url"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"links": [
|
|
||||||
{
|
|
||||||
"href": "https://www.poppycdn.io/v1.0/flavors/europe",
|
|
||||||
"rel": "self"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
`)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// HandleGetCDNFlavorSuccessfully creates an HTTP handler at `/flavors/{id}` on the test handler mux
|
|
||||||
// that responds with a `Get` response.
|
|
||||||
func HandleGetCDNFlavorSuccessfully(t *testing.T) {
|
|
||||||
th.Mux.HandleFunc("/flavors/asia", func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
th.TestMethod(t, r, "GET")
|
|
||||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
|
||||||
w.WriteHeader(http.StatusOK)
|
|
||||||
fmt.Fprintf(w, `
|
|
||||||
{
|
|
||||||
"id" : "asia",
|
|
||||||
"providers" : [
|
|
||||||
{
|
|
||||||
"provider" : "ChinaCache",
|
|
||||||
"links": [
|
|
||||||
{
|
|
||||||
"href": "http://www.chinacache.com",
|
|
||||||
"rel": "provider_url"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"links": [
|
|
||||||
{
|
|
||||||
"href": "https://www.poppycdn.io/v1.0/flavors/asia",
|
|
||||||
"rel": "self"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
`)
|
|
||||||
})
|
|
||||||
}
|
|
|
@ -1,22 +0,0 @@
|
||||||
package flavors
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/rackspace/gophercloud"
|
|
||||||
"github.com/rackspace/gophercloud/pagination"
|
|
||||||
)
|
|
||||||
|
|
||||||
// List returns a single page of CDN flavors.
|
|
||||||
func List(c *gophercloud.ServiceClient) pagination.Pager {
|
|
||||||
url := listURL(c)
|
|
||||||
createPage := func(r pagination.PageResult) pagination.Page {
|
|
||||||
return FlavorPage{pagination.SinglePageBase(r)}
|
|
||||||
}
|
|
||||||
return pagination.NewPager(c, url, createPage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get retrieves a specific flavor based on its unique ID.
|
|
||||||
func Get(c *gophercloud.ServiceClient, id string) GetResult {
|
|
||||||
var res GetResult
|
|
||||||
_, res.Err = c.Get(getURL(c, id), &res.Body, nil)
|
|
||||||
return res
|
|
||||||
}
|
|
|
@ -1,71 +0,0 @@
|
||||||
package flavors
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/mitchellh/mapstructure"
|
|
||||||
"github.com/rackspace/gophercloud"
|
|
||||||
"github.com/rackspace/gophercloud/pagination"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Provider represents a provider for a particular flavor.
|
|
||||||
type Provider struct {
|
|
||||||
// Specifies the name of the provider. The name must not exceed 64 bytes in
|
|
||||||
// length and is limited to unicode, digits, underscores, and hyphens.
|
|
||||||
Provider string `mapstructure:"provider"`
|
|
||||||
// Specifies a list with an href where rel is provider_url.
|
|
||||||
Links []gophercloud.Link `mapstructure:"links"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Flavor represents a mapping configuration to a CDN provider.
|
|
||||||
type Flavor struct {
|
|
||||||
// Specifies the name of the flavor. The name must not exceed 64 bytes in
|
|
||||||
// length and is limited to unicode, digits, underscores, and hyphens.
|
|
||||||
ID string `mapstructure:"id"`
|
|
||||||
// Specifies the list of providers mapped to this flavor.
|
|
||||||
Providers []Provider `mapstructure:"providers"`
|
|
||||||
// Specifies the self-navigating JSON document paths.
|
|
||||||
Links []gophercloud.Link `mapstructure:"links"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// FlavorPage is the page returned by a pager when traversing over a
|
|
||||||
// collection of CDN flavors.
|
|
||||||
type FlavorPage struct {
|
|
||||||
pagination.SinglePageBase
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsEmpty returns true if a FlavorPage contains no Flavors.
|
|
||||||
func (r FlavorPage) IsEmpty() (bool, error) {
|
|
||||||
flavors, err := ExtractFlavors(r)
|
|
||||||
if err != nil {
|
|
||||||
return true, err
|
|
||||||
}
|
|
||||||
return len(flavors) == 0, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExtractFlavors extracts and returns Flavors. It is used while iterating over
|
|
||||||
// a flavors.List call.
|
|
||||||
func ExtractFlavors(page pagination.Page) ([]Flavor, error) {
|
|
||||||
var response struct {
|
|
||||||
Flavors []Flavor `json:"flavors"`
|
|
||||||
}
|
|
||||||
|
|
||||||
err := mapstructure.Decode(page.(FlavorPage).Body, &response)
|
|
||||||
return response.Flavors, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetResult represents the result of a get operation.
|
|
||||||
type GetResult struct {
|
|
||||||
gophercloud.Result
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract is a function that extracts a flavor from a GetResult.
|
|
||||||
func (r GetResult) Extract() (*Flavor, error) {
|
|
||||||
if r.Err != nil {
|
|
||||||
return nil, r.Err
|
|
||||||
}
|
|
||||||
|
|
||||||
var res Flavor
|
|
||||||
|
|
||||||
err := mapstructure.Decode(r.Body, &res)
|
|
||||||
|
|
||||||
return &res, err
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
package flavors
|
|
||||||
|
|
||||||
import "github.com/rackspace/gophercloud"
|
|
||||||
|
|
||||||
func listURL(c *gophercloud.ServiceClient) string {
|
|
||||||
return c.ServiceURL("flavors")
|
|
||||||
}
|
|
||||||
|
|
||||||
func getURL(c *gophercloud.ServiceClient, id string) string {
|
|
||||||
return c.ServiceURL("flavors", id)
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
// Package serviceassets provides information and interaction with the
|
|
||||||
// serviceassets API resource in the OpenStack CDN service. This API resource
|
|
||||||
// allows for deleting cached assets.
|
|
||||||
//
|
|
||||||
// A service distributes assets across the network. Service assets let you
|
|
||||||
// interrogate properties about these assets and perform certain actions on them.
|
|
||||||
package serviceassets
|
|
19
vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/serviceassets/fixtures.go
generated
vendored
19
vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/serviceassets/fixtures.go
generated
vendored
|
@ -1,19 +0,0 @@
|
||||||
package serviceassets
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
th "github.com/rackspace/gophercloud/testhelper"
|
|
||||||
fake "github.com/rackspace/gophercloud/testhelper/client"
|
|
||||||
)
|
|
||||||
|
|
||||||
// HandleDeleteCDNAssetSuccessfully creates an HTTP handler at `/services/{id}/assets` on the test handler mux
|
|
||||||
// that responds with a `Delete` response.
|
|
||||||
func HandleDeleteCDNAssetSuccessfully(t *testing.T) {
|
|
||||||
th.Mux.HandleFunc("/services/96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0/assets", func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
th.TestMethod(t, r, "DELETE")
|
|
||||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
|
||||||
w.WriteHeader(http.StatusAccepted)
|
|
||||||
})
|
|
||||||
}
|
|
48
vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/serviceassets/requests.go
generated
vendored
48
vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/serviceassets/requests.go
generated
vendored
|
@ -1,48 +0,0 @@
|
||||||
package serviceassets
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/rackspace/gophercloud"
|
|
||||||
)
|
|
||||||
|
|
||||||
// DeleteOptsBuilder allows extensions to add additional parameters to the Delete
|
|
||||||
// request.
|
|
||||||
type DeleteOptsBuilder interface {
|
|
||||||
ToCDNAssetDeleteParams() (string, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteOpts is a structure that holds options for deleting CDN service assets.
|
|
||||||
type DeleteOpts struct {
|
|
||||||
// If all is set to true, specifies that the delete occurs against all of the
|
|
||||||
// assets for the service.
|
|
||||||
All bool `q:"all"`
|
|
||||||
// Specifies the relative URL of the asset to be deleted.
|
|
||||||
URL string `q:"url"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToCDNAssetDeleteParams formats a DeleteOpts into a query string.
|
|
||||||
func (opts DeleteOpts) ToCDNAssetDeleteParams() (string, error) {
|
|
||||||
q, err := gophercloud.BuildQueryString(opts)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return q.String(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete accepts a unique service ID or URL and deletes the CDN service asset associated with
|
|
||||||
// it. For example, both "96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0" and
|
|
||||||
// "https://global.cdn.api.rackspacecloud.com/v1.0/services/96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0"
|
|
||||||
// are valid options for idOrURL.
|
|
||||||
func Delete(c *gophercloud.ServiceClient, idOrURL string, opts DeleteOptsBuilder) DeleteResult {
|
|
||||||
var url string
|
|
||||||
if strings.Contains(idOrURL, "/") {
|
|
||||||
url = idOrURL
|
|
||||||
} else {
|
|
||||||
url = deleteURL(c, idOrURL)
|
|
||||||
}
|
|
||||||
|
|
||||||
var res DeleteResult
|
|
||||||
_, res.Err = c.Delete(url, nil)
|
|
||||||
return res
|
|
||||||
}
|
|
8
vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/serviceassets/results.go
generated
vendored
8
vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/serviceassets/results.go
generated
vendored
|
@ -1,8 +0,0 @@
|
||||||
package serviceassets
|
|
||||||
|
|
||||||
import "github.com/rackspace/gophercloud"
|
|
||||||
|
|
||||||
// DeleteResult represents the result of a Delete operation.
|
|
||||||
type DeleteResult struct {
|
|
||||||
gophercloud.ErrResult
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
package serviceassets
|
|
||||||
|
|
||||||
import "github.com/rackspace/gophercloud"
|
|
||||||
|
|
||||||
func deleteURL(c *gophercloud.ServiceClient, id string) string {
|
|
||||||
return c.ServiceURL("services", id, "assets")
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
// Package services provides information and interaction with the services API
|
|
||||||
// resource in the OpenStack CDN service. This API resource allows for
|
|
||||||
// listing, creating, updating, retrieving, and deleting services.
|
|
||||||
//
|
|
||||||
// A service represents an application that has its content cached to the edge
|
|
||||||
// nodes.
|
|
||||||
package services
|
|
|
@ -1,7 +0,0 @@
|
||||||
package services
|
|
||||||
|
|
||||||
import "fmt"
|
|
||||||
|
|
||||||
func no(str string) error {
|
|
||||||
return fmt.Errorf("Required parameter %s not provided", str)
|
|
||||||
}
|
|
372
vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/services/fixtures.go
generated
vendored
372
vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/services/fixtures.go
generated
vendored
|
@ -1,372 +0,0 @@
|
||||||
package services
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
th "github.com/rackspace/gophercloud/testhelper"
|
|
||||||
fake "github.com/rackspace/gophercloud/testhelper/client"
|
|
||||||
)
|
|
||||||
|
|
||||||
// HandleListCDNServiceSuccessfully creates an HTTP handler at `/services` on the test handler mux
|
|
||||||
// that responds with a `List` response.
|
|
||||||
func HandleListCDNServiceSuccessfully(t *testing.T) {
|
|
||||||
th.Mux.HandleFunc("/services", func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
th.TestMethod(t, r, "GET")
|
|
||||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
|
||||||
w.WriteHeader(http.StatusOK)
|
|
||||||
|
|
||||||
r.ParseForm()
|
|
||||||
marker := r.Form.Get("marker")
|
|
||||||
switch marker {
|
|
||||||
case "":
|
|
||||||
fmt.Fprintf(w, `
|
|
||||||
{
|
|
||||||
"links": [
|
|
||||||
{
|
|
||||||
"rel": "next",
|
|
||||||
"href": "https://www.poppycdn.io/v1.0/services?marker=96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0&limit=20"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"services": [
|
|
||||||
{
|
|
||||||
"id": "96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0",
|
|
||||||
"name": "mywebsite.com",
|
|
||||||
"domains": [
|
|
||||||
{
|
|
||||||
"domain": "www.mywebsite.com"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"origins": [
|
|
||||||
{
|
|
||||||
"origin": "mywebsite.com",
|
|
||||||
"port": 80,
|
|
||||||
"ssl": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"caching": [
|
|
||||||
{
|
|
||||||
"name": "default",
|
|
||||||
"ttl": 3600
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "home",
|
|
||||||
"ttl": 17200,
|
|
||||||
"rules": [
|
|
||||||
{
|
|
||||||
"name": "index",
|
|
||||||
"request_url": "/index.htm"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "images",
|
|
||||||
"ttl": 12800,
|
|
||||||
"rules": [
|
|
||||||
{
|
|
||||||
"name": "images",
|
|
||||||
"request_url": "*.png"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"restrictions": [
|
|
||||||
{
|
|
||||||
"name": "website only",
|
|
||||||
"rules": [
|
|
||||||
{
|
|
||||||
"name": "mywebsite.com",
|
|
||||||
"referrer": "www.mywebsite.com"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"flavor_id": "asia",
|
|
||||||
"status": "deployed",
|
|
||||||
"errors" : [],
|
|
||||||
"links": [
|
|
||||||
{
|
|
||||||
"href": "https://www.poppycdn.io/v1.0/services/96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0",
|
|
||||||
"rel": "self"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"href": "mywebsite.com.cdn123.poppycdn.net",
|
|
||||||
"rel": "access_url"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"href": "https://www.poppycdn.io/v1.0/flavors/asia",
|
|
||||||
"rel": "flavor"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "96737ae3-cfc1-4c72-be88-5d0e7cc9a3f1",
|
|
||||||
"name": "myothersite.com",
|
|
||||||
"domains": [
|
|
||||||
{
|
|
||||||
"domain": "www.myothersite.com"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"origins": [
|
|
||||||
{
|
|
||||||
"origin": "44.33.22.11",
|
|
||||||
"port": 80,
|
|
||||||
"ssl": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"origin": "77.66.55.44",
|
|
||||||
"port": 80,
|
|
||||||
"ssl": false,
|
|
||||||
"rules": [
|
|
||||||
{
|
|
||||||
"name": "videos",
|
|
||||||
"request_url": "^/videos/*.m3u"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"caching": [
|
|
||||||
{
|
|
||||||
"name": "default",
|
|
||||||
"ttl": 3600
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"restrictions": [
|
|
||||||
{}
|
|
||||||
],
|
|
||||||
"flavor_id": "europe",
|
|
||||||
"status": "deployed",
|
|
||||||
"links": [
|
|
||||||
{
|
|
||||||
"href": "https://www.poppycdn.io/v1.0/services/96737ae3-cfc1-4c72-be88-5d0e7cc9a3f1",
|
|
||||||
"rel": "self"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"href": "myothersite.com.poppycdn.net",
|
|
||||||
"rel": "access_url"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"href": "https://www.poppycdn.io/v1.0/flavors/europe",
|
|
||||||
"rel": "flavor"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
`)
|
|
||||||
case "96737ae3-cfc1-4c72-be88-5d0e7cc9a3f1":
|
|
||||||
fmt.Fprintf(w, `{
|
|
||||||
"services": []
|
|
||||||
}`)
|
|
||||||
default:
|
|
||||||
t.Fatalf("Unexpected marker: [%s]", marker)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// HandleCreateCDNServiceSuccessfully creates an HTTP handler at `/services` on the test handler mux
|
|
||||||
// that responds with a `Create` response.
|
|
||||||
func HandleCreateCDNServiceSuccessfully(t *testing.T) {
|
|
||||||
th.Mux.HandleFunc("/services", func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
th.TestMethod(t, r, "POST")
|
|
||||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
|
||||||
th.TestJSONRequest(t, r, `
|
|
||||||
{
|
|
||||||
"name": "mywebsite.com",
|
|
||||||
"domains": [
|
|
||||||
{
|
|
||||||
"domain": "www.mywebsite.com"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"domain": "blog.mywebsite.com"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"origins": [
|
|
||||||
{
|
|
||||||
"origin": "mywebsite.com",
|
|
||||||
"port": 80,
|
|
||||||
"ssl": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"restrictions": [
|
|
||||||
{
|
|
||||||
"name": "website only",
|
|
||||||
"rules": [
|
|
||||||
{
|
|
||||||
"name": "mywebsite.com",
|
|
||||||
"referrer": "www.mywebsite.com"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"caching": [
|
|
||||||
{
|
|
||||||
"name": "default",
|
|
||||||
"ttl": 3600
|
|
||||||
}
|
|
||||||
],
|
|
||||||
|
|
||||||
"flavor_id": "cdn"
|
|
||||||
}
|
|
||||||
`)
|
|
||||||
w.Header().Add("Location", "https://global.cdn.api.rackspacecloud.com/v1.0/services/96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0")
|
|
||||||
w.WriteHeader(http.StatusAccepted)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// HandleGetCDNServiceSuccessfully creates an HTTP handler at `/services/{id}` on the test handler mux
|
|
||||||
// that responds with a `Get` response.
|
|
||||||
func HandleGetCDNServiceSuccessfully(t *testing.T) {
|
|
||||||
th.Mux.HandleFunc("/services/96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0", func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
th.TestMethod(t, r, "GET")
|
|
||||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
|
||||||
w.WriteHeader(http.StatusOK)
|
|
||||||
fmt.Fprintf(w, `
|
|
||||||
{
|
|
||||||
"id": "96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0",
|
|
||||||
"name": "mywebsite.com",
|
|
||||||
"domains": [
|
|
||||||
{
|
|
||||||
"domain": "www.mywebsite.com",
|
|
||||||
"protocol": "http"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"origins": [
|
|
||||||
{
|
|
||||||
"origin": "mywebsite.com",
|
|
||||||
"port": 80,
|
|
||||||
"ssl": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"caching": [
|
|
||||||
{
|
|
||||||
"name": "default",
|
|
||||||
"ttl": 3600
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "home",
|
|
||||||
"ttl": 17200,
|
|
||||||
"rules": [
|
|
||||||
{
|
|
||||||
"name": "index",
|
|
||||||
"request_url": "/index.htm"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "images",
|
|
||||||
"ttl": 12800,
|
|
||||||
"rules": [
|
|
||||||
{
|
|
||||||
"name": "images",
|
|
||||||
"request_url": "*.png"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"restrictions": [
|
|
||||||
{
|
|
||||||
"name": "website only",
|
|
||||||
"rules": [
|
|
||||||
{
|
|
||||||
"name": "mywebsite.com",
|
|
||||||
"referrer": "www.mywebsite.com"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"flavor_id": "cdn",
|
|
||||||
"status": "deployed",
|
|
||||||
"errors" : [],
|
|
||||||
"links": [
|
|
||||||
{
|
|
||||||
"href": "https://global.cdn.api.rackspacecloud.com/v1.0/110011/services/96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0",
|
|
||||||
"rel": "self"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"href": "blog.mywebsite.com.cdn1.raxcdn.com",
|
|
||||||
"rel": "access_url"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"href": "https://global.cdn.api.rackspacecloud.com/v1.0/110011/flavors/cdn",
|
|
||||||
"rel": "flavor"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
`)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// HandleUpdateCDNServiceSuccessfully creates an HTTP handler at `/services/{id}` on the test handler mux
|
|
||||||
// that responds with a `Update` response.
|
|
||||||
func HandleUpdateCDNServiceSuccessfully(t *testing.T) {
|
|
||||||
th.Mux.HandleFunc("/services/96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0", func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
th.TestMethod(t, r, "PATCH")
|
|
||||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
|
||||||
th.TestJSONRequest(t, r, `
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"op": "add",
|
|
||||||
"path": "/domains/-",
|
|
||||||
"value": {"domain": "appended.mocksite4.com"}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"op": "add",
|
|
||||||
"path": "/domains/4",
|
|
||||||
"value": {"domain": "inserted.mocksite4.com"}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"op": "add",
|
|
||||||
"path": "/domains",
|
|
||||||
"value": [
|
|
||||||
{"domain": "bulkadded1.mocksite4.com"},
|
|
||||||
{"domain": "bulkadded2.mocksite4.com"}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"op": "replace",
|
|
||||||
"path": "/origins/2",
|
|
||||||
"value": {"origin": "44.33.22.11", "port": 80, "ssl": false}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"op": "replace",
|
|
||||||
"path": "/origins",
|
|
||||||
"value": [
|
|
||||||
{"origin": "44.33.22.11", "port": 80, "ssl": false},
|
|
||||||
{"origin": "55.44.33.22", "port": 443, "ssl": true}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"op": "remove",
|
|
||||||
"path": "/caching/8"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"op": "remove",
|
|
||||||
"path": "/caching"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"op": "replace",
|
|
||||||
"path": "/name",
|
|
||||||
"value": "differentServiceName"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
`)
|
|
||||||
w.Header().Add("Location", "https://www.poppycdn.io/v1.0/services/96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0")
|
|
||||||
w.WriteHeader(http.StatusAccepted)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// HandleDeleteCDNServiceSuccessfully creates an HTTP handler at `/services/{id}` on the test handler mux
|
|
||||||
// that responds with a `Delete` response.
|
|
||||||
func HandleDeleteCDNServiceSuccessfully(t *testing.T) {
|
|
||||||
th.Mux.HandleFunc("/services/96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0", func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
th.TestMethod(t, r, "DELETE")
|
|
||||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
|
||||||
w.WriteHeader(http.StatusAccepted)
|
|
||||||
})
|
|
||||||
}
|
|
378
vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/services/requests.go
generated
vendored
378
vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/services/requests.go
generated
vendored
|
@ -1,378 +0,0 @@
|
||||||
package services
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/rackspace/gophercloud"
|
|
||||||
"github.com/rackspace/gophercloud/pagination"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ListOptsBuilder allows extensions to add additional parameters to the
|
|
||||||
// List request.
|
|
||||||
type ListOptsBuilder interface {
|
|
||||||
ToCDNServiceListQuery() (string, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListOpts allows the filtering and sorting of paginated collections through
|
|
||||||
// the API. Marker and Limit are used for pagination.
|
|
||||||
type ListOpts struct {
|
|
||||||
Marker string `q:"marker"`
|
|
||||||
Limit int `q:"limit"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToCDNServiceListQuery formats a ListOpts into a query string.
|
|
||||||
func (opts ListOpts) ToCDNServiceListQuery() (string, error) {
|
|
||||||
q, err := gophercloud.BuildQueryString(opts)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return q.String(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// List returns a Pager which allows you to iterate over a collection of
|
|
||||||
// CDN services. It accepts a ListOpts struct, which allows for pagination via
|
|
||||||
// marker and limit.
|
|
||||||
func List(c *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager {
|
|
||||||
url := listURL(c)
|
|
||||||
if opts != nil {
|
|
||||||
query, err := opts.ToCDNServiceListQuery()
|
|
||||||
if err != nil {
|
|
||||||
return pagination.Pager{Err: err}
|
|
||||||
}
|
|
||||||
url += query
|
|
||||||
}
|
|
||||||
|
|
||||||
createPage := func(r pagination.PageResult) pagination.Page {
|
|
||||||
p := ServicePage{pagination.MarkerPageBase{PageResult: r}}
|
|
||||||
p.MarkerPageBase.Owner = p
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
pager := pagination.NewPager(c, url, createPage)
|
|
||||||
return pager
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateOptsBuilder is the interface options structs have to satisfy in order
|
|
||||||
// to be used in the main Create operation in this package. Since many
|
|
||||||
// extensions decorate or modify the common logic, it is useful for them to
|
|
||||||
// satisfy a basic interface in order for them to be used.
|
|
||||||
type CreateOptsBuilder interface {
|
|
||||||
ToCDNServiceCreateMap() (map[string]interface{}, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateOpts is the common options struct used in this package's Create
|
|
||||||
// operation.
|
|
||||||
type CreateOpts struct {
|
|
||||||
// REQUIRED. Specifies the name of the service. The minimum length for name is
|
|
||||||
// 3. The maximum length is 256.
|
|
||||||
Name string
|
|
||||||
// REQUIRED. Specifies a list of domains used by users to access their website.
|
|
||||||
Domains []Domain
|
|
||||||
// REQUIRED. Specifies a list of origin domains or IP addresses where the
|
|
||||||
// original assets are stored.
|
|
||||||
Origins []Origin
|
|
||||||
// REQUIRED. Specifies the CDN provider flavor ID to use. For a list of
|
|
||||||
// flavors, see the operation to list the available flavors. The minimum
|
|
||||||
// length for flavor_id is 1. The maximum length is 256.
|
|
||||||
FlavorID string
|
|
||||||
// OPTIONAL. Specifies the TTL rules for the assets under this service. Supports wildcards for fine-grained control.
|
|
||||||
Caching []CacheRule
|
|
||||||
// OPTIONAL. Specifies the restrictions that define who can access assets (content from the CDN cache).
|
|
||||||
Restrictions []Restriction
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToCDNServiceCreateMap casts a CreateOpts struct to a map.
|
|
||||||
func (opts CreateOpts) ToCDNServiceCreateMap() (map[string]interface{}, error) {
|
|
||||||
s := make(map[string]interface{})
|
|
||||||
|
|
||||||
if opts.Name == "" {
|
|
||||||
return nil, no("Name")
|
|
||||||
}
|
|
||||||
s["name"] = opts.Name
|
|
||||||
|
|
||||||
if opts.Domains == nil {
|
|
||||||
return nil, no("Domains")
|
|
||||||
}
|
|
||||||
for _, domain := range opts.Domains {
|
|
||||||
if domain.Domain == "" {
|
|
||||||
return nil, no("Domains[].Domain")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
s["domains"] = opts.Domains
|
|
||||||
|
|
||||||
if opts.Origins == nil {
|
|
||||||
return nil, no("Origins")
|
|
||||||
}
|
|
||||||
for _, origin := range opts.Origins {
|
|
||||||
if origin.Origin == "" {
|
|
||||||
return nil, no("Origins[].Origin")
|
|
||||||
}
|
|
||||||
if origin.Rules == nil && len(opts.Origins) > 1 {
|
|
||||||
return nil, no("Origins[].Rules")
|
|
||||||
}
|
|
||||||
for _, rule := range origin.Rules {
|
|
||||||
if rule.Name == "" {
|
|
||||||
return nil, no("Origins[].Rules[].Name")
|
|
||||||
}
|
|
||||||
if rule.RequestURL == "" {
|
|
||||||
return nil, no("Origins[].Rules[].RequestURL")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
s["origins"] = opts.Origins
|
|
||||||
|
|
||||||
if opts.FlavorID == "" {
|
|
||||||
return nil, no("FlavorID")
|
|
||||||
}
|
|
||||||
s["flavor_id"] = opts.FlavorID
|
|
||||||
|
|
||||||
if opts.Caching != nil {
|
|
||||||
for _, cache := range opts.Caching {
|
|
||||||
if cache.Name == "" {
|
|
||||||
return nil, no("Caching[].Name")
|
|
||||||
}
|
|
||||||
if cache.Rules != nil {
|
|
||||||
for _, rule := range cache.Rules {
|
|
||||||
if rule.Name == "" {
|
|
||||||
return nil, no("Caching[].Rules[].Name")
|
|
||||||
}
|
|
||||||
if rule.RequestURL == "" {
|
|
||||||
return nil, no("Caching[].Rules[].RequestURL")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
s["caching"] = opts.Caching
|
|
||||||
}
|
|
||||||
|
|
||||||
if opts.Restrictions != nil {
|
|
||||||
for _, restriction := range opts.Restrictions {
|
|
||||||
if restriction.Name == "" {
|
|
||||||
return nil, no("Restrictions[].Name")
|
|
||||||
}
|
|
||||||
if restriction.Rules != nil {
|
|
||||||
for _, rule := range restriction.Rules {
|
|
||||||
if rule.Name == "" {
|
|
||||||
return nil, no("Restrictions[].Rules[].Name")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
s["restrictions"] = opts.Restrictions
|
|
||||||
}
|
|
||||||
|
|
||||||
return s, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create accepts a CreateOpts struct and creates a new CDN service using the
|
|
||||||
// values provided.
|
|
||||||
func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
|
|
||||||
var res CreateResult
|
|
||||||
|
|
||||||
reqBody, err := opts.ToCDNServiceCreateMap()
|
|
||||||
if err != nil {
|
|
||||||
res.Err = err
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send request to API
|
|
||||||
resp, err := c.Post(createURL(c), &reqBody, nil, nil)
|
|
||||||
res.Header = resp.Header
|
|
||||||
res.Err = err
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get retrieves a specific service based on its URL or its unique ID. For
|
|
||||||
// example, both "96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0" and
|
|
||||||
// "https://global.cdn.api.rackspacecloud.com/v1.0/services/96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0"
|
|
||||||
// are valid options for idOrURL.
|
|
||||||
func Get(c *gophercloud.ServiceClient, idOrURL string) GetResult {
|
|
||||||
var url string
|
|
||||||
if strings.Contains(idOrURL, "/") {
|
|
||||||
url = idOrURL
|
|
||||||
} else {
|
|
||||||
url = getURL(c, idOrURL)
|
|
||||||
}
|
|
||||||
|
|
||||||
var res GetResult
|
|
||||||
_, res.Err = c.Get(url, &res.Body, nil)
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
// Path is a JSON pointer location that indicates which service parameter is being added, replaced,
|
|
||||||
// or removed.
|
|
||||||
type Path struct {
|
|
||||||
baseElement string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p Path) renderRoot() string {
|
|
||||||
return "/" + p.baseElement
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p Path) renderDash() string {
|
|
||||||
return fmt.Sprintf("/%s/-", p.baseElement)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p Path) renderIndex(index int64) string {
|
|
||||||
return fmt.Sprintf("/%s/%d", p.baseElement, index)
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
// PathDomains indicates that an update operation is to be performed on a Domain.
|
|
||||||
PathDomains = Path{baseElement: "domains"}
|
|
||||||
|
|
||||||
// PathOrigins indicates that an update operation is to be performed on an Origin.
|
|
||||||
PathOrigins = Path{baseElement: "origins"}
|
|
||||||
|
|
||||||
// PathCaching indicates that an update operation is to be performed on a CacheRule.
|
|
||||||
PathCaching = Path{baseElement: "caching"}
|
|
||||||
)
|
|
||||||
|
|
||||||
type value interface {
|
|
||||||
toPatchValue() interface{}
|
|
||||||
appropriatePath() Path
|
|
||||||
renderRootOr(func(p Path) string) string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Patch represents a single update to an existing Service. Multiple updates to a service can be
|
|
||||||
// submitted at the same time.
|
|
||||||
type Patch interface {
|
|
||||||
ToCDNServiceUpdateMap() map[string]interface{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insertion is a Patch that requests the addition of a value (Domain, Origin, or CacheRule) to
|
|
||||||
// a Service at a fixed index. Use an Append instead to append the new value to the end of its
|
|
||||||
// collection. Pass it to the Update function as part of the Patch slice.
|
|
||||||
type Insertion struct {
|
|
||||||
Index int64
|
|
||||||
Value value
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToCDNServiceUpdateMap converts an Insertion into a request body fragment suitable for the
|
|
||||||
// Update call.
|
|
||||||
func (i Insertion) ToCDNServiceUpdateMap() map[string]interface{} {
|
|
||||||
return map[string]interface{}{
|
|
||||||
"op": "add",
|
|
||||||
"path": i.Value.renderRootOr(func(p Path) string { return p.renderIndex(i.Index) }),
|
|
||||||
"value": i.Value.toPatchValue(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Append is a Patch that requests the addition of a value (Domain, Origin, or CacheRule) to a
|
|
||||||
// Service at the end of its respective collection. Use an Insertion instead to insert the value
|
|
||||||
// at a fixed index within the collection. Pass this to the Update function as part of its
|
|
||||||
// Patch slice.
|
|
||||||
type Append struct {
|
|
||||||
Value value
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToCDNServiceUpdateMap converts an Append into a request body fragment suitable for the
|
|
||||||
// Update call.
|
|
||||||
func (a Append) ToCDNServiceUpdateMap() map[string]interface{} {
|
|
||||||
return map[string]interface{}{
|
|
||||||
"op": "add",
|
|
||||||
"path": a.Value.renderRootOr(func(p Path) string { return p.renderDash() }),
|
|
||||||
"value": a.Value.toPatchValue(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Replacement is a Patch that alters a specific service parameter (Domain, Origin, or CacheRule)
|
|
||||||
// in-place by index. Pass it to the Update function as part of the Patch slice.
|
|
||||||
type Replacement struct {
|
|
||||||
Value value
|
|
||||||
Index int64
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToCDNServiceUpdateMap converts a Replacement into a request body fragment suitable for the
|
|
||||||
// Update call.
|
|
||||||
func (r Replacement) ToCDNServiceUpdateMap() map[string]interface{} {
|
|
||||||
return map[string]interface{}{
|
|
||||||
"op": "replace",
|
|
||||||
"path": r.Value.renderRootOr(func(p Path) string { return p.renderIndex(r.Index) }),
|
|
||||||
"value": r.Value.toPatchValue(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NameReplacement specifically updates the Service name. Pass it to the Update function as part
|
|
||||||
// of the Patch slice.
|
|
||||||
type NameReplacement struct {
|
|
||||||
NewName string
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToCDNServiceUpdateMap converts a NameReplacement into a request body fragment suitable for the
|
|
||||||
// Update call.
|
|
||||||
func (r NameReplacement) ToCDNServiceUpdateMap() map[string]interface{} {
|
|
||||||
return map[string]interface{}{
|
|
||||||
"op": "replace",
|
|
||||||
"path": "/name",
|
|
||||||
"value": r.NewName,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Removal is a Patch that requests the removal of a service parameter (Domain, Origin, or
|
|
||||||
// CacheRule) by index. Pass it to the Update function as part of the Patch slice.
|
|
||||||
type Removal struct {
|
|
||||||
Path Path
|
|
||||||
Index int64
|
|
||||||
All bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToCDNServiceUpdateMap converts a Removal into a request body fragment suitable for the
|
|
||||||
// Update call.
|
|
||||||
func (r Removal) ToCDNServiceUpdateMap() map[string]interface{} {
|
|
||||||
result := map[string]interface{}{"op": "remove"}
|
|
||||||
if r.All {
|
|
||||||
result["path"] = r.Path.renderRoot()
|
|
||||||
} else {
|
|
||||||
result["path"] = r.Path.renderIndex(r.Index)
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
type UpdateOpts []Patch
|
|
||||||
|
|
||||||
// Update accepts a slice of Patch operations (Insertion, Append, Replacement or Removal) and
|
|
||||||
// updates an existing CDN service using the values provided. idOrURL can be either the service's
|
|
||||||
// URL or its ID. For example, both "96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0" and
|
|
||||||
// "https://global.cdn.api.rackspacecloud.com/v1.0/services/96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0"
|
|
||||||
// are valid options for idOrURL.
|
|
||||||
func Update(c *gophercloud.ServiceClient, idOrURL string, opts UpdateOpts) UpdateResult {
|
|
||||||
var url string
|
|
||||||
if strings.Contains(idOrURL, "/") {
|
|
||||||
url = idOrURL
|
|
||||||
} else {
|
|
||||||
url = updateURL(c, idOrURL)
|
|
||||||
}
|
|
||||||
|
|
||||||
reqBody := make([]map[string]interface{}, len(opts))
|
|
||||||
for i, patch := range opts {
|
|
||||||
reqBody[i] = patch.ToCDNServiceUpdateMap()
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := c.Request("PATCH", url, gophercloud.RequestOpts{
|
|
||||||
JSONBody: &reqBody,
|
|
||||||
OkCodes: []int{202},
|
|
||||||
})
|
|
||||||
var result UpdateResult
|
|
||||||
result.Header = resp.Header
|
|
||||||
result.Err = err
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete accepts a service's ID or its URL and deletes the CDN service
|
|
||||||
// associated with it. For example, both "96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0" and
|
|
||||||
// "https://global.cdn.api.rackspacecloud.com/v1.0/services/96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0"
|
|
||||||
// are valid options for idOrURL.
|
|
||||||
func Delete(c *gophercloud.ServiceClient, idOrURL string) DeleteResult {
|
|
||||||
var url string
|
|
||||||
if strings.Contains(idOrURL, "/") {
|
|
||||||
url = idOrURL
|
|
||||||
} else {
|
|
||||||
url = deleteURL(c, idOrURL)
|
|
||||||
}
|
|
||||||
|
|
||||||
var res DeleteResult
|
|
||||||
_, res.Err = c.Delete(url, nil)
|
|
||||||
return res
|
|
||||||
}
|
|
|
@ -1,316 +0,0 @@
|
||||||
package services
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/rackspace/gophercloud"
|
|
||||||
"github.com/rackspace/gophercloud/pagination"
|
|
||||||
|
|
||||||
"github.com/mitchellh/mapstructure"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Domain represents a domain used by users to access their website.
|
|
||||||
type Domain struct {
|
|
||||||
// Specifies the domain used to access the assets on their website, for which
|
|
||||||
// a CNAME is given to the CDN provider.
|
|
||||||
Domain string `mapstructure:"domain" json:"domain"`
|
|
||||||
// Specifies the protocol used to access the assets on this domain. Only "http"
|
|
||||||
// or "https" are currently allowed. The default is "http".
|
|
||||||
Protocol string `mapstructure:"protocol" json:"protocol,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d Domain) toPatchValue() interface{} {
|
|
||||||
r := make(map[string]interface{})
|
|
||||||
r["domain"] = d.Domain
|
|
||||||
if d.Protocol != "" {
|
|
||||||
r["protocol"] = d.Protocol
|
|
||||||
}
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d Domain) appropriatePath() Path {
|
|
||||||
return PathDomains
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d Domain) renderRootOr(render func(p Path) string) string {
|
|
||||||
return render(d.appropriatePath())
|
|
||||||
}
|
|
||||||
|
|
||||||
// DomainList provides a useful way to perform bulk operations in a single Patch.
|
|
||||||
type DomainList []Domain
|
|
||||||
|
|
||||||
func (list DomainList) toPatchValue() interface{} {
|
|
||||||
r := make([]interface{}, len(list))
|
|
||||||
for i, domain := range list {
|
|
||||||
r[i] = domain.toPatchValue()
|
|
||||||
}
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
func (list DomainList) appropriatePath() Path {
|
|
||||||
return PathDomains
|
|
||||||
}
|
|
||||||
|
|
||||||
func (list DomainList) renderRootOr(_ func(p Path) string) string {
|
|
||||||
return list.appropriatePath().renderRoot()
|
|
||||||
}
|
|
||||||
|
|
||||||
// OriginRule represents a rule that defines when an origin should be accessed.
|
|
||||||
type OriginRule struct {
|
|
||||||
// Specifies the name of this rule.
|
|
||||||
Name string `mapstructure:"name" json:"name"`
|
|
||||||
// Specifies the request URL this rule should match for this origin to be used. Regex is supported.
|
|
||||||
RequestURL string `mapstructure:"request_url" json:"request_url"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Origin specifies a list of origin domains or IP addresses where the original assets are stored.
|
|
||||||
type Origin struct {
|
|
||||||
// Specifies the URL or IP address to pull origin content from.
|
|
||||||
Origin string `mapstructure:"origin" json:"origin"`
|
|
||||||
// Specifies the port used to access the origin. The default is port 80.
|
|
||||||
Port int `mapstructure:"port" json:"port,omitempty"`
|
|
||||||
// Specifies whether or not to use HTTPS to access the origin. The default
|
|
||||||
// is false.
|
|
||||||
SSL bool `mapstructure:"ssl" json:"ssl"`
|
|
||||||
// Specifies a collection of rules that define the conditions when this origin
|
|
||||||
// should be accessed. If there is more than one origin, the rules parameter is required.
|
|
||||||
Rules []OriginRule `mapstructure:"rules" json:"rules,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (o Origin) toPatchValue() interface{} {
|
|
||||||
r := make(map[string]interface{})
|
|
||||||
r["origin"] = o.Origin
|
|
||||||
r["port"] = o.Port
|
|
||||||
r["ssl"] = o.SSL
|
|
||||||
if len(o.Rules) > 0 {
|
|
||||||
r["rules"] = make([]map[string]interface{}, len(o.Rules))
|
|
||||||
for index, rule := range o.Rules {
|
|
||||||
submap := r["rules"].([]map[string]interface{})[index]
|
|
||||||
submap["name"] = rule.Name
|
|
||||||
submap["request_url"] = rule.RequestURL
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
func (o Origin) appropriatePath() Path {
|
|
||||||
return PathOrigins
|
|
||||||
}
|
|
||||||
|
|
||||||
func (o Origin) renderRootOr(render func(p Path) string) string {
|
|
||||||
return render(o.appropriatePath())
|
|
||||||
}
|
|
||||||
|
|
||||||
// OriginList provides a useful way to perform bulk operations in a single Patch.
|
|
||||||
type OriginList []Origin
|
|
||||||
|
|
||||||
func (list OriginList) toPatchValue() interface{} {
|
|
||||||
r := make([]interface{}, len(list))
|
|
||||||
for i, origin := range list {
|
|
||||||
r[i] = origin.toPatchValue()
|
|
||||||
}
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
func (list OriginList) appropriatePath() Path {
|
|
||||||
return PathOrigins
|
|
||||||
}
|
|
||||||
|
|
||||||
func (list OriginList) renderRootOr(_ func(p Path) string) string {
|
|
||||||
return list.appropriatePath().renderRoot()
|
|
||||||
}
|
|
||||||
|
|
||||||
// TTLRule specifies a rule that determines if a TTL should be applied to an asset.
|
|
||||||
type TTLRule struct {
|
|
||||||
// Specifies the name of this rule.
|
|
||||||
Name string `mapstructure:"name" json:"name"`
|
|
||||||
// Specifies the request URL this rule should match for this TTL to be used. Regex is supported.
|
|
||||||
RequestURL string `mapstructure:"request_url" json:"request_url"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// CacheRule specifies the TTL rules for the assets under this service.
|
|
||||||
type CacheRule struct {
|
|
||||||
// Specifies the name of this caching rule. Note: 'default' is a reserved name used for the default TTL setting.
|
|
||||||
Name string `mapstructure:"name" json:"name"`
|
|
||||||
// Specifies the TTL to apply.
|
|
||||||
TTL int `mapstructure:"ttl" json:"ttl"`
|
|
||||||
// Specifies a collection of rules that determine if this TTL should be applied to an asset.
|
|
||||||
Rules []TTLRule `mapstructure:"rules" json:"rules,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c CacheRule) toPatchValue() interface{} {
|
|
||||||
r := make(map[string]interface{})
|
|
||||||
r["name"] = c.Name
|
|
||||||
r["ttl"] = c.TTL
|
|
||||||
r["rules"] = make([]map[string]interface{}, len(c.Rules))
|
|
||||||
for index, rule := range c.Rules {
|
|
||||||
submap := r["rules"].([]map[string]interface{})[index]
|
|
||||||
submap["name"] = rule.Name
|
|
||||||
submap["request_url"] = rule.RequestURL
|
|
||||||
}
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c CacheRule) appropriatePath() Path {
|
|
||||||
return PathCaching
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c CacheRule) renderRootOr(render func(p Path) string) string {
|
|
||||||
return render(c.appropriatePath())
|
|
||||||
}
|
|
||||||
|
|
||||||
// CacheRuleList provides a useful way to perform bulk operations in a single Patch.
|
|
||||||
type CacheRuleList []CacheRule
|
|
||||||
|
|
||||||
func (list CacheRuleList) toPatchValue() interface{} {
|
|
||||||
r := make([]interface{}, len(list))
|
|
||||||
for i, rule := range list {
|
|
||||||
r[i] = rule.toPatchValue()
|
|
||||||
}
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
func (list CacheRuleList) appropriatePath() Path {
|
|
||||||
return PathCaching
|
|
||||||
}
|
|
||||||
|
|
||||||
func (list CacheRuleList) renderRootOr(_ func(p Path) string) string {
|
|
||||||
return list.appropriatePath().renderRoot()
|
|
||||||
}
|
|
||||||
|
|
||||||
// RestrictionRule specifies a rule that determines if this restriction should be applied to an asset.
|
|
||||||
type RestrictionRule struct {
|
|
||||||
// Specifies the name of this rule.
|
|
||||||
Name string `mapstructure:"name" json:"name"`
|
|
||||||
// Specifies the http host that requests must come from.
|
|
||||||
Referrer string `mapstructure:"referrer" json:"referrer,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Restriction specifies a restriction that defines who can access assets (content from the CDN cache).
|
|
||||||
type Restriction struct {
|
|
||||||
// Specifies the name of this restriction.
|
|
||||||
Name string `mapstructure:"name" json:"name"`
|
|
||||||
// Specifies a collection of rules that determine if this TTL should be applied to an asset.
|
|
||||||
Rules []RestrictionRule `mapstructure:"rules" json:"rules"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error specifies an error that occurred during the previous service action.
|
|
||||||
type Error struct {
|
|
||||||
// Specifies an error message detailing why there is an error.
|
|
||||||
Message string `mapstructure:"message"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Service represents a CDN service resource.
|
|
||||||
type Service struct {
|
|
||||||
// Specifies the service ID that represents distributed content. The value is
|
|
||||||
// a UUID, such as 96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0, that is generated by the server.
|
|
||||||
ID string `mapstructure:"id"`
|
|
||||||
// Specifies the name of the service.
|
|
||||||
Name string `mapstructure:"name"`
|
|
||||||
// Specifies a list of domains used by users to access their website.
|
|
||||||
Domains []Domain `mapstructure:"domains"`
|
|
||||||
// Specifies a list of origin domains or IP addresses where the original assets are stored.
|
|
||||||
Origins []Origin `mapstructure:"origins"`
|
|
||||||
// Specifies the TTL rules for the assets under this service. Supports wildcards for fine grained control.
|
|
||||||
Caching []CacheRule `mapstructure:"caching"`
|
|
||||||
// Specifies the restrictions that define who can access assets (content from the CDN cache).
|
|
||||||
Restrictions []Restriction `mapstructure:"restrictions" json:"restrictions,omitempty"`
|
|
||||||
// Specifies the CDN provider flavor ID to use. For a list of flavors, see the operation to list the available flavors.
|
|
||||||
FlavorID string `mapstructure:"flavor_id"`
|
|
||||||
// Specifies the current status of the service.
|
|
||||||
Status string `mapstructure:"status"`
|
|
||||||
// Specifies the list of errors that occurred during the previous service action.
|
|
||||||
Errors []Error `mapstructure:"errors"`
|
|
||||||
// Specifies the self-navigating JSON document paths.
|
|
||||||
Links []gophercloud.Link `mapstructure:"links"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ServicePage is the page returned by a pager when traversing over a
|
|
||||||
// collection of CDN services.
|
|
||||||
type ServicePage struct {
|
|
||||||
pagination.MarkerPageBase
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsEmpty returns true if a ListResult contains no services.
|
|
||||||
func (r ServicePage) IsEmpty() (bool, error) {
|
|
||||||
services, err := ExtractServices(r)
|
|
||||||
if err != nil {
|
|
||||||
return true, err
|
|
||||||
}
|
|
||||||
return len(services) == 0, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// LastMarker returns the last service in a ListResult.
|
|
||||||
func (r ServicePage) LastMarker() (string, error) {
|
|
||||||
services, err := ExtractServices(r)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
if len(services) == 0 {
|
|
||||||
return "", nil
|
|
||||||
}
|
|
||||||
return (services[len(services)-1]).ID, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExtractServices is a function that takes a ListResult and returns the services' information.
|
|
||||||
func ExtractServices(page pagination.Page) ([]Service, error) {
|
|
||||||
var response struct {
|
|
||||||
Services []Service `mapstructure:"services"`
|
|
||||||
}
|
|
||||||
|
|
||||||
err := mapstructure.Decode(page.(ServicePage).Body, &response)
|
|
||||||
return response.Services, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateResult represents the result of a Create operation.
|
|
||||||
type CreateResult struct {
|
|
||||||
gophercloud.Result
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract is a method that extracts the location of a newly created service.
|
|
||||||
func (r CreateResult) Extract() (string, error) {
|
|
||||||
if r.Err != nil {
|
|
||||||
return "", r.Err
|
|
||||||
}
|
|
||||||
if l, ok := r.Header["Location"]; ok && len(l) > 0 {
|
|
||||||
return l[0], nil
|
|
||||||
}
|
|
||||||
return "", nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetResult represents the result of a get operation.
|
|
||||||
type GetResult struct {
|
|
||||||
gophercloud.Result
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract is a function that extracts a service from a GetResult.
|
|
||||||
func (r GetResult) Extract() (*Service, error) {
|
|
||||||
if r.Err != nil {
|
|
||||||
return nil, r.Err
|
|
||||||
}
|
|
||||||
|
|
||||||
var res Service
|
|
||||||
|
|
||||||
err := mapstructure.Decode(r.Body, &res)
|
|
||||||
|
|
||||||
return &res, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateResult represents the result of a Update operation.
|
|
||||||
type UpdateResult struct {
|
|
||||||
gophercloud.Result
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract is a method that extracts the location of an updated service.
|
|
||||||
func (r UpdateResult) Extract() (string, error) {
|
|
||||||
if r.Err != nil {
|
|
||||||
return "", r.Err
|
|
||||||
}
|
|
||||||
if l, ok := r.Header["Location"]; ok && len(l) > 0 {
|
|
||||||
return l[0], nil
|
|
||||||
}
|
|
||||||
return "", nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteResult represents the result of a Delete operation.
|
|
||||||
type DeleteResult struct {
|
|
||||||
gophercloud.ErrResult
|
|
||||||
}
|
|
|
@ -1,23 +0,0 @@
|
||||||
package services
|
|
||||||
|
|
||||||
import "github.com/rackspace/gophercloud"
|
|
||||||
|
|
||||||
func listURL(c *gophercloud.ServiceClient) string {
|
|
||||||
return c.ServiceURL("services")
|
|
||||||
}
|
|
||||||
|
|
||||||
func createURL(c *gophercloud.ServiceClient) string {
|
|
||||||
return listURL(c)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getURL(c *gophercloud.ServiceClient, id string) string {
|
|
||||||
return c.ServiceURL("services", id)
|
|
||||||
}
|
|
||||||
|
|
||||||
func updateURL(c *gophercloud.ServiceClient, id string) string {
|
|
||||||
return getURL(c, id)
|
|
||||||
}
|
|
||||||
|
|
||||||
func deleteURL(c *gophercloud.ServiceClient, id string) string {
|
|
||||||
return getURL(c, id)
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
# Common Resources
|
|
||||||
|
|
||||||
This directory is for resources that are shared by multiple services.
|
|
|
@ -1,118 +0,0 @@
|
||||||
package bootfromvolume
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/rackspace/gophercloud"
|
|
||||||
"github.com/rackspace/gophercloud/openstack/compute/v2/servers"
|
|
||||||
)
|
|
||||||
|
|
||||||
// SourceType represents the type of medium being used to create the volume.
|
|
||||||
type SourceType string
|
|
||||||
|
|
||||||
const (
|
|
||||||
Volume SourceType = "volume"
|
|
||||||
Snapshot SourceType = "snapshot"
|
|
||||||
Image SourceType = "image"
|
|
||||||
Blank SourceType = "blank"
|
|
||||||
)
|
|
||||||
|
|
||||||
// BlockDevice is a structure with options for booting a server instance
|
|
||||||
// from a volume. The volume may be created from an image, snapshot, or another
|
|
||||||
// volume.
|
|
||||||
type BlockDevice struct {
|
|
||||||
// BootIndex [optional] is the boot index. It defaults to 0.
|
|
||||||
BootIndex int `json:"boot_index"`
|
|
||||||
|
|
||||||
// DeleteOnTermination [optional] specifies whether or not to delete the attached volume
|
|
||||||
// when the server is deleted. Defaults to `false`.
|
|
||||||
DeleteOnTermination bool `json:"delete_on_termination"`
|
|
||||||
|
|
||||||
// DestinationType [optional] is the type that gets created. Possible values are "volume"
|
|
||||||
// and "local".
|
|
||||||
DestinationType string `json:"destination_type"`
|
|
||||||
|
|
||||||
// GuestFormat [optional] specifies the format of the block device.
|
|
||||||
GuestFormat string `json:"guest_format"`
|
|
||||||
|
|
||||||
// SourceType [required] must be one of: "volume", "snapshot", "image".
|
|
||||||
SourceType SourceType `json:"source_type"`
|
|
||||||
|
|
||||||
// UUID [required] is the unique identifier for the volume, snapshot, or image (see above)
|
|
||||||
UUID string `json:"uuid"`
|
|
||||||
|
|
||||||
// VolumeSize [optional] is the size of the volume to create (in gigabytes).
|
|
||||||
VolumeSize int `json:"volume_size"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateOptsExt is a structure that extends the server `CreateOpts` structure
|
|
||||||
// by allowing for a block device mapping.
|
|
||||||
type CreateOptsExt struct {
|
|
||||||
servers.CreateOptsBuilder
|
|
||||||
BlockDevice []BlockDevice `json:"block_device_mapping_v2,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToServerCreateMap adds the block device mapping option to the base server
|
|
||||||
// creation options.
|
|
||||||
func (opts CreateOptsExt) ToServerCreateMap() (map[string]interface{}, error) {
|
|
||||||
base, err := opts.CreateOptsBuilder.ToServerCreateMap()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(opts.BlockDevice) == 0 {
|
|
||||||
return nil, errors.New("Required fields UUID and SourceType not set.")
|
|
||||||
}
|
|
||||||
|
|
||||||
serverMap := base["server"].(map[string]interface{})
|
|
||||||
|
|
||||||
blockDevice := make([]map[string]interface{}, len(opts.BlockDevice))
|
|
||||||
|
|
||||||
for i, bd := range opts.BlockDevice {
|
|
||||||
if string(bd.SourceType) == "" {
|
|
||||||
return nil, errors.New("SourceType must be one of: volume, image, snapshot.")
|
|
||||||
}
|
|
||||||
|
|
||||||
blockDevice[i] = make(map[string]interface{})
|
|
||||||
|
|
||||||
blockDevice[i]["source_type"] = bd.SourceType
|
|
||||||
blockDevice[i]["boot_index"] = strconv.Itoa(bd.BootIndex)
|
|
||||||
blockDevice[i]["delete_on_termination"] = strconv.FormatBool(bd.DeleteOnTermination)
|
|
||||||
blockDevice[i]["volume_size"] = strconv.Itoa(bd.VolumeSize)
|
|
||||||
if bd.UUID != "" {
|
|
||||||
blockDevice[i]["uuid"] = bd.UUID
|
|
||||||
}
|
|
||||||
if bd.DestinationType != "" {
|
|
||||||
blockDevice[i]["destination_type"] = bd.DestinationType
|
|
||||||
}
|
|
||||||
if bd.GuestFormat != "" {
|
|
||||||
blockDevice[i]["guest_format"] = bd.GuestFormat
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
serverMap["block_device_mapping_v2"] = blockDevice
|
|
||||||
|
|
||||||
return base, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create requests the creation of a server from the given block device mapping.
|
|
||||||
func Create(client *gophercloud.ServiceClient, opts servers.CreateOptsBuilder) servers.CreateResult {
|
|
||||||
var res servers.CreateResult
|
|
||||||
|
|
||||||
reqBody, err := opts.ToServerCreateMap()
|
|
||||||
if err != nil {
|
|
||||||
res.Err = err
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete imageName and flavorName that come from ToServerCreateMap().
|
|
||||||
// As of Liberty, Boot From Volume is failing if they are passed.
|
|
||||||
delete(reqBody["server"].(map[string]interface{}), "imageName")
|
|
||||||
delete(reqBody["server"].(map[string]interface{}), "flavorName")
|
|
||||||
|
|
||||||
_, res.Err = client.Post(createURL(client), reqBody, &res.Body, &gophercloud.RequestOpts{
|
|
||||||
OkCodes: []int{200, 202},
|
|
||||||
})
|
|
||||||
return res
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
package bootfromvolume
|
|
||||||
|
|
||||||
import (
|
|
||||||
os "github.com/rackspace/gophercloud/openstack/compute/v2/servers"
|
|
||||||
)
|
|
||||||
|
|
||||||
// CreateResult temporarily contains the response from a Create call.
|
|
||||||
type CreateResult struct {
|
|
||||||
os.CreateResult
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
package bootfromvolume
|
|
||||||
|
|
||||||
import "github.com/rackspace/gophercloud"
|
|
||||||
|
|
||||||
func createURL(c *gophercloud.ServiceClient) string {
|
|
||||||
return c.ServiceURL("os-volumes_boot")
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
package defsecrules
|
|
|
@ -1,108 +0,0 @@
|
||||||
package defsecrules
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
th "github.com/rackspace/gophercloud/testhelper"
|
|
||||||
fake "github.com/rackspace/gophercloud/testhelper/client"
|
|
||||||
)
|
|
||||||
|
|
||||||
const rootPath = "/os-security-group-default-rules"
|
|
||||||
|
|
||||||
func mockListRulesResponse(t *testing.T) {
|
|
||||||
th.Mux.HandleFunc(rootPath, 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")
|
|
||||||
w.WriteHeader(http.StatusOK)
|
|
||||||
|
|
||||||
fmt.Fprintf(w, `
|
|
||||||
{
|
|
||||||
"security_group_default_rules": [
|
|
||||||
{
|
|
||||||
"from_port": 80,
|
|
||||||
"id": "{ruleID}",
|
|
||||||
"ip_protocol": "TCP",
|
|
||||||
"ip_range": {
|
|
||||||
"cidr": "10.10.10.0/24"
|
|
||||||
},
|
|
||||||
"to_port": 80
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
`)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func mockCreateRuleResponse(t *testing.T) {
|
|
||||||
th.Mux.HandleFunc(rootPath, func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
th.TestMethod(t, r, "POST")
|
|
||||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
|
||||||
|
|
||||||
th.TestJSONRequest(t, r, `
|
|
||||||
{
|
|
||||||
"security_group_default_rule": {
|
|
||||||
"ip_protocol": "TCP",
|
|
||||||
"from_port": 80,
|
|
||||||
"to_port": 80,
|
|
||||||
"cidr": "10.10.12.0/24"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`)
|
|
||||||
|
|
||||||
w.Header().Add("Content-Type", "application/json")
|
|
||||||
w.WriteHeader(http.StatusOK)
|
|
||||||
|
|
||||||
fmt.Fprintf(w, `
|
|
||||||
{
|
|
||||||
"security_group_default_rule": {
|
|
||||||
"from_port": 80,
|
|
||||||
"id": "{ruleID}",
|
|
||||||
"ip_protocol": "TCP",
|
|
||||||
"ip_range": {
|
|
||||||
"cidr": "10.10.12.0/24"
|
|
||||||
},
|
|
||||||
"to_port": 80
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func mockGetRuleResponse(t *testing.T, ruleID string) {
|
|
||||||
url := rootPath + "/" + ruleID
|
|
||||||
th.Mux.HandleFunc(url, 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")
|
|
||||||
w.WriteHeader(http.StatusOK)
|
|
||||||
|
|
||||||
fmt.Fprintf(w, `
|
|
||||||
{
|
|
||||||
"security_group_default_rule": {
|
|
||||||
"id": "{ruleID}",
|
|
||||||
"from_port": 80,
|
|
||||||
"to_port": 80,
|
|
||||||
"ip_protocol": "TCP",
|
|
||||||
"ip_range": {
|
|
||||||
"cidr": "10.10.12.0/24"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func mockDeleteRuleResponse(t *testing.T, ruleID string) {
|
|
||||||
url := rootPath + "/" + ruleID
|
|
||||||
th.Mux.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
th.TestMethod(t, r, "DELETE")
|
|
||||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
|
||||||
w.Header().Add("Content-Type", "application/json")
|
|
||||||
w.WriteHeader(http.StatusNoContent)
|
|
||||||
})
|
|
||||||
}
|
|
|
@ -1,95 +0,0 @@
|
||||||
package defsecrules
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
|
|
||||||
"github.com/rackspace/gophercloud"
|
|
||||||
"github.com/rackspace/gophercloud/pagination"
|
|
||||||
)
|
|
||||||
|
|
||||||
// List will return a collection of default rules.
|
|
||||||
func List(client *gophercloud.ServiceClient) pagination.Pager {
|
|
||||||
createPage := func(r pagination.PageResult) pagination.Page {
|
|
||||||
return DefaultRulePage{pagination.SinglePageBase(r)}
|
|
||||||
}
|
|
||||||
|
|
||||||
return pagination.NewPager(client, rootURL(client), createPage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateOpts represents the configuration for adding a new default rule.
|
|
||||||
type CreateOpts struct {
|
|
||||||
// Required - the lower bound of the port range that will be opened.
|
|
||||||
FromPort int `json:"from_port"`
|
|
||||||
|
|
||||||
// Required - the upper bound of the port range that will be opened.
|
|
||||||
ToPort int `json:"to_port"`
|
|
||||||
|
|
||||||
// Required - the protocol type that will be allowed, e.g. TCP.
|
|
||||||
IPProtocol string `json:"ip_protocol"`
|
|
||||||
|
|
||||||
// ONLY required if FromGroupID is blank. This represents the IP range that
|
|
||||||
// will be the source of network traffic to your security group. Use
|
|
||||||
// 0.0.0.0/0 to allow all IP addresses.
|
|
||||||
CIDR string `json:"cidr,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateOptsBuilder builds the create rule options into a serializable format.
|
|
||||||
type CreateOptsBuilder interface {
|
|
||||||
ToRuleCreateMap() (map[string]interface{}, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToRuleCreateMap builds the create rule options into a serializable format.
|
|
||||||
func (opts CreateOpts) ToRuleCreateMap() (map[string]interface{}, error) {
|
|
||||||
rule := make(map[string]interface{})
|
|
||||||
|
|
||||||
if opts.FromPort == 0 {
|
|
||||||
return rule, errors.New("A FromPort must be set")
|
|
||||||
}
|
|
||||||
if opts.ToPort == 0 {
|
|
||||||
return rule, errors.New("A ToPort must be set")
|
|
||||||
}
|
|
||||||
if opts.IPProtocol == "" {
|
|
||||||
return rule, errors.New("A IPProtocol must be set")
|
|
||||||
}
|
|
||||||
if opts.CIDR == "" {
|
|
||||||
return rule, errors.New("A CIDR must be set")
|
|
||||||
}
|
|
||||||
|
|
||||||
rule["from_port"] = opts.FromPort
|
|
||||||
rule["to_port"] = opts.ToPort
|
|
||||||
rule["ip_protocol"] = opts.IPProtocol
|
|
||||||
rule["cidr"] = opts.CIDR
|
|
||||||
|
|
||||||
return map[string]interface{}{"security_group_default_rule": rule}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create is the operation responsible for creating a new default rule.
|
|
||||||
func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
|
|
||||||
var result CreateResult
|
|
||||||
|
|
||||||
reqBody, err := opts.ToRuleCreateMap()
|
|
||||||
if err != nil {
|
|
||||||
result.Err = err
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
_, result.Err = client.Post(rootURL(client), reqBody, &result.Body, &gophercloud.RequestOpts{
|
|
||||||
OkCodes: []int{200},
|
|
||||||
})
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get will return details for a particular default rule.
|
|
||||||
func Get(client *gophercloud.ServiceClient, id string) GetResult {
|
|
||||||
var result GetResult
|
|
||||||
_, result.Err = client.Get(resourceURL(client, id), &result.Body, nil)
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete will permanently delete a default rule from the project.
|
|
||||||
func Delete(client *gophercloud.ServiceClient, id string) gophercloud.ErrResult {
|
|
||||||
var result gophercloud.ErrResult
|
|
||||||
_, result.Err = client.Delete(resourceURL(client, id), nil)
|
|
||||||
return result
|
|
||||||
}
|
|
|
@ -1,69 +0,0 @@
|
||||||
package defsecrules
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/mitchellh/mapstructure"
|
|
||||||
|
|
||||||
"github.com/rackspace/gophercloud"
|
|
||||||
"github.com/rackspace/gophercloud/openstack/compute/v2/extensions/secgroups"
|
|
||||||
"github.com/rackspace/gophercloud/pagination"
|
|
||||||
)
|
|
||||||
|
|
||||||
// DefaultRule represents a default rule - which is identical to a
|
|
||||||
// normal security rule.
|
|
||||||
type DefaultRule secgroups.Rule
|
|
||||||
|
|
||||||
// DefaultRulePage is a single page of a DefaultRule collection.
|
|
||||||
type DefaultRulePage struct {
|
|
||||||
pagination.SinglePageBase
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsEmpty determines whether or not a page of default rules contains any results.
|
|
||||||
func (page DefaultRulePage) IsEmpty() (bool, error) {
|
|
||||||
users, err := ExtractDefaultRules(page)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
return len(users) == 0, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExtractDefaultRules returns a slice of DefaultRules contained in a single
|
|
||||||
// page of results.
|
|
||||||
func ExtractDefaultRules(page pagination.Page) ([]DefaultRule, error) {
|
|
||||||
casted := page.(DefaultRulePage).Body
|
|
||||||
var response struct {
|
|
||||||
Rules []DefaultRule `mapstructure:"security_group_default_rules"`
|
|
||||||
}
|
|
||||||
|
|
||||||
err := mapstructure.WeakDecode(casted, &response)
|
|
||||||
|
|
||||||
return response.Rules, err
|
|
||||||
}
|
|
||||||
|
|
||||||
type commonResult struct {
|
|
||||||
gophercloud.Result
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateResult represents the result of a create operation.
|
|
||||||
type CreateResult struct {
|
|
||||||
commonResult
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetResult represents the result of a get operation.
|
|
||||||
type GetResult struct {
|
|
||||||
commonResult
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract will extract a DefaultRule struct from most responses.
|
|
||||||
func (r commonResult) Extract() (*DefaultRule, error) {
|
|
||||||
if r.Err != nil {
|
|
||||||
return nil, r.Err
|
|
||||||
}
|
|
||||||
|
|
||||||
var response struct {
|
|
||||||
Rule DefaultRule `mapstructure:"security_group_default_rule"`
|
|
||||||
}
|
|
||||||
|
|
||||||
err := mapstructure.WeakDecode(r.Body, &response)
|
|
||||||
|
|
||||||
return &response.Rule, err
|
|
||||||
}
|
|
|
@ -1,13 +0,0 @@
|
||||||
package defsecrules
|
|
||||||
|
|
||||||
import "github.com/rackspace/gophercloud"
|
|
||||||
|
|
||||||
const rulepath = "os-security-group-default-rules"
|
|
||||||
|
|
||||||
func resourceURL(c *gophercloud.ServiceClient, id string) string {
|
|
||||||
return c.ServiceURL(rulepath, id)
|
|
||||||
}
|
|
||||||
|
|
||||||
func rootURL(c *gophercloud.ServiceClient) string {
|
|
||||||
return c.ServiceURL(rulepath)
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
// Package diskconfig provides information and interaction with the Disk
|
|
||||||
// Config extension that works with the OpenStack Compute service.
|
|
||||||
package diskconfig
|
|
|
@ -1,114 +0,0 @@
|
||||||
package diskconfig
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
|
|
||||||
"github.com/rackspace/gophercloud/openstack/compute/v2/servers"
|
|
||||||
)
|
|
||||||
|
|
||||||
// DiskConfig represents one of the two possible settings for the DiskConfig option when creating,
|
|
||||||
// rebuilding, or resizing servers: Auto or Manual.
|
|
||||||
type DiskConfig string
|
|
||||||
|
|
||||||
const (
|
|
||||||
// Auto builds a server with a single partition the size of the target flavor disk and
|
|
||||||
// automatically adjusts the filesystem to fit the entire partition. Auto may only be used with
|
|
||||||
// images and servers that use a single EXT3 partition.
|
|
||||||
Auto DiskConfig = "AUTO"
|
|
||||||
|
|
||||||
// Manual builds a server using whatever partition scheme and filesystem are present in the source
|
|
||||||
// image. If the target flavor disk is larger, the remaining space is left unpartitioned. This
|
|
||||||
// enables images to have non-EXT3 filesystems, multiple partitions, and so on, and enables you
|
|
||||||
// to manage the disk configuration. It also results in slightly shorter boot times.
|
|
||||||
Manual DiskConfig = "MANUAL"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ErrInvalidDiskConfig is returned if an invalid string is specified for a DiskConfig option.
|
|
||||||
var ErrInvalidDiskConfig = errors.New("DiskConfig must be either diskconfig.Auto or diskconfig.Manual.")
|
|
||||||
|
|
||||||
// Validate ensures that a DiskConfig contains an appropriate value.
|
|
||||||
func (config DiskConfig) validate() error {
|
|
||||||
switch config {
|
|
||||||
case Auto, Manual:
|
|
||||||
return nil
|
|
||||||
default:
|
|
||||||
return ErrInvalidDiskConfig
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateOptsExt adds a DiskConfig option to the base CreateOpts.
|
|
||||||
type CreateOptsExt struct {
|
|
||||||
servers.CreateOptsBuilder
|
|
||||||
|
|
||||||
// DiskConfig [optional] controls how the created server's disk is partitioned.
|
|
||||||
DiskConfig DiskConfig `json:"OS-DCF:diskConfig,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToServerCreateMap adds the diskconfig option to the base server creation options.
|
|
||||||
func (opts CreateOptsExt) ToServerCreateMap() (map[string]interface{}, error) {
|
|
||||||
base, err := opts.CreateOptsBuilder.ToServerCreateMap()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if string(opts.DiskConfig) == "" {
|
|
||||||
return base, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
serverMap := base["server"].(map[string]interface{})
|
|
||||||
serverMap["OS-DCF:diskConfig"] = string(opts.DiskConfig)
|
|
||||||
|
|
||||||
return base, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// RebuildOptsExt adds a DiskConfig option to the base RebuildOpts.
|
|
||||||
type RebuildOptsExt struct {
|
|
||||||
servers.RebuildOptsBuilder
|
|
||||||
|
|
||||||
// DiskConfig [optional] controls how the rebuilt server's disk is partitioned.
|
|
||||||
DiskConfig DiskConfig
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToServerRebuildMap adds the diskconfig option to the base server rebuild options.
|
|
||||||
func (opts RebuildOptsExt) ToServerRebuildMap() (map[string]interface{}, error) {
|
|
||||||
err := opts.DiskConfig.validate()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
base, err := opts.RebuildOptsBuilder.ToServerRebuildMap()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
serverMap := base["rebuild"].(map[string]interface{})
|
|
||||||
serverMap["OS-DCF:diskConfig"] = string(opts.DiskConfig)
|
|
||||||
|
|
||||||
return base, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ResizeOptsExt adds a DiskConfig option to the base server resize options.
|
|
||||||
type ResizeOptsExt struct {
|
|
||||||
servers.ResizeOptsBuilder
|
|
||||||
|
|
||||||
// DiskConfig [optional] controls how the resized server's disk is partitioned.
|
|
||||||
DiskConfig DiskConfig
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToServerResizeMap adds the diskconfig option to the base server creation options.
|
|
||||||
func (opts ResizeOptsExt) ToServerResizeMap() (map[string]interface{}, error) {
|
|
||||||
err := opts.DiskConfig.validate()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
base, err := opts.ResizeOptsBuilder.ToServerResizeMap()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
serverMap := base["resize"].(map[string]interface{})
|
|
||||||
serverMap["OS-DCF:diskConfig"] = string(opts.DiskConfig)
|
|
||||||
|
|
||||||
return base, nil
|
|
||||||
}
|
|
|
@ -1,60 +0,0 @@
|
||||||
package diskconfig
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/mitchellh/mapstructure"
|
|
||||||
"github.com/rackspace/gophercloud"
|
|
||||||
"github.com/rackspace/gophercloud/openstack/compute/v2/servers"
|
|
||||||
"github.com/rackspace/gophercloud/pagination"
|
|
||||||
)
|
|
||||||
|
|
||||||
func commonExtract(result gophercloud.Result) (*DiskConfig, error) {
|
|
||||||
var resp struct {
|
|
||||||
Server struct {
|
|
||||||
DiskConfig string `mapstructure:"OS-DCF:diskConfig"`
|
|
||||||
} `mapstructure:"server"`
|
|
||||||
}
|
|
||||||
|
|
||||||
err := mapstructure.Decode(result.Body, &resp)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
config := DiskConfig(resp.Server.DiskConfig)
|
|
||||||
return &config, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExtractGet returns the disk configuration from a servers.Get call.
|
|
||||||
func ExtractGet(result servers.GetResult) (*DiskConfig, error) {
|
|
||||||
return commonExtract(result.Result)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExtractUpdate returns the disk configuration from a servers.Update call.
|
|
||||||
func ExtractUpdate(result servers.UpdateResult) (*DiskConfig, error) {
|
|
||||||
return commonExtract(result.Result)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExtractRebuild returns the disk configuration from a servers.Rebuild call.
|
|
||||||
func ExtractRebuild(result servers.RebuildResult) (*DiskConfig, error) {
|
|
||||||
return commonExtract(result.Result)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExtractDiskConfig returns the DiskConfig setting for a specific server acquired from an
|
|
||||||
// servers.ExtractServers call, while iterating through a Pager.
|
|
||||||
func ExtractDiskConfig(page pagination.Page, index int) (*DiskConfig, error) {
|
|
||||||
casted := page.(servers.ServerPage).Body
|
|
||||||
|
|
||||||
type server struct {
|
|
||||||
DiskConfig string `mapstructure:"OS-DCF:diskConfig"`
|
|
||||||
}
|
|
||||||
var response struct {
|
|
||||||
Servers []server `mapstructure:"servers"`
|
|
||||||
}
|
|
||||||
|
|
||||||
err := mapstructure.Decode(casted, &response)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
config := DiskConfig(response.Servers[index].DiskConfig)
|
|
||||||
return &config, nil
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
// Package network provides the ability to manage nova-networks
|
|
||||||
package networks
|
|
209
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/networks/fixtures.go
generated
vendored
209
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/networks/fixtures.go
generated
vendored
|
@ -1,209 +0,0 @@
|
||||||
// +build fixtures
|
|
||||||
|
|
||||||
package networks
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
th "github.com/rackspace/gophercloud/testhelper"
|
|
||||||
"github.com/rackspace/gophercloud/testhelper/client"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ListOutput is a sample response to a List call.
|
|
||||||
const ListOutput = `
|
|
||||||
{
|
|
||||||
"networks": [
|
|
||||||
{
|
|
||||||
"bridge": "br100",
|
|
||||||
"bridge_interface": "eth0",
|
|
||||||
"broadcast": "10.0.0.7",
|
|
||||||
"cidr": "10.0.0.0/29",
|
|
||||||
"cidr_v6": null,
|
|
||||||
"created_at": "2011-08-15 06:19:19.387525",
|
|
||||||
"deleted": false,
|
|
||||||
"deleted_at": null,
|
|
||||||
"dhcp_start": "10.0.0.3",
|
|
||||||
"dns1": null,
|
|
||||||
"dns2": null,
|
|
||||||
"gateway": "10.0.0.1",
|
|
||||||
"gateway_v6": null,
|
|
||||||
"host": "nsokolov-desktop",
|
|
||||||
"id": "20c8acc0-f747-4d71-a389-46d078ebf047",
|
|
||||||
"injected": false,
|
|
||||||
"label": "mynet_0",
|
|
||||||
"multi_host": false,
|
|
||||||
"netmask": "255.255.255.248",
|
|
||||||
"netmask_v6": null,
|
|
||||||
"priority": null,
|
|
||||||
"project_id": "1234",
|
|
||||||
"rxtx_base": null,
|
|
||||||
"updated_at": "2011-08-16 09:26:13.048257",
|
|
||||||
"vlan": 100,
|
|
||||||
"vpn_private_address": "10.0.0.2",
|
|
||||||
"vpn_public_address": "127.0.0.1",
|
|
||||||
"vpn_public_port": 1000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"bridge": "br101",
|
|
||||||
"bridge_interface": "eth0",
|
|
||||||
"broadcast": "10.0.0.15",
|
|
||||||
"cidr": "10.0.0.10/29",
|
|
||||||
"cidr_v6": null,
|
|
||||||
"created_at": "2011-08-15 06:19:19.885495",
|
|
||||||
"deleted": false,
|
|
||||||
"deleted_at": null,
|
|
||||||
"dhcp_start": "10.0.0.11",
|
|
||||||
"dns1": null,
|
|
||||||
"dns2": null,
|
|
||||||
"gateway": "10.0.0.9",
|
|
||||||
"gateway_v6": null,
|
|
||||||
"host": null,
|
|
||||||
"id": "20c8acc0-f747-4d71-a389-46d078ebf000",
|
|
||||||
"injected": false,
|
|
||||||
"label": "mynet_1",
|
|
||||||
"multi_host": false,
|
|
||||||
"netmask": "255.255.255.248",
|
|
||||||
"netmask_v6": null,
|
|
||||||
"priority": null,
|
|
||||||
"project_id": null,
|
|
||||||
"rxtx_base": null,
|
|
||||||
"updated_at": null,
|
|
||||||
"vlan": 101,
|
|
||||||
"vpn_private_address": "10.0.0.10",
|
|
||||||
"vpn_public_address": null,
|
|
||||||
"vpn_public_port": 1001
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
// GetOutput is a sample response to a Get call.
|
|
||||||
const GetOutput = `
|
|
||||||
{
|
|
||||||
"network": {
|
|
||||||
"bridge": "br101",
|
|
||||||
"bridge_interface": "eth0",
|
|
||||||
"broadcast": "10.0.0.15",
|
|
||||||
"cidr": "10.0.0.10/29",
|
|
||||||
"cidr_v6": null,
|
|
||||||
"created_at": "2011-08-15 06:19:19.885495",
|
|
||||||
"deleted": false,
|
|
||||||
"deleted_at": null,
|
|
||||||
"dhcp_start": "10.0.0.11",
|
|
||||||
"dns1": null,
|
|
||||||
"dns2": null,
|
|
||||||
"gateway": "10.0.0.9",
|
|
||||||
"gateway_v6": null,
|
|
||||||
"host": null,
|
|
||||||
"id": "20c8acc0-f747-4d71-a389-46d078ebf000",
|
|
||||||
"injected": false,
|
|
||||||
"label": "mynet_1",
|
|
||||||
"multi_host": false,
|
|
||||||
"netmask": "255.255.255.248",
|
|
||||||
"netmask_v6": null,
|
|
||||||
"priority": null,
|
|
||||||
"project_id": null,
|
|
||||||
"rxtx_base": null,
|
|
||||||
"updated_at": null,
|
|
||||||
"vlan": 101,
|
|
||||||
"vpn_private_address": "10.0.0.10",
|
|
||||||
"vpn_public_address": null,
|
|
||||||
"vpn_public_port": 1001
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
// FirstNetwork is the first result in ListOutput.
|
|
||||||
var nilTime time.Time
|
|
||||||
var FirstNetwork = Network{
|
|
||||||
Bridge: "br100",
|
|
||||||
BridgeInterface: "eth0",
|
|
||||||
Broadcast: "10.0.0.7",
|
|
||||||
CIDR: "10.0.0.0/29",
|
|
||||||
CIDRv6: "",
|
|
||||||
CreatedAt: time.Date(2011, 8, 15, 6, 19, 19, 387525000, time.UTC),
|
|
||||||
Deleted: false,
|
|
||||||
DeletedAt: nilTime,
|
|
||||||
DHCPStart: "10.0.0.3",
|
|
||||||
DNS1: "",
|
|
||||||
DNS2: "",
|
|
||||||
Gateway: "10.0.0.1",
|
|
||||||
Gatewayv6: "",
|
|
||||||
Host: "nsokolov-desktop",
|
|
||||||
ID: "20c8acc0-f747-4d71-a389-46d078ebf047",
|
|
||||||
Injected: false,
|
|
||||||
Label: "mynet_0",
|
|
||||||
MultiHost: false,
|
|
||||||
Netmask: "255.255.255.248",
|
|
||||||
Netmaskv6: "",
|
|
||||||
Priority: 0,
|
|
||||||
ProjectID: "1234",
|
|
||||||
RXTXBase: 0,
|
|
||||||
UpdatedAt: time.Date(2011, 8, 16, 9, 26, 13, 48257000, time.UTC),
|
|
||||||
VLAN: 100,
|
|
||||||
VPNPrivateAddress: "10.0.0.2",
|
|
||||||
VPNPublicAddress: "127.0.0.1",
|
|
||||||
VPNPublicPort: 1000,
|
|
||||||
}
|
|
||||||
|
|
||||||
// SecondNetwork is the second result in ListOutput.
|
|
||||||
var SecondNetwork = Network{
|
|
||||||
Bridge: "br101",
|
|
||||||
BridgeInterface: "eth0",
|
|
||||||
Broadcast: "10.0.0.15",
|
|
||||||
CIDR: "10.0.0.10/29",
|
|
||||||
CIDRv6: "",
|
|
||||||
CreatedAt: time.Date(2011, 8, 15, 6, 19, 19, 885495000, time.UTC),
|
|
||||||
Deleted: false,
|
|
||||||
DeletedAt: nilTime,
|
|
||||||
DHCPStart: "10.0.0.11",
|
|
||||||
DNS1: "",
|
|
||||||
DNS2: "",
|
|
||||||
Gateway: "10.0.0.9",
|
|
||||||
Gatewayv6: "",
|
|
||||||
Host: "",
|
|
||||||
ID: "20c8acc0-f747-4d71-a389-46d078ebf000",
|
|
||||||
Injected: false,
|
|
||||||
Label: "mynet_1",
|
|
||||||
MultiHost: false,
|
|
||||||
Netmask: "255.255.255.248",
|
|
||||||
Netmaskv6: "",
|
|
||||||
Priority: 0,
|
|
||||||
ProjectID: "",
|
|
||||||
RXTXBase: 0,
|
|
||||||
UpdatedAt: nilTime,
|
|
||||||
VLAN: 101,
|
|
||||||
VPNPrivateAddress: "10.0.0.10",
|
|
||||||
VPNPublicAddress: "",
|
|
||||||
VPNPublicPort: 1001,
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExpectedNetworkSlice is the slice of results that should be parsed
|
|
||||||
// from ListOutput, in the expected order.
|
|
||||||
var ExpectedNetworkSlice = []Network{FirstNetwork, SecondNetwork}
|
|
||||||
|
|
||||||
// HandleListSuccessfully configures the test server to respond to a List request.
|
|
||||||
func HandleListSuccessfully(t *testing.T) {
|
|
||||||
th.Mux.HandleFunc("/os-networks", func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
th.TestMethod(t, r, "GET")
|
|
||||||
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
|
||||||
|
|
||||||
w.Header().Add("Content-Type", "application/json")
|
|
||||||
fmt.Fprintf(w, ListOutput)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// HandleGetSuccessfully configures the test server to respond to a Get request
|
|
||||||
// for an existing network.
|
|
||||||
func HandleGetSuccessfully(t *testing.T) {
|
|
||||||
th.Mux.HandleFunc("/os-networks/20c8acc0-f747-4d71-a389-46d078ebf000", func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
th.TestMethod(t, r, "GET")
|
|
||||||
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
|
||||||
|
|
||||||
w.Header().Add("Content-Type", "application/json")
|
|
||||||
fmt.Fprintf(w, GetOutput)
|
|
||||||
})
|
|
||||||
}
|
|
|
@ -1,22 +0,0 @@
|
||||||
package networks
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/rackspace/gophercloud"
|
|
||||||
"github.com/rackspace/gophercloud/pagination"
|
|
||||||
)
|
|
||||||
|
|
||||||
// List returns a Pager that allows you to iterate over a collection of Network.
|
|
||||||
func List(client *gophercloud.ServiceClient) pagination.Pager {
|
|
||||||
url := listURL(client)
|
|
||||||
createPage := func(r pagination.PageResult) pagination.Page {
|
|
||||||
return NetworkPage{pagination.SinglePageBase(r)}
|
|
||||||
}
|
|
||||||
return pagination.NewPager(client, url, createPage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get returns data about a previously created Network.
|
|
||||||
func Get(client *gophercloud.ServiceClient, id string) GetResult {
|
|
||||||
var res GetResult
|
|
||||||
_, res.Err = client.Get(getURL(client, id), &res.Body, nil)
|
|
||||||
return res
|
|
||||||
}
|
|
222
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/networks/results.go
generated
vendored
222
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/networks/results.go
generated
vendored
|
@ -1,222 +0,0 @@
|
||||||
package networks
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/mitchellh/mapstructure"
|
|
||||||
"github.com/rackspace/gophercloud"
|
|
||||||
"github.com/rackspace/gophercloud/pagination"
|
|
||||||
)
|
|
||||||
|
|
||||||
// A Network represents a nova-network that an instance communicates on
|
|
||||||
type Network struct {
|
|
||||||
// The Bridge that VIFs on this network are connected to
|
|
||||||
Bridge string `mapstructure:"bridge"`
|
|
||||||
|
|
||||||
// BridgeInterface is what interface is connected to the Bridge
|
|
||||||
BridgeInterface string `mapstructure:"bridge_interface"`
|
|
||||||
|
|
||||||
// The Broadcast address of the network.
|
|
||||||
Broadcast string `mapstructure:"broadcast"`
|
|
||||||
|
|
||||||
// CIDR is the IPv4 subnet.
|
|
||||||
CIDR string `mapstructure:"cidr"`
|
|
||||||
|
|
||||||
// CIDRv6 is the IPv6 subnet.
|
|
||||||
CIDRv6 string `mapstructure:"cidr_v6"`
|
|
||||||
|
|
||||||
// CreatedAt is when the network was created..
|
|
||||||
CreatedAt time.Time `mapstructure:"-"`
|
|
||||||
|
|
||||||
// Deleted shows if the network has been deleted.
|
|
||||||
Deleted bool `mapstructure:"deleted"`
|
|
||||||
|
|
||||||
// DeletedAt is the time when the network was deleted.
|
|
||||||
DeletedAt time.Time `mapstructure:"-"`
|
|
||||||
|
|
||||||
// DHCPStart is the start of the DHCP address range.
|
|
||||||
DHCPStart string `mapstructure:"dhcp_start"`
|
|
||||||
|
|
||||||
// DNS1 is the first DNS server to use through DHCP.
|
|
||||||
DNS1 string `mapstructure:"dns_1"`
|
|
||||||
|
|
||||||
// DNS2 is the first DNS server to use through DHCP.
|
|
||||||
DNS2 string `mapstructure:"dns_2"`
|
|
||||||
|
|
||||||
// Gateway is the network gateway.
|
|
||||||
Gateway string `mapstructure:"gateway"`
|
|
||||||
|
|
||||||
// Gatewayv6 is the IPv6 network gateway.
|
|
||||||
Gatewayv6 string `mapstructure:"gateway_v6"`
|
|
||||||
|
|
||||||
// Host is the host that the network service is running on.
|
|
||||||
Host string `mapstructure:"host"`
|
|
||||||
|
|
||||||
// ID is the UUID of the network.
|
|
||||||
ID string `mapstructure:"id"`
|
|
||||||
|
|
||||||
// Injected determines if network information is injected into the host.
|
|
||||||
Injected bool `mapstructure:"injected"`
|
|
||||||
|
|
||||||
// Label is the common name that the network has..
|
|
||||||
Label string `mapstructure:"label"`
|
|
||||||
|
|
||||||
// MultiHost is if multi-host networking is enablec..
|
|
||||||
MultiHost bool `mapstructure:"multi_host"`
|
|
||||||
|
|
||||||
// Netmask is the network netmask.
|
|
||||||
Netmask string `mapstructure:"netmask"`
|
|
||||||
|
|
||||||
// Netmaskv6 is the IPv6 netmask.
|
|
||||||
Netmaskv6 string `mapstructure:"netmask_v6"`
|
|
||||||
|
|
||||||
// Priority is the network interface priority.
|
|
||||||
Priority int `mapstructure:"priority"`
|
|
||||||
|
|
||||||
// ProjectID is the project associated with this network.
|
|
||||||
ProjectID string `mapstructure:"project_id"`
|
|
||||||
|
|
||||||
// RXTXBase configures bandwidth entitlement.
|
|
||||||
RXTXBase int `mapstructure:"rxtx_base"`
|
|
||||||
|
|
||||||
// UpdatedAt is the time when the network was last updated.
|
|
||||||
UpdatedAt time.Time `mapstructure:"-"`
|
|
||||||
|
|
||||||
// VLAN is the vlan this network runs on.
|
|
||||||
VLAN int `mapstructure:"vlan"`
|
|
||||||
|
|
||||||
// VPNPrivateAddress is the private address of the CloudPipe VPN.
|
|
||||||
VPNPrivateAddress string `mapstructure:"vpn_private_address"`
|
|
||||||
|
|
||||||
// VPNPublicAddress is the public address of the CloudPipe VPN.
|
|
||||||
VPNPublicAddress string `mapstructure:"vpn_public_address"`
|
|
||||||
|
|
||||||
// VPNPublicPort is the port of the CloudPipe VPN.
|
|
||||||
VPNPublicPort int `mapstructure:"vpn_public_port"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// NetworkPage stores a single, only page of Networks
|
|
||||||
// results from a List call.
|
|
||||||
type NetworkPage struct {
|
|
||||||
pagination.SinglePageBase
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsEmpty determines whether or not a NetworkPage is empty.
|
|
||||||
func (page NetworkPage) IsEmpty() (bool, error) {
|
|
||||||
va, err := ExtractNetworks(page)
|
|
||||||
return len(va) == 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExtractNetworks interprets a page of results as a slice of Networks
|
|
||||||
func ExtractNetworks(page pagination.Page) ([]Network, error) {
|
|
||||||
var res struct {
|
|
||||||
Networks []Network `mapstructure:"networks"`
|
|
||||||
}
|
|
||||||
|
|
||||||
err := mapstructure.Decode(page.(NetworkPage).Body, &res)
|
|
||||||
|
|
||||||
var rawNetworks []interface{}
|
|
||||||
body := page.(NetworkPage).Body
|
|
||||||
switch body.(type) {
|
|
||||||
case map[string]interface{}:
|
|
||||||
rawNetworks = body.(map[string]interface{})["networks"].([]interface{})
|
|
||||||
case map[string][]interface{}:
|
|
||||||
rawNetworks = body.(map[string][]interface{})["networks"]
|
|
||||||
default:
|
|
||||||
return res.Networks, fmt.Errorf("Unknown type")
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := range rawNetworks {
|
|
||||||
thisNetwork := rawNetworks[i].(map[string]interface{})
|
|
||||||
if t, ok := thisNetwork["created_at"].(string); ok && t != "" {
|
|
||||||
createdAt, err := time.Parse("2006-01-02 15:04:05.000000", t)
|
|
||||||
if err != nil {
|
|
||||||
return res.Networks, err
|
|
||||||
}
|
|
||||||
res.Networks[i].CreatedAt = createdAt
|
|
||||||
}
|
|
||||||
|
|
||||||
if t, ok := thisNetwork["updated_at"].(string); ok && t != "" {
|
|
||||||
updatedAt, err := time.Parse("2006-01-02 15:04:05.000000", t)
|
|
||||||
if err != nil {
|
|
||||||
return res.Networks, err
|
|
||||||
}
|
|
||||||
res.Networks[i].UpdatedAt = updatedAt
|
|
||||||
}
|
|
||||||
|
|
||||||
if t, ok := thisNetwork["deleted_at"].(string); ok && t != "" {
|
|
||||||
deletedAt, err := time.Parse("2006-01-02 15:04:05.000000", t)
|
|
||||||
if err != nil {
|
|
||||||
return res.Networks, err
|
|
||||||
}
|
|
||||||
res.Networks[i].DeletedAt = deletedAt
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.Networks, err
|
|
||||||
}
|
|
||||||
|
|
||||||
type NetworkResult struct {
|
|
||||||
gophercloud.Result
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract is a method that attempts to interpret any Network resource
|
|
||||||
// response as a Network struct.
|
|
||||||
func (r NetworkResult) Extract() (*Network, error) {
|
|
||||||
if r.Err != nil {
|
|
||||||
return nil, r.Err
|
|
||||||
}
|
|
||||||
|
|
||||||
var res struct {
|
|
||||||
Network *Network `json:"network" mapstructure:"network"`
|
|
||||||
}
|
|
||||||
|
|
||||||
config := &mapstructure.DecoderConfig{
|
|
||||||
Result: &res,
|
|
||||||
WeaklyTypedInput: true,
|
|
||||||
}
|
|
||||||
decoder, err := mapstructure.NewDecoder(config)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := decoder.Decode(r.Body); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
b := r.Body.(map[string]interface{})["network"].(map[string]interface{})
|
|
||||||
|
|
||||||
if t, ok := b["created_at"].(string); ok && t != "" {
|
|
||||||
createdAt, err := time.Parse("2006-01-02 15:04:05.000000", t)
|
|
||||||
if err != nil {
|
|
||||||
return res.Network, err
|
|
||||||
}
|
|
||||||
res.Network.CreatedAt = createdAt
|
|
||||||
}
|
|
||||||
|
|
||||||
if t, ok := b["updated_at"].(string); ok && t != "" {
|
|
||||||
updatedAt, err := time.Parse("2006-01-02 15:04:05.000000", t)
|
|
||||||
if err != nil {
|
|
||||||
return res.Network, err
|
|
||||||
}
|
|
||||||
res.Network.UpdatedAt = updatedAt
|
|
||||||
}
|
|
||||||
|
|
||||||
if t, ok := b["deleted_at"].(string); ok && t != "" {
|
|
||||||
deletedAt, err := time.Parse("2006-01-02 15:04:05.000000", t)
|
|
||||||
if err != nil {
|
|
||||||
return res.Network, err
|
|
||||||
}
|
|
||||||
res.Network.DeletedAt = deletedAt
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.Network, err
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetResult is the response from a Get operation. Call its Extract method to interpret it
|
|
||||||
// as a Network.
|
|
||||||
type GetResult struct {
|
|
||||||
NetworkResult
|
|
||||||
}
|
|
17
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/networks/urls.go
generated
vendored
17
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/networks/urls.go
generated
vendored
|
@ -1,17 +0,0 @@
|
||||||
package networks
|
|
||||||
|
|
||||||
import "github.com/rackspace/gophercloud"
|
|
||||||
|
|
||||||
const resourcePath = "os-networks"
|
|
||||||
|
|
||||||
func resourceURL(c *gophercloud.ServiceClient) string {
|
|
||||||
return c.ServiceURL(resourcePath)
|
|
||||||
}
|
|
||||||
|
|
||||||
func listURL(c *gophercloud.ServiceClient) string {
|
|
||||||
return resourceURL(c)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getURL(c *gophercloud.ServiceClient, id string) string {
|
|
||||||
return c.ServiceURL(resourcePath, id)
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
// Package schedulerhints enables instances to provide the OpenStack scheduler
|
|
||||||
// hints about where they should be placed in the cloud.
|
|
||||||
package schedulerhints
|
|
|
@ -1,134 +0,0 @@
|
||||||
package schedulerhints
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
"regexp"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/rackspace/gophercloud/openstack/compute/v2/servers"
|
|
||||||
)
|
|
||||||
|
|
||||||
// SchedulerHints represents a set of scheduling hints that are passed to the
|
|
||||||
// OpenStack scheduler
|
|
||||||
type SchedulerHints struct {
|
|
||||||
// Group specifies a Server Group to place the instance in.
|
|
||||||
Group string
|
|
||||||
|
|
||||||
// DifferentHost will place the instance on a compute node that does not
|
|
||||||
// host the given instances.
|
|
||||||
DifferentHost []string
|
|
||||||
|
|
||||||
// SameHost will place the instance on a compute node that hosts the given
|
|
||||||
// instances.
|
|
||||||
SameHost []string
|
|
||||||
|
|
||||||
// Query is a conditional statement that results in compute nodes able to
|
|
||||||
// host the instance.
|
|
||||||
Query []interface{}
|
|
||||||
|
|
||||||
// TargetCell specifies a cell name where the instance will be placed.
|
|
||||||
TargetCell string
|
|
||||||
|
|
||||||
// BuildNearHostIP specifies a subnet of compute nodes to host the instance.
|
|
||||||
BuildNearHostIP string
|
|
||||||
}
|
|
||||||
|
|
||||||
// SchedulerHintsBuilder builds the scheduler hints into a serializable format.
|
|
||||||
type SchedulerHintsBuilder interface {
|
|
||||||
ToServerSchedulerHintsMap() (map[string]interface{}, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToServerSchedulerHintsMap builds the scheduler hints into a serializable format.
|
|
||||||
func (opts SchedulerHints) ToServerSchedulerHintsMap() (map[string]interface{}, error) {
|
|
||||||
sh := make(map[string]interface{})
|
|
||||||
|
|
||||||
uuidRegex, _ := regexp.Compile("^[a-z0-9]{8}-[a-z0-9]{4}-[1-5][a-z0-9]{3}-[a-z0-9]{4}-[a-z0-9]{12}$")
|
|
||||||
|
|
||||||
if opts.Group != "" {
|
|
||||||
if !uuidRegex.MatchString(opts.Group) {
|
|
||||||
return nil, fmt.Errorf("Group must be a UUID")
|
|
||||||
}
|
|
||||||
sh["group"] = opts.Group
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(opts.DifferentHost) > 0 {
|
|
||||||
for _, diffHost := range opts.DifferentHost {
|
|
||||||
if !uuidRegex.MatchString(diffHost) {
|
|
||||||
return nil, fmt.Errorf("The hosts in DifferentHost must be in UUID format.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sh["different_host"] = opts.DifferentHost
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(opts.SameHost) > 0 {
|
|
||||||
for _, sameHost := range opts.SameHost {
|
|
||||||
if !uuidRegex.MatchString(sameHost) {
|
|
||||||
return nil, fmt.Errorf("The hosts in SameHost must be in UUID format.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sh["same_host"] = opts.SameHost
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Query can be something simple like:
|
|
||||||
[">=", "$free_ram_mb", 1024]
|
|
||||||
|
|
||||||
Or more complex like:
|
|
||||||
['and',
|
|
||||||
['>=', '$free_ram_mb', 1024],
|
|
||||||
['>=', '$free_disk_mb', 200 * 1024]
|
|
||||||
]
|
|
||||||
|
|
||||||
Because of the possible complexity, just make sure the length is a minimum of 3.
|
|
||||||
*/
|
|
||||||
if len(opts.Query) > 0 {
|
|
||||||
if len(opts.Query) < 3 {
|
|
||||||
return nil, fmt.Errorf("Query must be a conditional statement in the format of [op,variable,value]")
|
|
||||||
}
|
|
||||||
sh["query"] = opts.Query
|
|
||||||
}
|
|
||||||
|
|
||||||
if opts.TargetCell != "" {
|
|
||||||
sh["target_cell"] = opts.TargetCell
|
|
||||||
}
|
|
||||||
|
|
||||||
if opts.BuildNearHostIP != "" {
|
|
||||||
if _, _, err := net.ParseCIDR(opts.BuildNearHostIP); err != nil {
|
|
||||||
return nil, fmt.Errorf("BuildNearHostIP must be a valid subnet in the form 192.168.1.1/24")
|
|
||||||
}
|
|
||||||
ipParts := strings.Split(opts.BuildNearHostIP, "/")
|
|
||||||
sh["build_near_host_ip"] = ipParts[0]
|
|
||||||
sh["cidr"] = "/" + ipParts[1]
|
|
||||||
}
|
|
||||||
|
|
||||||
return sh, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateOptsExt adds a SchedulerHints option to the base CreateOpts.
|
|
||||||
type CreateOptsExt struct {
|
|
||||||
servers.CreateOptsBuilder
|
|
||||||
|
|
||||||
// SchedulerHints provides a set of hints to the scheduler.
|
|
||||||
SchedulerHints SchedulerHintsBuilder
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToServerCreateMap adds the SchedulerHints option to the base server creation options.
|
|
||||||
func (opts CreateOptsExt) ToServerCreateMap() (map[string]interface{}, error) {
|
|
||||||
base, err := opts.CreateOptsBuilder.ToServerCreateMap()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
schedulerHints, err := opts.SchedulerHints.ToServerSchedulerHintsMap()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(schedulerHints) == 0 {
|
|
||||||
return base, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
base["os:scheduler_hints"] = schedulerHints
|
|
||||||
|
|
||||||
return base, nil
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
package secgroups
|
|
|
@ -1,267 +0,0 @@
|
||||||
package secgroups
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
th "github.com/rackspace/gophercloud/testhelper"
|
|
||||||
fake "github.com/rackspace/gophercloud/testhelper/client"
|
|
||||||
)
|
|
||||||
|
|
||||||
const rootPath = "/os-security-groups"
|
|
||||||
|
|
||||||
const listGroupsJSON = `
|
|
||||||
{
|
|
||||||
"security_groups": [
|
|
||||||
{
|
|
||||||
"description": "default",
|
|
||||||
"id": "{groupID}",
|
|
||||||
"name": "default",
|
|
||||||
"rules": [],
|
|
||||||
"tenant_id": "openstack"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
func mockListGroupsResponse(t *testing.T) {
|
|
||||||
th.Mux.HandleFunc(rootPath, 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")
|
|
||||||
w.WriteHeader(http.StatusOK)
|
|
||||||
|
|
||||||
fmt.Fprintf(w, listGroupsJSON)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func mockListGroupsByServerResponse(t *testing.T, serverID string) {
|
|
||||||
url := fmt.Sprintf("/servers/%s%s", serverID, rootPath)
|
|
||||||
th.Mux.HandleFunc(url, 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")
|
|
||||||
w.WriteHeader(http.StatusOK)
|
|
||||||
|
|
||||||
fmt.Fprintf(w, listGroupsJSON)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func mockCreateGroupResponse(t *testing.T) {
|
|
||||||
th.Mux.HandleFunc(rootPath, func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
th.TestMethod(t, r, "POST")
|
|
||||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
|
||||||
|
|
||||||
th.TestJSONRequest(t, r, `
|
|
||||||
{
|
|
||||||
"security_group": {
|
|
||||||
"name": "test",
|
|
||||||
"description": "something"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`)
|
|
||||||
|
|
||||||
w.Header().Add("Content-Type", "application/json")
|
|
||||||
w.WriteHeader(http.StatusOK)
|
|
||||||
|
|
||||||
fmt.Fprintf(w, `
|
|
||||||
{
|
|
||||||
"security_group": {
|
|
||||||
"description": "something",
|
|
||||||
"id": "{groupID}",
|
|
||||||
"name": "test",
|
|
||||||
"rules": [],
|
|
||||||
"tenant_id": "openstack"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func mockUpdateGroupResponse(t *testing.T, groupID string) {
|
|
||||||
url := fmt.Sprintf("%s/%s", rootPath, groupID)
|
|
||||||
th.Mux.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
th.TestMethod(t, r, "PUT")
|
|
||||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
|
||||||
|
|
||||||
th.TestJSONRequest(t, r, `
|
|
||||||
{
|
|
||||||
"security_group": {
|
|
||||||
"name": "new_name",
|
|
||||||
"description": "new_desc"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`)
|
|
||||||
|
|
||||||
w.Header().Add("Content-Type", "application/json")
|
|
||||||
w.WriteHeader(http.StatusOK)
|
|
||||||
|
|
||||||
fmt.Fprintf(w, `
|
|
||||||
{
|
|
||||||
"security_group": {
|
|
||||||
"description": "something",
|
|
||||||
"id": "{groupID}",
|
|
||||||
"name": "new_name",
|
|
||||||
"rules": [],
|
|
||||||
"tenant_id": "openstack"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func mockGetGroupsResponse(t *testing.T, groupID string) {
|
|
||||||
url := fmt.Sprintf("%s/%s", rootPath, groupID)
|
|
||||||
th.Mux.HandleFunc(url, 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")
|
|
||||||
w.WriteHeader(http.StatusOK)
|
|
||||||
|
|
||||||
fmt.Fprintf(w, `
|
|
||||||
{
|
|
||||||
"security_group": {
|
|
||||||
"description": "default",
|
|
||||||
"id": "{groupID}",
|
|
||||||
"name": "default",
|
|
||||||
"rules": [
|
|
||||||
{
|
|
||||||
"from_port": 80,
|
|
||||||
"group": {
|
|
||||||
"tenant_id": "openstack",
|
|
||||||
"name": "default"
|
|
||||||
},
|
|
||||||
"ip_protocol": "TCP",
|
|
||||||
"to_port": 85,
|
|
||||||
"parent_group_id": "{groupID}",
|
|
||||||
"ip_range": {
|
|
||||||
"cidr": "0.0.0.0"
|
|
||||||
},
|
|
||||||
"id": "{ruleID}"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"tenant_id": "openstack"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func mockGetNumericIDGroupResponse(t *testing.T, groupID int) {
|
|
||||||
url := fmt.Sprintf("%s/%d", rootPath, groupID)
|
|
||||||
th.Mux.HandleFunc(url, 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")
|
|
||||||
w.WriteHeader(http.StatusOK)
|
|
||||||
|
|
||||||
fmt.Fprintf(w, `
|
|
||||||
{
|
|
||||||
"security_group": {
|
|
||||||
"id": 12345
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func mockDeleteGroupResponse(t *testing.T, groupID string) {
|
|
||||||
url := fmt.Sprintf("%s/%s", rootPath, groupID)
|
|
||||||
th.Mux.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
th.TestMethod(t, r, "DELETE")
|
|
||||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
|
||||||
w.Header().Add("Content-Type", "application/json")
|
|
||||||
w.WriteHeader(http.StatusAccepted)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func mockAddRuleResponse(t *testing.T) {
|
|
||||||
th.Mux.HandleFunc("/os-security-group-rules", func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
th.TestMethod(t, r, "POST")
|
|
||||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
|
||||||
|
|
||||||
th.TestJSONRequest(t, r, `
|
|
||||||
{
|
|
||||||
"security_group_rule": {
|
|
||||||
"from_port": 22,
|
|
||||||
"ip_protocol": "TCP",
|
|
||||||
"to_port": 22,
|
|
||||||
"parent_group_id": "{groupID}",
|
|
||||||
"cidr": "0.0.0.0/0"
|
|
||||||
}
|
|
||||||
} `)
|
|
||||||
|
|
||||||
w.Header().Add("Content-Type", "application/json")
|
|
||||||
w.WriteHeader(http.StatusOK)
|
|
||||||
|
|
||||||
fmt.Fprintf(w, `
|
|
||||||
{
|
|
||||||
"security_group_rule": {
|
|
||||||
"from_port": 22,
|
|
||||||
"group": {},
|
|
||||||
"ip_protocol": "TCP",
|
|
||||||
"to_port": 22,
|
|
||||||
"parent_group_id": "{groupID}",
|
|
||||||
"ip_range": {
|
|
||||||
"cidr": "0.0.0.0/0"
|
|
||||||
},
|
|
||||||
"id": "{ruleID}"
|
|
||||||
}
|
|
||||||
}`)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func mockDeleteRuleResponse(t *testing.T, ruleID string) {
|
|
||||||
url := fmt.Sprintf("/os-security-group-rules/%s", ruleID)
|
|
||||||
th.Mux.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
th.TestMethod(t, r, "DELETE")
|
|
||||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
|
||||||
w.Header().Add("Content-Type", "application/json")
|
|
||||||
w.WriteHeader(http.StatusAccepted)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func mockAddServerToGroupResponse(t *testing.T, serverID string) {
|
|
||||||
url := fmt.Sprintf("/servers/%s/action", serverID)
|
|
||||||
th.Mux.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
th.TestMethod(t, r, "POST")
|
|
||||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
|
||||||
|
|
||||||
th.TestJSONRequest(t, r, `
|
|
||||||
{
|
|
||||||
"addSecurityGroup": {
|
|
||||||
"name": "test"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`)
|
|
||||||
|
|
||||||
w.Header().Add("Content-Type", "application/json")
|
|
||||||
w.WriteHeader(http.StatusAccepted)
|
|
||||||
fmt.Fprintf(w, `{}`)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func mockRemoveServerFromGroupResponse(t *testing.T, serverID string) {
|
|
||||||
url := fmt.Sprintf("/servers/%s/action", serverID)
|
|
||||||
th.Mux.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
th.TestMethod(t, r, "POST")
|
|
||||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
|
||||||
|
|
||||||
th.TestJSONRequest(t, r, `
|
|
||||||
{
|
|
||||||
"removeSecurityGroup": {
|
|
||||||
"name": "test"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`)
|
|
||||||
|
|
||||||
w.Header().Add("Content-Type", "application/json")
|
|
||||||
w.WriteHeader(http.StatusAccepted)
|
|
||||||
fmt.Fprintf(w, `{}`)
|
|
||||||
})
|
|
||||||
}
|
|
|
@ -1,257 +0,0 @@
|
||||||
package secgroups
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
|
|
||||||
"github.com/rackspace/gophercloud"
|
|
||||||
"github.com/rackspace/gophercloud/pagination"
|
|
||||||
)
|
|
||||||
|
|
||||||
func commonList(client *gophercloud.ServiceClient, url string) pagination.Pager {
|
|
||||||
createPage := func(r pagination.PageResult) pagination.Page {
|
|
||||||
return SecurityGroupPage{pagination.SinglePageBase(r)}
|
|
||||||
}
|
|
||||||
|
|
||||||
return pagination.NewPager(client, url, createPage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// List will return a collection of all the security groups for a particular
|
|
||||||
// tenant.
|
|
||||||
func List(client *gophercloud.ServiceClient) pagination.Pager {
|
|
||||||
return commonList(client, rootURL(client))
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListByServer will return a collection of all the security groups which are
|
|
||||||
// associated with a particular server.
|
|
||||||
func ListByServer(client *gophercloud.ServiceClient, serverID string) pagination.Pager {
|
|
||||||
return commonList(client, listByServerURL(client, serverID))
|
|
||||||
}
|
|
||||||
|
|
||||||
// GroupOpts is the underlying struct responsible for creating or updating
|
|
||||||
// security groups. It therefore represents the mutable attributes of a
|
|
||||||
// security group.
|
|
||||||
type GroupOpts struct {
|
|
||||||
// Required - the name of your security group.
|
|
||||||
Name string `json:"name"`
|
|
||||||
|
|
||||||
// Required - the description of your security group.
|
|
||||||
Description string `json:"description"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateOpts is the struct responsible for creating a security group.
|
|
||||||
type CreateOpts GroupOpts
|
|
||||||
|
|
||||||
// CreateOptsBuilder builds the create options into a serializable format.
|
|
||||||
type CreateOptsBuilder interface {
|
|
||||||
ToSecGroupCreateMap() (map[string]interface{}, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
errName = errors.New("Name is a required field")
|
|
||||||
errDesc = errors.New("Description is a required field")
|
|
||||||
)
|
|
||||||
|
|
||||||
// ToSecGroupCreateMap builds the create options into a serializable format.
|
|
||||||
func (opts CreateOpts) ToSecGroupCreateMap() (map[string]interface{}, error) {
|
|
||||||
sg := make(map[string]interface{})
|
|
||||||
|
|
||||||
if opts.Name == "" {
|
|
||||||
return sg, errName
|
|
||||||
}
|
|
||||||
if opts.Description == "" {
|
|
||||||
return sg, errDesc
|
|
||||||
}
|
|
||||||
|
|
||||||
sg["name"] = opts.Name
|
|
||||||
sg["description"] = opts.Description
|
|
||||||
|
|
||||||
return map[string]interface{}{"security_group": sg}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create will create a new security group.
|
|
||||||
func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
|
|
||||||
var result CreateResult
|
|
||||||
|
|
||||||
reqBody, err := opts.ToSecGroupCreateMap()
|
|
||||||
if err != nil {
|
|
||||||
result.Err = err
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
_, result.Err = client.Post(rootURL(client), reqBody, &result.Body, &gophercloud.RequestOpts{
|
|
||||||
OkCodes: []int{200},
|
|
||||||
})
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateOpts is the struct responsible for updating an existing security group.
|
|
||||||
type UpdateOpts GroupOpts
|
|
||||||
|
|
||||||
// UpdateOptsBuilder builds the update options into a serializable format.
|
|
||||||
type UpdateOptsBuilder interface {
|
|
||||||
ToSecGroupUpdateMap() (map[string]interface{}, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToSecGroupUpdateMap builds the update options into a serializable format.
|
|
||||||
func (opts UpdateOpts) ToSecGroupUpdateMap() (map[string]interface{}, error) {
|
|
||||||
sg := make(map[string]interface{})
|
|
||||||
|
|
||||||
if opts.Name == "" {
|
|
||||||
return sg, errName
|
|
||||||
}
|
|
||||||
if opts.Description == "" {
|
|
||||||
return sg, errDesc
|
|
||||||
}
|
|
||||||
|
|
||||||
sg["name"] = opts.Name
|
|
||||||
sg["description"] = opts.Description
|
|
||||||
|
|
||||||
return map[string]interface{}{"security_group": sg}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update will modify the mutable properties of a security group, notably its
|
|
||||||
// name and description.
|
|
||||||
func Update(client *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) UpdateResult {
|
|
||||||
var result UpdateResult
|
|
||||||
|
|
||||||
reqBody, err := opts.ToSecGroupUpdateMap()
|
|
||||||
if err != nil {
|
|
||||||
result.Err = err
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
_, result.Err = client.Put(resourceURL(client, id), reqBody, &result.Body, &gophercloud.RequestOpts{
|
|
||||||
OkCodes: []int{200},
|
|
||||||
})
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get will return details for a particular security group.
|
|
||||||
func Get(client *gophercloud.ServiceClient, id string) GetResult {
|
|
||||||
var result GetResult
|
|
||||||
_, result.Err = client.Get(resourceURL(client, id), &result.Body, nil)
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete will permanently delete a security group from the project.
|
|
||||||
func Delete(client *gophercloud.ServiceClient, id string) gophercloud.ErrResult {
|
|
||||||
var result gophercloud.ErrResult
|
|
||||||
_, result.Err = client.Delete(resourceURL(client, id), nil)
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateRuleOpts represents the configuration for adding a new rule to an
|
|
||||||
// existing security group.
|
|
||||||
type CreateRuleOpts struct {
|
|
||||||
// Required - the ID of the group that this rule will be added to.
|
|
||||||
ParentGroupID string `json:"parent_group_id"`
|
|
||||||
|
|
||||||
// Required - the lower bound of the port range that will be opened.
|
|
||||||
FromPort int `json:"from_port"`
|
|
||||||
|
|
||||||
// Required - the upper bound of the port range that will be opened.
|
|
||||||
ToPort int `json:"to_port"`
|
|
||||||
|
|
||||||
// Required - the protocol type that will be allowed, e.g. TCP.
|
|
||||||
IPProtocol string `json:"ip_protocol"`
|
|
||||||
|
|
||||||
// ONLY required if FromGroupID is blank. This represents the IP range that
|
|
||||||
// will be the source of network traffic to your security group. Use
|
|
||||||
// 0.0.0.0/0 to allow all IP addresses.
|
|
||||||
CIDR string `json:"cidr,omitempty"`
|
|
||||||
|
|
||||||
// ONLY required if CIDR is blank. This value represents the ID of a group
|
|
||||||
// that forwards traffic to the parent group. So, instead of accepting
|
|
||||||
// network traffic from an entire IP range, you can instead refine the
|
|
||||||
// inbound source by an existing security group.
|
|
||||||
FromGroupID string `json:"group_id,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateRuleOptsBuilder builds the create rule options into a serializable format.
|
|
||||||
type CreateRuleOptsBuilder interface {
|
|
||||||
ToRuleCreateMap() (map[string]interface{}, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToRuleCreateMap builds the create rule options into a serializable format.
|
|
||||||
func (opts CreateRuleOpts) ToRuleCreateMap() (map[string]interface{}, error) {
|
|
||||||
rule := make(map[string]interface{})
|
|
||||||
|
|
||||||
if opts.ParentGroupID == "" {
|
|
||||||
return rule, errors.New("A ParentGroupID must be set")
|
|
||||||
}
|
|
||||||
if opts.FromPort == 0 {
|
|
||||||
return rule, errors.New("A FromPort must be set")
|
|
||||||
}
|
|
||||||
if opts.ToPort == 0 {
|
|
||||||
return rule, errors.New("A ToPort must be set")
|
|
||||||
}
|
|
||||||
if opts.IPProtocol == "" {
|
|
||||||
return rule, errors.New("A IPProtocol must be set")
|
|
||||||
}
|
|
||||||
if opts.CIDR == "" && opts.FromGroupID == "" {
|
|
||||||
return rule, errors.New("A CIDR or FromGroupID must be set")
|
|
||||||
}
|
|
||||||
|
|
||||||
rule["parent_group_id"] = opts.ParentGroupID
|
|
||||||
rule["from_port"] = opts.FromPort
|
|
||||||
rule["to_port"] = opts.ToPort
|
|
||||||
rule["ip_protocol"] = opts.IPProtocol
|
|
||||||
|
|
||||||
if opts.CIDR != "" {
|
|
||||||
rule["cidr"] = opts.CIDR
|
|
||||||
}
|
|
||||||
if opts.FromGroupID != "" {
|
|
||||||
rule["group_id"] = opts.FromGroupID
|
|
||||||
}
|
|
||||||
|
|
||||||
return map[string]interface{}{"security_group_rule": rule}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateRule will add a new rule to an existing security group (whose ID is
|
|
||||||
// specified in CreateRuleOpts). You have the option of controlling inbound
|
|
||||||
// traffic from either an IP range (CIDR) or from another security group.
|
|
||||||
func CreateRule(client *gophercloud.ServiceClient, opts CreateRuleOptsBuilder) CreateRuleResult {
|
|
||||||
var result CreateRuleResult
|
|
||||||
|
|
||||||
reqBody, err := opts.ToRuleCreateMap()
|
|
||||||
if err != nil {
|
|
||||||
result.Err = err
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
_, result.Err = client.Post(rootRuleURL(client), reqBody, &result.Body, &gophercloud.RequestOpts{
|
|
||||||
OkCodes: []int{200},
|
|
||||||
})
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteRule will permanently delete a rule from a security group.
|
|
||||||
func DeleteRule(client *gophercloud.ServiceClient, id string) gophercloud.ErrResult {
|
|
||||||
var result gophercloud.ErrResult
|
|
||||||
_, result.Err = client.Delete(resourceRuleURL(client, id), nil)
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
func actionMap(prefix, groupName string) map[string]map[string]string {
|
|
||||||
return map[string]map[string]string{
|
|
||||||
prefix + "SecurityGroup": map[string]string{"name": groupName},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddServerToGroup will associate a server and a security group, enforcing the
|
|
||||||
// rules of the group on the server.
|
|
||||||
func AddServerToGroup(client *gophercloud.ServiceClient, serverID, groupName string) gophercloud.ErrResult {
|
|
||||||
var result gophercloud.ErrResult
|
|
||||||
_, result.Err = client.Post(serverActionURL(client, serverID), actionMap("add", groupName), &result.Body, nil)
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
// RemoveServerFromGroup will disassociate a server from a security group.
|
|
||||||
func RemoveServerFromGroup(client *gophercloud.ServiceClient, serverID, groupName string) gophercloud.ErrResult {
|
|
||||||
var result gophercloud.ErrResult
|
|
||||||
_, result.Err = client.Post(serverActionURL(client, serverID), actionMap("remove", groupName), &result.Body, nil)
|
|
||||||
return result
|
|
||||||
}
|
|
147
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/secgroups/results.go
generated
vendored
147
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/secgroups/results.go
generated
vendored
|
@ -1,147 +0,0 @@
|
||||||
package secgroups
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/mitchellh/mapstructure"
|
|
||||||
|
|
||||||
"github.com/rackspace/gophercloud"
|
|
||||||
"github.com/rackspace/gophercloud/pagination"
|
|
||||||
)
|
|
||||||
|
|
||||||
// SecurityGroup represents a security group.
|
|
||||||
type SecurityGroup struct {
|
|
||||||
// The unique ID of the group. If Neutron is installed, this ID will be
|
|
||||||
// represented as a string UUID; if Neutron is not installed, it will be a
|
|
||||||
// numeric ID. For the sake of consistency, we always cast it to a string.
|
|
||||||
ID string
|
|
||||||
|
|
||||||
// The human-readable name of the group, which needs to be unique.
|
|
||||||
Name string
|
|
||||||
|
|
||||||
// The human-readable description of the group.
|
|
||||||
Description string
|
|
||||||
|
|
||||||
// The rules which determine how this security group operates.
|
|
||||||
Rules []Rule
|
|
||||||
|
|
||||||
// The ID of the tenant to which this security group belongs.
|
|
||||||
TenantID string `mapstructure:"tenant_id"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rule represents a security group rule, a policy which determines how a
|
|
||||||
// security group operates and what inbound traffic it allows in.
|
|
||||||
type Rule struct {
|
|
||||||
// The unique ID. If Neutron is installed, this ID will be
|
|
||||||
// represented as a string UUID; if Neutron is not installed, it will be a
|
|
||||||
// numeric ID. For the sake of consistency, we always cast it to a string.
|
|
||||||
ID string
|
|
||||||
|
|
||||||
// The lower bound of the port range which this security group should open up
|
|
||||||
FromPort int `mapstructure:"from_port"`
|
|
||||||
|
|
||||||
// The upper bound of the port range which this security group should open up
|
|
||||||
ToPort int `mapstructure:"to_port"`
|
|
||||||
|
|
||||||
// The IP protocol (e.g. TCP) which the security group accepts
|
|
||||||
IPProtocol string `mapstructure:"ip_protocol"`
|
|
||||||
|
|
||||||
// The CIDR IP range whose traffic can be received
|
|
||||||
IPRange IPRange `mapstructure:"ip_range"`
|
|
||||||
|
|
||||||
// The security group ID to which this rule belongs
|
|
||||||
ParentGroupID string `mapstructure:"parent_group_id"`
|
|
||||||
|
|
||||||
// Not documented.
|
|
||||||
Group Group
|
|
||||||
}
|
|
||||||
|
|
||||||
// IPRange represents the IP range whose traffic will be accepted by the
|
|
||||||
// security group.
|
|
||||||
type IPRange struct {
|
|
||||||
CIDR string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Group represents a group.
|
|
||||||
type Group struct {
|
|
||||||
TenantID string `mapstructure:"tenant_id"`
|
|
||||||
Name string
|
|
||||||
}
|
|
||||||
|
|
||||||
// SecurityGroupPage is a single page of a SecurityGroup collection.
|
|
||||||
type SecurityGroupPage struct {
|
|
||||||
pagination.SinglePageBase
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsEmpty determines whether or not a page of Security Groups contains any results.
|
|
||||||
func (page SecurityGroupPage) IsEmpty() (bool, error) {
|
|
||||||
users, err := ExtractSecurityGroups(page)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
return len(users) == 0, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExtractSecurityGroups returns a slice of SecurityGroups contained in a single page of results.
|
|
||||||
func ExtractSecurityGroups(page pagination.Page) ([]SecurityGroup, error) {
|
|
||||||
casted := page.(SecurityGroupPage).Body
|
|
||||||
var response struct {
|
|
||||||
SecurityGroups []SecurityGroup `mapstructure:"security_groups"`
|
|
||||||
}
|
|
||||||
|
|
||||||
err := mapstructure.WeakDecode(casted, &response)
|
|
||||||
|
|
||||||
return response.SecurityGroups, err
|
|
||||||
}
|
|
||||||
|
|
||||||
type commonResult struct {
|
|
||||||
gophercloud.Result
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateResult represents the result of a create operation.
|
|
||||||
type CreateResult struct {
|
|
||||||
commonResult
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetResult represents the result of a get operation.
|
|
||||||
type GetResult struct {
|
|
||||||
commonResult
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateResult represents the result of an update operation.
|
|
||||||
type UpdateResult struct {
|
|
||||||
commonResult
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract will extract a SecurityGroup struct from most responses.
|
|
||||||
func (r commonResult) Extract() (*SecurityGroup, error) {
|
|
||||||
if r.Err != nil {
|
|
||||||
return nil, r.Err
|
|
||||||
}
|
|
||||||
|
|
||||||
var response struct {
|
|
||||||
SecurityGroup SecurityGroup `mapstructure:"security_group"`
|
|
||||||
}
|
|
||||||
|
|
||||||
err := mapstructure.WeakDecode(r.Body, &response)
|
|
||||||
|
|
||||||
return &response.SecurityGroup, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateRuleResult represents the result when adding rules to a security group.
|
|
||||||
type CreateRuleResult struct {
|
|
||||||
gophercloud.Result
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract will extract a Rule struct from a CreateRuleResult.
|
|
||||||
func (r CreateRuleResult) Extract() (*Rule, error) {
|
|
||||||
if r.Err != nil {
|
|
||||||
return nil, r.Err
|
|
||||||
}
|
|
||||||
|
|
||||||
var response struct {
|
|
||||||
Rule Rule `mapstructure:"security_group_rule"`
|
|
||||||
}
|
|
||||||
|
|
||||||
err := mapstructure.WeakDecode(r.Body, &response)
|
|
||||||
|
|
||||||
return &response.Rule, err
|
|
||||||
}
|
|
|
@ -1,32 +0,0 @@
|
||||||
package secgroups
|
|
||||||
|
|
||||||
import "github.com/rackspace/gophercloud"
|
|
||||||
|
|
||||||
const (
|
|
||||||
secgrouppath = "os-security-groups"
|
|
||||||
rulepath = "os-security-group-rules"
|
|
||||||
)
|
|
||||||
|
|
||||||
func resourceURL(c *gophercloud.ServiceClient, id string) string {
|
|
||||||
return c.ServiceURL(secgrouppath, id)
|
|
||||||
}
|
|
||||||
|
|
||||||
func rootURL(c *gophercloud.ServiceClient) string {
|
|
||||||
return c.ServiceURL(secgrouppath)
|
|
||||||
}
|
|
||||||
|
|
||||||
func listByServerURL(c *gophercloud.ServiceClient, serverID string) string {
|
|
||||||
return c.ServiceURL("servers", serverID, secgrouppath)
|
|
||||||
}
|
|
||||||
|
|
||||||
func rootRuleURL(c *gophercloud.ServiceClient) string {
|
|
||||||
return c.ServiceURL(rulepath)
|
|
||||||
}
|
|
||||||
|
|
||||||
func resourceRuleURL(c *gophercloud.ServiceClient, id string) string {
|
|
||||||
return c.ServiceURL(rulepath, id)
|
|
||||||
}
|
|
||||||
|
|
||||||
func serverActionURL(c *gophercloud.ServiceClient, id string) string {
|
|
||||||
return c.ServiceURL("servers", id, "action")
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
// Package servergroups provides the ability to manage server groups
|
|
||||||
package servergroups
|
|
|
@ -1,161 +0,0 @@
|
||||||
// +build fixtures
|
|
||||||
|
|
||||||
package servergroups
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
th "github.com/rackspace/gophercloud/testhelper"
|
|
||||||
"github.com/rackspace/gophercloud/testhelper/client"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ListOutput is a sample response to a List call.
|
|
||||||
const ListOutput = `
|
|
||||||
{
|
|
||||||
"server_groups": [
|
|
||||||
{
|
|
||||||
"id": "616fb98f-46ca-475e-917e-2563e5a8cd19",
|
|
||||||
"name": "test",
|
|
||||||
"policies": [
|
|
||||||
"anti-affinity"
|
|
||||||
],
|
|
||||||
"members": [],
|
|
||||||
"metadata": {}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "4d8c3732-a248-40ed-bebc-539a6ffd25c0",
|
|
||||||
"name": "test2",
|
|
||||||
"policies": [
|
|
||||||
"affinity"
|
|
||||||
],
|
|
||||||
"members": [],
|
|
||||||
"metadata": {}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
// GetOutput is a sample response to a Get call.
|
|
||||||
const GetOutput = `
|
|
||||||
{
|
|
||||||
"server_group": {
|
|
||||||
"id": "616fb98f-46ca-475e-917e-2563e5a8cd19",
|
|
||||||
"name": "test",
|
|
||||||
"policies": [
|
|
||||||
"anti-affinity"
|
|
||||||
],
|
|
||||||
"members": [],
|
|
||||||
"metadata": {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
// CreateOutput is a sample response to a Post call
|
|
||||||
const CreateOutput = `
|
|
||||||
{
|
|
||||||
"server_group": {
|
|
||||||
"id": "616fb98f-46ca-475e-917e-2563e5a8cd19",
|
|
||||||
"name": "test",
|
|
||||||
"policies": [
|
|
||||||
"anti-affinity"
|
|
||||||
],
|
|
||||||
"members": [],
|
|
||||||
"metadata": {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
// FirstServerGroup is the first result in ListOutput.
|
|
||||||
var FirstServerGroup = ServerGroup{
|
|
||||||
ID: "616fb98f-46ca-475e-917e-2563e5a8cd19",
|
|
||||||
Name: "test",
|
|
||||||
Policies: []string{
|
|
||||||
"anti-affinity",
|
|
||||||
},
|
|
||||||
Members: []string{},
|
|
||||||
Metadata: map[string]interface{}{},
|
|
||||||
}
|
|
||||||
|
|
||||||
// SecondServerGroup is the second result in ListOutput.
|
|
||||||
var SecondServerGroup = ServerGroup{
|
|
||||||
ID: "4d8c3732-a248-40ed-bebc-539a6ffd25c0",
|
|
||||||
Name: "test2",
|
|
||||||
Policies: []string{
|
|
||||||
"affinity",
|
|
||||||
},
|
|
||||||
Members: []string{},
|
|
||||||
Metadata: map[string]interface{}{},
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExpectedServerGroupSlice is the slice of results that should be parsed
|
|
||||||
// from ListOutput, in the expected order.
|
|
||||||
var ExpectedServerGroupSlice = []ServerGroup{FirstServerGroup, SecondServerGroup}
|
|
||||||
|
|
||||||
// CreatedServerGroup is the parsed result from CreateOutput.
|
|
||||||
var CreatedServerGroup = ServerGroup{
|
|
||||||
ID: "616fb98f-46ca-475e-917e-2563e5a8cd19",
|
|
||||||
Name: "test",
|
|
||||||
Policies: []string{
|
|
||||||
"anti-affinity",
|
|
||||||
},
|
|
||||||
Members: []string{},
|
|
||||||
Metadata: map[string]interface{}{},
|
|
||||||
}
|
|
||||||
|
|
||||||
// HandleListSuccessfully configures the test server to respond to a List request.
|
|
||||||
func HandleListSuccessfully(t *testing.T) {
|
|
||||||
th.Mux.HandleFunc("/os-server-groups", func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
th.TestMethod(t, r, "GET")
|
|
||||||
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
|
||||||
|
|
||||||
w.Header().Add("Content-Type", "application/json")
|
|
||||||
fmt.Fprintf(w, ListOutput)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// HandleGetSuccessfully configures the test server to respond to a Get request
|
|
||||||
// for an existing server group
|
|
||||||
func HandleGetSuccessfully(t *testing.T) {
|
|
||||||
th.Mux.HandleFunc("/os-server-groups/4d8c3732-a248-40ed-bebc-539a6ffd25c0", func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
th.TestMethod(t, r, "GET")
|
|
||||||
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
|
||||||
|
|
||||||
w.Header().Add("Content-Type", "application/json")
|
|
||||||
fmt.Fprintf(w, GetOutput)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// HandleCreateSuccessfully configures the test server to respond to a Create request
|
|
||||||
// for a new server group
|
|
||||||
func HandleCreateSuccessfully(t *testing.T) {
|
|
||||||
th.Mux.HandleFunc("/os-server-groups", func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
th.TestMethod(t, r, "POST")
|
|
||||||
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
|
||||||
th.TestJSONRequest(t, r, `
|
|
||||||
{
|
|
||||||
"server_group": {
|
|
||||||
"name": "test",
|
|
||||||
"policies": [
|
|
||||||
"anti-affinity"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`)
|
|
||||||
|
|
||||||
w.Header().Add("Content-Type", "application/json")
|
|
||||||
fmt.Fprintf(w, CreateOutput)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// HandleDeleteSuccessfully configures the test server to respond to a Delete request for a
|
|
||||||
// an existing server group
|
|
||||||
func HandleDeleteSuccessfully(t *testing.T) {
|
|
||||||
th.Mux.HandleFunc("/os-server-groups/616fb98f-46ca-475e-917e-2563e5a8cd19", func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
th.TestMethod(t, r, "DELETE")
|
|
||||||
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
|
||||||
|
|
||||||
w.WriteHeader(http.StatusAccepted)
|
|
||||||
})
|
|
||||||
}
|
|
|
@ -1,77 +0,0 @@
|
||||||
package servergroups
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
|
|
||||||
"github.com/rackspace/gophercloud"
|
|
||||||
"github.com/rackspace/gophercloud/pagination"
|
|
||||||
)
|
|
||||||
|
|
||||||
// List returns a Pager that allows you to iterate over a collection of ServerGroups.
|
|
||||||
func List(client *gophercloud.ServiceClient) pagination.Pager {
|
|
||||||
return pagination.NewPager(client, listURL(client), func(r pagination.PageResult) pagination.Page {
|
|
||||||
return ServerGroupsPage{pagination.SinglePageBase(r)}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateOptsBuilder describes struct types that can be accepted by the Create call. Notably, the
|
|
||||||
// CreateOpts struct in this package does.
|
|
||||||
type CreateOptsBuilder interface {
|
|
||||||
ToServerGroupCreateMap() (map[string]interface{}, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateOpts specifies a Server Group allocation request
|
|
||||||
type CreateOpts struct {
|
|
||||||
// Name is the name of the server group
|
|
||||||
Name string
|
|
||||||
|
|
||||||
// Policies are the server group policies
|
|
||||||
Policies []string
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToServerGroupCreateMap constructs a request body from CreateOpts.
|
|
||||||
func (opts CreateOpts) ToServerGroupCreateMap() (map[string]interface{}, error) {
|
|
||||||
if opts.Name == "" {
|
|
||||||
return nil, errors.New("Missing field required for server group creation: Name")
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(opts.Policies) < 1 {
|
|
||||||
return nil, errors.New("Missing field required for server group creation: Policies")
|
|
||||||
}
|
|
||||||
|
|
||||||
serverGroup := make(map[string]interface{})
|
|
||||||
serverGroup["name"] = opts.Name
|
|
||||||
serverGroup["policies"] = opts.Policies
|
|
||||||
|
|
||||||
return map[string]interface{}{"server_group": serverGroup}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create requests the creation of a new Server Group
|
|
||||||
func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
|
|
||||||
var res CreateResult
|
|
||||||
|
|
||||||
reqBody, err := opts.ToServerGroupCreateMap()
|
|
||||||
if err != nil {
|
|
||||||
res.Err = err
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
_, res.Err = client.Post(createURL(client), reqBody, &res.Body, &gophercloud.RequestOpts{
|
|
||||||
OkCodes: []int{200},
|
|
||||||
})
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get returns data about a previously created ServerGroup.
|
|
||||||
func Get(client *gophercloud.ServiceClient, id string) GetResult {
|
|
||||||
var res GetResult
|
|
||||||
_, res.Err = client.Get(getURL(client, id), &res.Body, nil)
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete requests the deletion of a previously allocated ServerGroup.
|
|
||||||
func Delete(client *gophercloud.ServiceClient, id string) DeleteResult {
|
|
||||||
var res DeleteResult
|
|
||||||
_, res.Err = client.Delete(deleteURL(client, id), nil)
|
|
||||||
return res
|
|
||||||
}
|
|
|
@ -1,87 +0,0 @@
|
||||||
package servergroups
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/mitchellh/mapstructure"
|
|
||||||
"github.com/rackspace/gophercloud"
|
|
||||||
"github.com/rackspace/gophercloud/pagination"
|
|
||||||
)
|
|
||||||
|
|
||||||
// A ServerGroup creates a policy for instance placement in the cloud
|
|
||||||
type ServerGroup struct {
|
|
||||||
// ID is the unique ID of the Server Group.
|
|
||||||
ID string `mapstructure:"id"`
|
|
||||||
|
|
||||||
// Name is the common name of the server group.
|
|
||||||
Name string `mapstructure:"name"`
|
|
||||||
|
|
||||||
// Polices are the group policies.
|
|
||||||
Policies []string `mapstructure:"policies"`
|
|
||||||
|
|
||||||
// Members are the members of the server group.
|
|
||||||
Members []string `mapstructure:"members"`
|
|
||||||
|
|
||||||
// Metadata includes a list of all user-specified key-value pairs attached to the Server Group.
|
|
||||||
Metadata map[string]interface{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ServerGroupsPage stores a single, only page of ServerGroups
|
|
||||||
// results from a List call.
|
|
||||||
type ServerGroupsPage struct {
|
|
||||||
pagination.SinglePageBase
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsEmpty determines whether or not a ServerGroupsPage is empty.
|
|
||||||
func (page ServerGroupsPage) IsEmpty() (bool, error) {
|
|
||||||
va, err := ExtractServerGroups(page)
|
|
||||||
return len(va) == 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExtractServerGroups interprets a page of results as a slice of
|
|
||||||
// ServerGroups.
|
|
||||||
func ExtractServerGroups(page pagination.Page) ([]ServerGroup, error) {
|
|
||||||
casted := page.(ServerGroupsPage).Body
|
|
||||||
var response struct {
|
|
||||||
ServerGroups []ServerGroup `mapstructure:"server_groups"`
|
|
||||||
}
|
|
||||||
|
|
||||||
err := mapstructure.WeakDecode(casted, &response)
|
|
||||||
|
|
||||||
return response.ServerGroups, err
|
|
||||||
}
|
|
||||||
|
|
||||||
type ServerGroupResult struct {
|
|
||||||
gophercloud.Result
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract is a method that attempts to interpret any Server Group resource
|
|
||||||
// response as a ServerGroup struct.
|
|
||||||
func (r ServerGroupResult) Extract() (*ServerGroup, error) {
|
|
||||||
if r.Err != nil {
|
|
||||||
return nil, r.Err
|
|
||||||
}
|
|
||||||
|
|
||||||
var res struct {
|
|
||||||
ServerGroup *ServerGroup `json:"server_group" mapstructure:"server_group"`
|
|
||||||
}
|
|
||||||
|
|
||||||
err := mapstructure.WeakDecode(r.Body, &res)
|
|
||||||
return res.ServerGroup, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateResult is the response from a Create operation. Call its Extract method to interpret it
|
|
||||||
// as a ServerGroup.
|
|
||||||
type CreateResult struct {
|
|
||||||
ServerGroupResult
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetResult is the response from a Get operation. Call its Extract method to interpret it
|
|
||||||
// as a ServerGroup.
|
|
||||||
type GetResult struct {
|
|
||||||
ServerGroupResult
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteResult is the response from a Delete operation. Call its Extract method to determine if
|
|
||||||
// the call succeeded or failed.
|
|
||||||
type DeleteResult struct {
|
|
||||||
gophercloud.ErrResult
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
package servergroups
|
|
||||||
|
|
||||||
import "github.com/rackspace/gophercloud"
|
|
||||||
|
|
||||||
const resourcePath = "os-server-groups"
|
|
||||||
|
|
||||||
func resourceURL(c *gophercloud.ServiceClient) string {
|
|
||||||
return c.ServiceURL(resourcePath)
|
|
||||||
}
|
|
||||||
|
|
||||||
func listURL(c *gophercloud.ServiceClient) string {
|
|
||||||
return resourceURL(c)
|
|
||||||
}
|
|
||||||
|
|
||||||
func createURL(c *gophercloud.ServiceClient) string {
|
|
||||||
return resourceURL(c)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getURL(c *gophercloud.ServiceClient, id string) string {
|
|
||||||
return c.ServiceURL(resourcePath, id)
|
|
||||||
}
|
|
||||||
|
|
||||||
func deleteURL(c *gophercloud.ServiceClient, id string) string {
|
|
||||||
return getURL(c, id)
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
// Package tenantnetworks provides the ability for tenants to see information about the networks they have access to
|
|
||||||
package tenantnetworks
|
|
|
@ -1,84 +0,0 @@
|
||||||
// +build fixtures
|
|
||||||
|
|
||||||
package tenantnetworks
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
th "github.com/rackspace/gophercloud/testhelper"
|
|
||||||
"github.com/rackspace/gophercloud/testhelper/client"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ListOutput is a sample response to a List call.
|
|
||||||
const ListOutput = `
|
|
||||||
{
|
|
||||||
"networks": [
|
|
||||||
{
|
|
||||||
"cidr": "10.0.0.0/29",
|
|
||||||
"id": "20c8acc0-f747-4d71-a389-46d078ebf047",
|
|
||||||
"label": "mynet_0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"cidr": "10.0.0.10/29",
|
|
||||||
"id": "20c8acc0-f747-4d71-a389-46d078ebf000",
|
|
||||||
"label": "mynet_1"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
// GetOutput is a sample response to a Get call.
|
|
||||||
const GetOutput = `
|
|
||||||
{
|
|
||||||
"network": {
|
|
||||||
"cidr": "10.0.0.10/29",
|
|
||||||
"id": "20c8acc0-f747-4d71-a389-46d078ebf000",
|
|
||||||
"label": "mynet_1"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
// FirstNetwork is the first result in ListOutput.
|
|
||||||
var nilTime time.Time
|
|
||||||
var FirstNetwork = Network{
|
|
||||||
CIDR: "10.0.0.0/29",
|
|
||||||
ID: "20c8acc0-f747-4d71-a389-46d078ebf047",
|
|
||||||
Name: "mynet_0",
|
|
||||||
}
|
|
||||||
|
|
||||||
// SecondNetwork is the second result in ListOutput.
|
|
||||||
var SecondNetwork = Network{
|
|
||||||
CIDR: "10.0.0.10/29",
|
|
||||||
ID: "20c8acc0-f747-4d71-a389-46d078ebf000",
|
|
||||||
Name: "mynet_1",
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExpectedNetworkSlice is the slice of results that should be parsed
|
|
||||||
// from ListOutput, in the expected order.
|
|
||||||
var ExpectedNetworkSlice = []Network{FirstNetwork, SecondNetwork}
|
|
||||||
|
|
||||||
// HandleListSuccessfully configures the test server to respond to a List request.
|
|
||||||
func HandleListSuccessfully(t *testing.T) {
|
|
||||||
th.Mux.HandleFunc("/os-tenant-networks", func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
th.TestMethod(t, r, "GET")
|
|
||||||
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
|
||||||
|
|
||||||
w.Header().Add("Content-Type", "application/json")
|
|
||||||
fmt.Fprintf(w, ListOutput)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// HandleGetSuccessfully configures the test server to respond to a Get request
|
|
||||||
// for an existing network.
|
|
||||||
func HandleGetSuccessfully(t *testing.T) {
|
|
||||||
th.Mux.HandleFunc("/os-tenant-networks/20c8acc0-f747-4d71-a389-46d078ebf000", func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
th.TestMethod(t, r, "GET")
|
|
||||||
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
|
||||||
|
|
||||||
w.Header().Add("Content-Type", "application/json")
|
|
||||||
fmt.Fprintf(w, GetOutput)
|
|
||||||
})
|
|
||||||
}
|
|
|
@ -1,22 +0,0 @@
|
||||||
package tenantnetworks
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/rackspace/gophercloud"
|
|
||||||
"github.com/rackspace/gophercloud/pagination"
|
|
||||||
)
|
|
||||||
|
|
||||||
// List returns a Pager that allows you to iterate over a collection of Network.
|
|
||||||
func List(client *gophercloud.ServiceClient) pagination.Pager {
|
|
||||||
url := listURL(client)
|
|
||||||
createPage := func(r pagination.PageResult) pagination.Page {
|
|
||||||
return NetworkPage{pagination.SinglePageBase(r)}
|
|
||||||
}
|
|
||||||
return pagination.NewPager(client, url, createPage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get returns data about a previously created Network.
|
|
||||||
func Get(client *gophercloud.ServiceClient, id string) GetResult {
|
|
||||||
var res GetResult
|
|
||||||
_, res.Err = client.Get(getURL(client, id), &res.Body, nil)
|
|
||||||
return res
|
|
||||||
}
|
|
|
@ -1,68 +0,0 @@
|
||||||
package tenantnetworks
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/mitchellh/mapstructure"
|
|
||||||
"github.com/rackspace/gophercloud"
|
|
||||||
"github.com/rackspace/gophercloud/pagination"
|
|
||||||
)
|
|
||||||
|
|
||||||
// A Network represents a nova-network that an instance communicates on
|
|
||||||
type Network struct {
|
|
||||||
// CIDR is the IPv4 subnet.
|
|
||||||
CIDR string `mapstructure:"cidr"`
|
|
||||||
|
|
||||||
// ID is the UUID of the network.
|
|
||||||
ID string `mapstructure:"id"`
|
|
||||||
|
|
||||||
// Name is the common name that the network has.
|
|
||||||
Name string `mapstructure:"label"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// NetworkPage stores a single, only page of Networks
|
|
||||||
// results from a List call.
|
|
||||||
type NetworkPage struct {
|
|
||||||
pagination.SinglePageBase
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsEmpty determines whether or not a NetworkPage is empty.
|
|
||||||
func (page NetworkPage) IsEmpty() (bool, error) {
|
|
||||||
va, err := ExtractNetworks(page)
|
|
||||||
return len(va) == 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExtractNetworks interprets a page of results as a slice of Networks
|
|
||||||
func ExtractNetworks(page pagination.Page) ([]Network, error) {
|
|
||||||
networks := page.(NetworkPage).Body
|
|
||||||
var res struct {
|
|
||||||
Networks []Network `mapstructure:"networks"`
|
|
||||||
}
|
|
||||||
|
|
||||||
err := mapstructure.WeakDecode(networks, &res)
|
|
||||||
|
|
||||||
return res.Networks, err
|
|
||||||
}
|
|
||||||
|
|
||||||
type NetworkResult struct {
|
|
||||||
gophercloud.Result
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract is a method that attempts to interpret any Network resource
|
|
||||||
// response as a Network struct.
|
|
||||||
func (r NetworkResult) Extract() (*Network, error) {
|
|
||||||
if r.Err != nil {
|
|
||||||
return nil, r.Err
|
|
||||||
}
|
|
||||||
|
|
||||||
var res struct {
|
|
||||||
Network *Network `json:"network" mapstructure:"network"`
|
|
||||||
}
|
|
||||||
|
|
||||||
err := mapstructure.Decode(r.Body, &res)
|
|
||||||
return res.Network, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetResult is the response from a Get operation. Call its Extract method to interpret it
|
|
||||||
// as a Network.
|
|
||||||
type GetResult struct {
|
|
||||||
NetworkResult
|
|
||||||
}
|
|
|
@ -1,17 +0,0 @@
|
||||||
package tenantnetworks
|
|
||||||
|
|
||||||
import "github.com/rackspace/gophercloud"
|
|
||||||
|
|
||||||
const resourcePath = "os-tenant-networks"
|
|
||||||
|
|
||||||
func resourceURL(c *gophercloud.ServiceClient) string {
|
|
||||||
return c.ServiceURL(resourcePath)
|
|
||||||
}
|
|
||||||
|
|
||||||
func listURL(c *gophercloud.ServiceClient) string {
|
|
||||||
return resourceURL(c)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getURL(c *gophercloud.ServiceClient, id string) string {
|
|
||||||
return c.ServiceURL(resourcePath, id)
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
// Package volumeattach provides the ability to attach and detach volumes
|
|
||||||
// to instances
|
|
||||||
package volumeattach
|
|
|
@ -1,75 +0,0 @@
|
||||||
package volumeattach
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
|
|
||||||
"github.com/rackspace/gophercloud"
|
|
||||||
"github.com/rackspace/gophercloud/pagination"
|
|
||||||
)
|
|
||||||
|
|
||||||
// List returns a Pager that allows you to iterate over a collection of VolumeAttachments.
|
|
||||||
func List(client *gophercloud.ServiceClient, serverId string) pagination.Pager {
|
|
||||||
return pagination.NewPager(client, listURL(client, serverId), func(r pagination.PageResult) pagination.Page {
|
|
||||||
return VolumeAttachmentsPage{pagination.SinglePageBase(r)}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateOptsBuilder describes struct types that can be accepted by the Create call. Notable, the
|
|
||||||
// CreateOpts struct in this package does.
|
|
||||||
type CreateOptsBuilder interface {
|
|
||||||
ToVolumeAttachmentCreateMap() (map[string]interface{}, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateOpts specifies volume attachment creation or import parameters.
|
|
||||||
type CreateOpts struct {
|
|
||||||
// Device is the device that the volume will attach to the instance as. Omit for "auto"
|
|
||||||
Device string
|
|
||||||
|
|
||||||
// VolumeID is the ID of the volume to attach to the instance
|
|
||||||
VolumeID string
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToVolumeAttachmentCreateMap constructs a request body from CreateOpts.
|
|
||||||
func (opts CreateOpts) ToVolumeAttachmentCreateMap() (map[string]interface{}, error) {
|
|
||||||
if opts.VolumeID == "" {
|
|
||||||
return nil, errors.New("Missing field required for volume attachment creation: VolumeID")
|
|
||||||
}
|
|
||||||
|
|
||||||
volumeAttachment := make(map[string]interface{})
|
|
||||||
volumeAttachment["volumeId"] = opts.VolumeID
|
|
||||||
if opts.Device != "" {
|
|
||||||
volumeAttachment["device"] = opts.Device
|
|
||||||
}
|
|
||||||
|
|
||||||
return map[string]interface{}{"volumeAttachment": volumeAttachment}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create requests the creation of a new volume attachment on the server
|
|
||||||
func Create(client *gophercloud.ServiceClient, serverId string, opts CreateOptsBuilder) CreateResult {
|
|
||||||
var res CreateResult
|
|
||||||
|
|
||||||
reqBody, err := opts.ToVolumeAttachmentCreateMap()
|
|
||||||
if err != nil {
|
|
||||||
res.Err = err
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
_, res.Err = client.Post(createURL(client, serverId), reqBody, &res.Body, &gophercloud.RequestOpts{
|
|
||||||
OkCodes: []int{200},
|
|
||||||
})
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get returns public data about a previously created VolumeAttachment.
|
|
||||||
func Get(client *gophercloud.ServiceClient, serverId, aId string) GetResult {
|
|
||||||
var res GetResult
|
|
||||||
_, res.Err = client.Get(getURL(client, serverId, aId), &res.Body, nil)
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete requests the deletion of a previous stored VolumeAttachment from the server.
|
|
||||||
func Delete(client *gophercloud.ServiceClient, serverId, aId string) DeleteResult {
|
|
||||||
var res DeleteResult
|
|
||||||
_, res.Err = client.Delete(deleteURL(client, serverId, aId), nil)
|
|
||||||
return res
|
|
||||||
}
|
|
|
@ -1,84 +0,0 @@
|
||||||
package volumeattach
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/mitchellh/mapstructure"
|
|
||||||
"github.com/rackspace/gophercloud"
|
|
||||||
"github.com/rackspace/gophercloud/pagination"
|
|
||||||
)
|
|
||||||
|
|
||||||
// VolumeAttach controls the attachment of a volume to an instance.
|
|
||||||
type VolumeAttachment struct {
|
|
||||||
// ID is a unique id of the attachment
|
|
||||||
ID string `mapstructure:"id"`
|
|
||||||
|
|
||||||
// Device is what device the volume is attached as
|
|
||||||
Device string `mapstructure:"device"`
|
|
||||||
|
|
||||||
// VolumeID is the ID of the attached volume
|
|
||||||
VolumeID string `mapstructure:"volumeId"`
|
|
||||||
|
|
||||||
// ServerID is the ID of the instance that has the volume attached
|
|
||||||
ServerID string `mapstructure:"serverId"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// VolumeAttachmentsPage stores a single, only page of VolumeAttachments
|
|
||||||
// results from a List call.
|
|
||||||
type VolumeAttachmentsPage struct {
|
|
||||||
pagination.SinglePageBase
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsEmpty determines whether or not a VolumeAttachmentsPage is empty.
|
|
||||||
func (page VolumeAttachmentsPage) IsEmpty() (bool, error) {
|
|
||||||
va, err := ExtractVolumeAttachments(page)
|
|
||||||
return len(va) == 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExtractVolumeAttachments interprets a page of results as a slice of
|
|
||||||
// VolumeAttachments.
|
|
||||||
func ExtractVolumeAttachments(page pagination.Page) ([]VolumeAttachment, error) {
|
|
||||||
casted := page.(VolumeAttachmentsPage).Body
|
|
||||||
var response struct {
|
|
||||||
VolumeAttachments []VolumeAttachment `mapstructure:"volumeAttachments"`
|
|
||||||
}
|
|
||||||
|
|
||||||
err := mapstructure.WeakDecode(casted, &response)
|
|
||||||
|
|
||||||
return response.VolumeAttachments, err
|
|
||||||
}
|
|
||||||
|
|
||||||
type VolumeAttachmentResult struct {
|
|
||||||
gophercloud.Result
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract is a method that attempts to interpret any VolumeAttachment resource
|
|
||||||
// response as a VolumeAttachment struct.
|
|
||||||
func (r VolumeAttachmentResult) Extract() (*VolumeAttachment, error) {
|
|
||||||
if r.Err != nil {
|
|
||||||
return nil, r.Err
|
|
||||||
}
|
|
||||||
|
|
||||||
var res struct {
|
|
||||||
VolumeAttachment *VolumeAttachment `json:"volumeAttachment" mapstructure:"volumeAttachment"`
|
|
||||||
}
|
|
||||||
|
|
||||||
err := mapstructure.Decode(r.Body, &res)
|
|
||||||
return res.VolumeAttachment, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateResult is the response from a Create operation. Call its Extract method to interpret it
|
|
||||||
// as a VolumeAttachment.
|
|
||||||
type CreateResult struct {
|
|
||||||
VolumeAttachmentResult
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetResult is the response from a Get operation. Call its Extract method to interpret it
|
|
||||||
// as a VolumeAttachment.
|
|
||||||
type GetResult struct {
|
|
||||||
VolumeAttachmentResult
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteResult is the response from a Delete operation. Call its Extract method to determine if
|
|
||||||
// the call succeeded or failed.
|
|
||||||
type DeleteResult struct {
|
|
||||||
gophercloud.ErrResult
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
/*
|
|
||||||
This is package created is to hold fixtures (which imports testing),
|
|
||||||
so that importing volumeattach package does not inadvertently import testing into production code
|
|
||||||
More information here:
|
|
||||||
https://github.com/rackspace/gophercloud/issues/473
|
|
||||||
*/
|
|
||||||
package testing
|
|
|
@ -1,110 +0,0 @@
|
||||||
// +build fixtures
|
|
||||||
|
|
||||||
package testing
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
th "github.com/rackspace/gophercloud/testhelper"
|
|
||||||
"github.com/rackspace/gophercloud/testhelper/client"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ListOutput is a sample response to a List call.
|
|
||||||
const ListOutput = `
|
|
||||||
{
|
|
||||||
"volumeAttachments": [
|
|
||||||
{
|
|
||||||
"device": "/dev/vdd",
|
|
||||||
"id": "a26887c6-c47b-4654-abb5-dfadf7d3f803",
|
|
||||||
"serverId": "4d8c3732-a248-40ed-bebc-539a6ffd25c0",
|
|
||||||
"volumeId": "a26887c6-c47b-4654-abb5-dfadf7d3f803"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"device": "/dev/vdc",
|
|
||||||
"id": "a26887c6-c47b-4654-abb5-dfadf7d3f804",
|
|
||||||
"serverId": "4d8c3732-a248-40ed-bebc-539a6ffd25c0",
|
|
||||||
"volumeId": "a26887c6-c47b-4654-abb5-dfadf7d3f804"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
// GetOutput is a sample response to a Get call.
|
|
||||||
const GetOutput = `
|
|
||||||
{
|
|
||||||
"volumeAttachment": {
|
|
||||||
"device": "/dev/vdc",
|
|
||||||
"id": "a26887c6-c47b-4654-abb5-dfadf7d3f804",
|
|
||||||
"serverId": "4d8c3732-a248-40ed-bebc-539a6ffd25c0",
|
|
||||||
"volumeId": "a26887c6-c47b-4654-abb5-dfadf7d3f804"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
// CreateOutput is a sample response to a Create call.
|
|
||||||
const CreateOutput = `
|
|
||||||
{
|
|
||||||
"volumeAttachment": {
|
|
||||||
"device": "/dev/vdc",
|
|
||||||
"id": "a26887c6-c47b-4654-abb5-dfadf7d3f804",
|
|
||||||
"serverId": "4d8c3732-a248-40ed-bebc-539a6ffd25c0",
|
|
||||||
"volumeId": "a26887c6-c47b-4654-abb5-dfadf7d3f804"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
// HandleListSuccessfully configures the test server to respond to a List request.
|
|
||||||
func HandleListSuccessfully(t *testing.T) {
|
|
||||||
th.Mux.HandleFunc("/servers/4d8c3732-a248-40ed-bebc-539a6ffd25c0/os-volume_attachments", func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
th.TestMethod(t, r, "GET")
|
|
||||||
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
|
||||||
|
|
||||||
w.Header().Add("Content-Type", "application/json")
|
|
||||||
fmt.Fprintf(w, ListOutput)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// HandleGetSuccessfully configures the test server to respond to a Get request
|
|
||||||
// for an existing attachment
|
|
||||||
func HandleGetSuccessfully(t *testing.T) {
|
|
||||||
th.Mux.HandleFunc("/servers/4d8c3732-a248-40ed-bebc-539a6ffd25c0/os-volume_attachments/a26887c6-c47b-4654-abb5-dfadf7d3f804", func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
th.TestMethod(t, r, "GET")
|
|
||||||
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
|
||||||
|
|
||||||
w.Header().Add("Content-Type", "application/json")
|
|
||||||
fmt.Fprintf(w, GetOutput)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// HandleCreateSuccessfully configures the test server to respond to a Create request
|
|
||||||
// for a new attachment
|
|
||||||
func HandleCreateSuccessfully(t *testing.T) {
|
|
||||||
th.Mux.HandleFunc("/servers/4d8c3732-a248-40ed-bebc-539a6ffd25c0/os-volume_attachments", func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
th.TestMethod(t, r, "POST")
|
|
||||||
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
|
||||||
th.TestJSONRequest(t, r, `
|
|
||||||
{
|
|
||||||
"volumeAttachment": {
|
|
||||||
"volumeId": "a26887c6-c47b-4654-abb5-dfadf7d3f804",
|
|
||||||
"device": "/dev/vdc"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`)
|
|
||||||
|
|
||||||
w.Header().Add("Content-Type", "application/json")
|
|
||||||
fmt.Fprintf(w, CreateOutput)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// HandleDeleteSuccessfully configures the test server to respond to a Delete request for a
|
|
||||||
// an existing attachment
|
|
||||||
func HandleDeleteSuccessfully(t *testing.T) {
|
|
||||||
th.Mux.HandleFunc("/servers/4d8c3732-a248-40ed-bebc-539a6ffd25c0/os-volume_attachments/a26887c6-c47b-4654-abb5-dfadf7d3f804", func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
th.TestMethod(t, r, "DELETE")
|
|
||||||
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
|
||||||
|
|
||||||
w.WriteHeader(http.StatusAccepted)
|
|
||||||
})
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
package volumeattach
|
|
||||||
|
|
||||||
import "github.com/rackspace/gophercloud"
|
|
||||||
|
|
||||||
const resourcePath = "os-volume_attachments"
|
|
||||||
|
|
||||||
func resourceURL(c *gophercloud.ServiceClient, serverId string) string {
|
|
||||||
return c.ServiceURL("servers", serverId, resourcePath)
|
|
||||||
}
|
|
||||||
|
|
||||||
func listURL(c *gophercloud.ServiceClient, serverId string) string {
|
|
||||||
return resourceURL(c, serverId)
|
|
||||||
}
|
|
||||||
|
|
||||||
func createURL(c *gophercloud.ServiceClient, serverId string) string {
|
|
||||||
return resourceURL(c, serverId)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getURL(c *gophercloud.ServiceClient, serverId, aId string) string {
|
|
||||||
return c.ServiceURL("servers", serverId, resourcePath, aId)
|
|
||||||
}
|
|
||||||
|
|
||||||
func deleteURL(c *gophercloud.ServiceClient, serverId, aId string) string {
|
|
||||||
return getURL(c, serverId, aId)
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
// Package configurations provides information and interaction with the
|
|
||||||
// configuration API resource in the Rackspace Database service.
|
|
||||||
//
|
|
||||||
// A configuration group is a collection of key/value pairs which define how a
|
|
||||||
// particular database operates. These key/value pairs are specific to each
|
|
||||||
// datastore type and serve like settings. Some directives are capable of being
|
|
||||||
// applied dynamically, while other directives require a server restart to take
|
|
||||||
// effect. The configuration group can be applied to an instance at creation or
|
|
||||||
// applied to an existing instance to modify the behavior of the running
|
|
||||||
// datastore on the instance.
|
|
||||||
package configurations
|
|
157
vendor/github.com/rackspace/gophercloud/openstack/db/v1/configurations/fixtures.go
generated
vendored
157
vendor/github.com/rackspace/gophercloud/openstack/db/v1/configurations/fixtures.go
generated
vendored
|
@ -1,157 +0,0 @@
|
||||||
package configurations
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
timestamp = "2015-11-12T14:22:42Z"
|
|
||||||
timeVal, _ = time.Parse(time.RFC3339, timestamp)
|
|
||||||
)
|
|
||||||
|
|
||||||
var singleConfigJSON = `
|
|
||||||
{
|
|
||||||
"created": "` + timestamp + `",
|
|
||||||
"datastore_name": "mysql",
|
|
||||||
"datastore_version_id": "b00000b0-00b0-0b00-00b0-000b000000bb",
|
|
||||||
"datastore_version_name": "5.6",
|
|
||||||
"description": "example_description",
|
|
||||||
"id": "005a8bb7-a8df-40ee-b0b7-fc144641abc2",
|
|
||||||
"name": "example-configuration-name",
|
|
||||||
"updated": "` + timestamp + `"
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
var singleConfigWithValuesJSON = `
|
|
||||||
{
|
|
||||||
"created": "` + timestamp + `",
|
|
||||||
"datastore_name": "mysql",
|
|
||||||
"datastore_version_id": "b00000b0-00b0-0b00-00b0-000b000000bb",
|
|
||||||
"datastore_version_name": "5.6",
|
|
||||||
"description": "example description",
|
|
||||||
"id": "005a8bb7-a8df-40ee-b0b7-fc144641abc2",
|
|
||||||
"instance_count": 0,
|
|
||||||
"name": "example-configuration-name",
|
|
||||||
"updated": "` + timestamp + `",
|
|
||||||
"values": {
|
|
||||||
"collation_server": "latin1_swedish_ci",
|
|
||||||
"connect_timeout": 120
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
var (
|
|
||||||
ListConfigsJSON = fmt.Sprintf(`{"configurations": [%s]}`, singleConfigJSON)
|
|
||||||
GetConfigJSON = fmt.Sprintf(`{"configuration": %s}`, singleConfigJSON)
|
|
||||||
CreateConfigJSON = fmt.Sprintf(`{"configuration": %s}`, singleConfigWithValuesJSON)
|
|
||||||
)
|
|
||||||
|
|
||||||
var CreateReq = `
|
|
||||||
{
|
|
||||||
"configuration": {
|
|
||||||
"datastore": {
|
|
||||||
"type": "a00000a0-00a0-0a00-00a0-000a000000aa",
|
|
||||||
"version": "b00000b0-00b0-0b00-00b0-000b000000bb"
|
|
||||||
},
|
|
||||||
"description": "example description",
|
|
||||||
"name": "example-configuration-name",
|
|
||||||
"values": {
|
|
||||||
"collation_server": "latin1_swedish_ci",
|
|
||||||
"connect_timeout": 120
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
var UpdateReq = `
|
|
||||||
{
|
|
||||||
"configuration": {
|
|
||||||
"values": {
|
|
||||||
"connect_timeout": 300
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
var ListInstancesJSON = `
|
|
||||||
{
|
|
||||||
"instances": [
|
|
||||||
{
|
|
||||||
"id": "d4603f69-ec7e-4e9b-803f-600b9205576f",
|
|
||||||
"name": "json_rack_instance"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
var ListParamsJSON = `
|
|
||||||
{
|
|
||||||
"configuration-parameters": [
|
|
||||||
{
|
|
||||||
"max": 1,
|
|
||||||
"min": 0,
|
|
||||||
"name": "innodb_file_per_table",
|
|
||||||
"restart_required": true,
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"max": 4294967296,
|
|
||||||
"min": 0,
|
|
||||||
"name": "key_buffer_size",
|
|
||||||
"restart_required": false,
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"max": 65535,
|
|
||||||
"min": 2,
|
|
||||||
"name": "connect_timeout",
|
|
||||||
"restart_required": false,
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"max": 4294967296,
|
|
||||||
"min": 0,
|
|
||||||
"name": "join_buffer_size",
|
|
||||||
"restart_required": false,
|
|
||||||
"type": "integer"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
var GetParamJSON = `
|
|
||||||
{
|
|
||||||
"max": 1,
|
|
||||||
"min": 0,
|
|
||||||
"name": "innodb_file_per_table",
|
|
||||||
"restart_required": true,
|
|
||||||
"type": "integer"
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
var ExampleConfig = Config{
|
|
||||||
Created: timeVal,
|
|
||||||
DatastoreName: "mysql",
|
|
||||||
DatastoreVersionID: "b00000b0-00b0-0b00-00b0-000b000000bb",
|
|
||||||
DatastoreVersionName: "5.6",
|
|
||||||
Description: "example_description",
|
|
||||||
ID: "005a8bb7-a8df-40ee-b0b7-fc144641abc2",
|
|
||||||
Name: "example-configuration-name",
|
|
||||||
Updated: timeVal,
|
|
||||||
}
|
|
||||||
|
|
||||||
var ExampleConfigWithValues = Config{
|
|
||||||
Created: timeVal,
|
|
||||||
DatastoreName: "mysql",
|
|
||||||
DatastoreVersionID: "b00000b0-00b0-0b00-00b0-000b000000bb",
|
|
||||||
DatastoreVersionName: "5.6",
|
|
||||||
Description: "example description",
|
|
||||||
ID: "005a8bb7-a8df-40ee-b0b7-fc144641abc2",
|
|
||||||
Name: "example-configuration-name",
|
|
||||||
Updated: timeVal,
|
|
||||||
Values: map[string]interface{}{
|
|
||||||
"collation_server": "latin1_swedish_ci",
|
|
||||||
"connect_timeout": 120,
|
|
||||||
},
|
|
||||||
}
|
|
287
vendor/github.com/rackspace/gophercloud/openstack/db/v1/configurations/requests.go
generated
vendored
287
vendor/github.com/rackspace/gophercloud/openstack/db/v1/configurations/requests.go
generated
vendored
|
@ -1,287 +0,0 @@
|
||||||
package configurations
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
|
|
||||||
"github.com/rackspace/gophercloud"
|
|
||||||
"github.com/rackspace/gophercloud/openstack/db/v1/instances"
|
|
||||||
"github.com/rackspace/gophercloud/pagination"
|
|
||||||
)
|
|
||||||
|
|
||||||
// List will list all of the available configurations.
|
|
||||||
func List(client *gophercloud.ServiceClient) pagination.Pager {
|
|
||||||
pageFn := func(r pagination.PageResult) pagination.Page {
|
|
||||||
return ConfigPage{pagination.SinglePageBase(r)}
|
|
||||||
}
|
|
||||||
|
|
||||||
return pagination.NewPager(client, baseURL(client), pageFn)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateOptsBuilder is a top-level interface which renders a JSON map.
|
|
||||||
type CreateOptsBuilder interface {
|
|
||||||
ToConfigCreateMap() (map[string]interface{}, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DatastoreOpts is the primary options struct for creating and modifying
|
|
||||||
// how configuration resources are associated with datastores.
|
|
||||||
type DatastoreOpts struct {
|
|
||||||
// [OPTIONAL] The type of datastore. Defaults to "MySQL".
|
|
||||||
Type string
|
|
||||||
|
|
||||||
// [OPTIONAL] The specific version of a datastore. Defaults to "5.6".
|
|
||||||
Version string
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToMap renders a JSON map for a datastore setting.
|
|
||||||
func (opts DatastoreOpts) ToMap() (map[string]string, error) {
|
|
||||||
datastore := map[string]string{}
|
|
||||||
|
|
||||||
if opts.Type != "" {
|
|
||||||
datastore["type"] = opts.Type
|
|
||||||
}
|
|
||||||
|
|
||||||
if opts.Version != "" {
|
|
||||||
datastore["version"] = opts.Version
|
|
||||||
}
|
|
||||||
|
|
||||||
return datastore, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateOpts is the struct responsible for configuring new configurations.
|
|
||||||
type CreateOpts struct {
|
|
||||||
// [REQUIRED] The configuration group name
|
|
||||||
Name string
|
|
||||||
|
|
||||||
// [REQUIRED] A map of user-defined configuration settings that will define
|
|
||||||
// how each associated datastore works. Each key/value pair is specific to a
|
|
||||||
// datastore type.
|
|
||||||
Values map[string]interface{}
|
|
||||||
|
|
||||||
// [OPTIONAL] Associates the configuration group with a particular datastore.
|
|
||||||
Datastore *DatastoreOpts
|
|
||||||
|
|
||||||
// [OPTIONAL] A human-readable explanation for the group.
|
|
||||||
Description string
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToConfigCreateMap casts a CreateOpts struct into a JSON map.
|
|
||||||
func (opts CreateOpts) ToConfigCreateMap() (map[string]interface{}, error) {
|
|
||||||
if opts.Name == "" {
|
|
||||||
return nil, errors.New("Name is a required field")
|
|
||||||
}
|
|
||||||
if len(opts.Values) == 0 {
|
|
||||||
return nil, errors.New("Values must be a populated map")
|
|
||||||
}
|
|
||||||
|
|
||||||
config := map[string]interface{}{
|
|
||||||
"name": opts.Name,
|
|
||||||
"values": opts.Values,
|
|
||||||
}
|
|
||||||
|
|
||||||
if opts.Datastore != nil {
|
|
||||||
ds, err := opts.Datastore.ToMap()
|
|
||||||
if err != nil {
|
|
||||||
return config, err
|
|
||||||
}
|
|
||||||
config["datastore"] = ds
|
|
||||||
}
|
|
||||||
|
|
||||||
if opts.Description != "" {
|
|
||||||
config["description"] = opts.Description
|
|
||||||
}
|
|
||||||
|
|
||||||
return map[string]interface{}{"configuration": config}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create will create a new configuration group.
|
|
||||||
func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
|
|
||||||
var res CreateResult
|
|
||||||
|
|
||||||
reqBody, err := opts.ToConfigCreateMap()
|
|
||||||
if err != nil {
|
|
||||||
res.Err = err
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
_, res.Err = client.Request("POST", baseURL(client), gophercloud.RequestOpts{
|
|
||||||
OkCodes: []int{200},
|
|
||||||
JSONBody: &reqBody,
|
|
||||||
JSONResponse: &res.Body,
|
|
||||||
})
|
|
||||||
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get will retrieve the details for a specified configuration group.
|
|
||||||
func Get(client *gophercloud.ServiceClient, configID string) GetResult {
|
|
||||||
var res GetResult
|
|
||||||
|
|
||||||
_, res.Err = client.Request("GET", resourceURL(client, configID), gophercloud.RequestOpts{
|
|
||||||
OkCodes: []int{200},
|
|
||||||
JSONResponse: &res.Body,
|
|
||||||
})
|
|
||||||
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateOptsBuilder is the top-level interface for casting update options into
|
|
||||||
// JSON maps.
|
|
||||||
type UpdateOptsBuilder interface {
|
|
||||||
ToConfigUpdateMap() (map[string]interface{}, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateOpts is the struct responsible for modifying existing configurations.
|
|
||||||
type UpdateOpts struct {
|
|
||||||
// [OPTIONAL] The configuration group name
|
|
||||||
Name string
|
|
||||||
|
|
||||||
// [OPTIONAL] A map of user-defined configuration settings that will define
|
|
||||||
// how each associated datastore works. Each key/value pair is specific to a
|
|
||||||
// datastore type.
|
|
||||||
Values map[string]interface{}
|
|
||||||
|
|
||||||
// [OPTIONAL] Associates the configuration group with a particular datastore.
|
|
||||||
Datastore *DatastoreOpts
|
|
||||||
|
|
||||||
// [OPTIONAL] A human-readable explanation for the group.
|
|
||||||
Description string
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToConfigUpdateMap will cast an UpdateOpts struct into a JSON map.
|
|
||||||
func (opts UpdateOpts) ToConfigUpdateMap() (map[string]interface{}, error) {
|
|
||||||
config := map[string]interface{}{}
|
|
||||||
|
|
||||||
if opts.Name != "" {
|
|
||||||
config["name"] = opts.Name
|
|
||||||
}
|
|
||||||
|
|
||||||
if opts.Description != "" {
|
|
||||||
config["description"] = opts.Description
|
|
||||||
}
|
|
||||||
|
|
||||||
if opts.Datastore != nil {
|
|
||||||
ds, err := opts.Datastore.ToMap()
|
|
||||||
if err != nil {
|
|
||||||
return config, err
|
|
||||||
}
|
|
||||||
config["datastore"] = ds
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(opts.Values) > 0 {
|
|
||||||
config["values"] = opts.Values
|
|
||||||
}
|
|
||||||
|
|
||||||
return map[string]interface{}{"configuration": config}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update will modify an existing configuration group by performing a merge
|
|
||||||
// between new and existing values. If the key already exists, the new value
|
|
||||||
// will overwrite. All other keys will remain unaffected.
|
|
||||||
func Update(client *gophercloud.ServiceClient, configID string, opts UpdateOptsBuilder) UpdateResult {
|
|
||||||
var res UpdateResult
|
|
||||||
|
|
||||||
reqBody, err := opts.ToConfigUpdateMap()
|
|
||||||
if err != nil {
|
|
||||||
res.Err = err
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
_, res.Err = client.Request("PATCH", resourceURL(client, configID), gophercloud.RequestOpts{
|
|
||||||
OkCodes: []int{200},
|
|
||||||
JSONBody: &reqBody,
|
|
||||||
})
|
|
||||||
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
// Replace will modify an existing configuration group by overwriting the
|
|
||||||
// entire parameter group with the new values provided. Any existing keys not
|
|
||||||
// included in UpdateOptsBuilder will be deleted.
|
|
||||||
func Replace(client *gophercloud.ServiceClient, configID string, opts UpdateOptsBuilder) ReplaceResult {
|
|
||||||
var res ReplaceResult
|
|
||||||
|
|
||||||
reqBody, err := opts.ToConfigUpdateMap()
|
|
||||||
if err != nil {
|
|
||||||
res.Err = err
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
_, res.Err = client.Request("PUT", resourceURL(client, configID), gophercloud.RequestOpts{
|
|
||||||
OkCodes: []int{202},
|
|
||||||
JSONBody: &reqBody,
|
|
||||||
})
|
|
||||||
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete will permanently delete a configuration group. Please note that
|
|
||||||
// config groups cannot be deleted whilst still attached to running instances -
|
|
||||||
// you must detach and then delete them.
|
|
||||||
func Delete(client *gophercloud.ServiceClient, configID string) DeleteResult {
|
|
||||||
var res DeleteResult
|
|
||||||
|
|
||||||
_, res.Err = client.Request("DELETE", resourceURL(client, configID), gophercloud.RequestOpts{
|
|
||||||
OkCodes: []int{202},
|
|
||||||
})
|
|
||||||
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListInstances will list all the instances associated with a particular
|
|
||||||
// configuration group.
|
|
||||||
func ListInstances(client *gophercloud.ServiceClient, configID string) pagination.Pager {
|
|
||||||
pageFn := func(r pagination.PageResult) pagination.Page {
|
|
||||||
return instances.InstancePage{pagination.LinkedPageBase{PageResult: r}}
|
|
||||||
}
|
|
||||||
return pagination.NewPager(client, instancesURL(client, configID), pageFn)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListDatastoreParams will list all the available and supported parameters
|
|
||||||
// that can be used for a particular datastore ID and a particular version.
|
|
||||||
// For example, if you are wondering how you can configure a MySQL 5.6 instance,
|
|
||||||
// you can use this operation (you will need to retrieve the MySQL datastore ID
|
|
||||||
// by using the datastores API).
|
|
||||||
func ListDatastoreParams(client *gophercloud.ServiceClient, datastoreID, versionID string) pagination.Pager {
|
|
||||||
pageFn := func(r pagination.PageResult) pagination.Page {
|
|
||||||
return ParamPage{pagination.SinglePageBase(r)}
|
|
||||||
}
|
|
||||||
return pagination.NewPager(client, listDSParamsURL(client, datastoreID, versionID), pageFn)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetDatastoreParam will retrieve information about a specific configuration
|
|
||||||
// parameter. For example, you can use this operation to understand more about
|
|
||||||
// "innodb_file_per_table" configuration param for MySQL datastores. You will
|
|
||||||
// need the param's ID first, which can be attained by using the ListDatastoreParams
|
|
||||||
// operation.
|
|
||||||
func GetDatastoreParam(client *gophercloud.ServiceClient, datastoreID, versionID, paramID string) ParamResult {
|
|
||||||
var res ParamResult
|
|
||||||
|
|
||||||
_, res.Err = client.Request("GET", getDSParamURL(client, datastoreID, versionID, paramID), gophercloud.RequestOpts{
|
|
||||||
OkCodes: []int{200},
|
|
||||||
JSONResponse: &res.Body,
|
|
||||||
})
|
|
||||||
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListGlobalParams is similar to ListDatastoreParams but does not require a
|
|
||||||
// DatastoreID.
|
|
||||||
func ListGlobalParams(client *gophercloud.ServiceClient, versionID string) pagination.Pager {
|
|
||||||
pageFn := func(r pagination.PageResult) pagination.Page {
|
|
||||||
return ParamPage{pagination.SinglePageBase(r)}
|
|
||||||
}
|
|
||||||
return pagination.NewPager(client, listGlobalParamsURL(client, versionID), pageFn)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetGlobalParam is similar to GetDatastoreParam but does not require a
|
|
||||||
// DatastoreID.
|
|
||||||
func GetGlobalParam(client *gophercloud.ServiceClient, versionID, paramID string) ParamResult {
|
|
||||||
var res ParamResult
|
|
||||||
|
|
||||||
_, res.Err = client.Request("GET", getGlobalParamURL(client, versionID, paramID), gophercloud.RequestOpts{
|
|
||||||
OkCodes: []int{200},
|
|
||||||
JSONResponse: &res.Body,
|
|
||||||
})
|
|
||||||
|
|
||||||
return res
|
|
||||||
}
|
|
197
vendor/github.com/rackspace/gophercloud/openstack/db/v1/configurations/results.go
generated
vendored
197
vendor/github.com/rackspace/gophercloud/openstack/db/v1/configurations/results.go
generated
vendored
|
@ -1,197 +0,0 @@
|
||||||
package configurations
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"reflect"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/mitchellh/mapstructure"
|
|
||||||
"github.com/rackspace/gophercloud"
|
|
||||||
"github.com/rackspace/gophercloud/pagination"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Config represents a configuration group API resource.
|
|
||||||
type Config struct {
|
|
||||||
Created time.Time `mapstructure:"-"`
|
|
||||||
Updated time.Time `mapstructure:"-"`
|
|
||||||
DatastoreName string `mapstructure:"datastore_name"`
|
|
||||||
DatastoreVersionID string `mapstructure:"datastore_version_id"`
|
|
||||||
DatastoreVersionName string `mapstructure:"datastore_version_name"`
|
|
||||||
Description string
|
|
||||||
ID string
|
|
||||||
Name string
|
|
||||||
Values map[string]interface{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ConfigPage contains a page of Config resources in a paginated collection.
|
|
||||||
type ConfigPage struct {
|
|
||||||
pagination.SinglePageBase
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsEmpty indicates whether a ConfigPage is empty.
|
|
||||||
func (r ConfigPage) IsEmpty() (bool, error) {
|
|
||||||
is, err := ExtractConfigs(r)
|
|
||||||
if err != nil {
|
|
||||||
return true, err
|
|
||||||
}
|
|
||||||
return len(is) == 0, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExtractConfigs will retrieve a slice of Config structs from a page.
|
|
||||||
func ExtractConfigs(page pagination.Page) ([]Config, error) {
|
|
||||||
casted := page.(ConfigPage).Body
|
|
||||||
|
|
||||||
var resp struct {
|
|
||||||
Configs []Config `mapstructure:"configurations" json:"configurations"`
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := mapstructure.Decode(casted, &resp); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var vals []interface{}
|
|
||||||
switch casted.(type) {
|
|
||||||
case map[string]interface{}:
|
|
||||||
vals = casted.(map[string]interface{})["configurations"].([]interface{})
|
|
||||||
case map[string][]interface{}:
|
|
||||||
vals = casted.(map[string][]interface{})["configurations"]
|
|
||||||
default:
|
|
||||||
return resp.Configs, fmt.Errorf("Unknown type: %v", reflect.TypeOf(casted))
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, v := range vals {
|
|
||||||
val := v.(map[string]interface{})
|
|
||||||
|
|
||||||
if t, ok := val["created"].(string); ok && t != "" {
|
|
||||||
creationTime, err := time.Parse(time.RFC3339, t)
|
|
||||||
if err != nil {
|
|
||||||
return resp.Configs, err
|
|
||||||
}
|
|
||||||
resp.Configs[i].Created = creationTime
|
|
||||||
}
|
|
||||||
|
|
||||||
if t, ok := val["updated"].(string); ok && t != "" {
|
|
||||||
updatedTime, err := time.Parse(time.RFC3339, t)
|
|
||||||
if err != nil {
|
|
||||||
return resp.Configs, err
|
|
||||||
}
|
|
||||||
resp.Configs[i].Updated = updatedTime
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return resp.Configs, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type commonResult struct {
|
|
||||||
gophercloud.Result
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract will retrieve a Config resource from an operation result.
|
|
||||||
func (r commonResult) Extract() (*Config, error) {
|
|
||||||
if r.Err != nil {
|
|
||||||
return nil, r.Err
|
|
||||||
}
|
|
||||||
|
|
||||||
var response struct {
|
|
||||||
Config Config `mapstructure:"configuration"`
|
|
||||||
}
|
|
||||||
|
|
||||||
err := mapstructure.Decode(r.Body, &response)
|
|
||||||
val := r.Body.(map[string]interface{})["configuration"].(map[string]interface{})
|
|
||||||
|
|
||||||
if t, ok := val["created"].(string); ok && t != "" {
|
|
||||||
creationTime, err := time.Parse(time.RFC3339, t)
|
|
||||||
if err != nil {
|
|
||||||
return &response.Config, err
|
|
||||||
}
|
|
||||||
response.Config.Created = creationTime
|
|
||||||
}
|
|
||||||
|
|
||||||
if t, ok := val["updated"].(string); ok && t != "" {
|
|
||||||
updatedTime, err := time.Parse(time.RFC3339, t)
|
|
||||||
if err != nil {
|
|
||||||
return &response.Config, err
|
|
||||||
}
|
|
||||||
response.Config.Updated = updatedTime
|
|
||||||
}
|
|
||||||
|
|
||||||
return &response.Config, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetResult represents the result of a Get operation.
|
|
||||||
type GetResult struct {
|
|
||||||
commonResult
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateResult represents the result of a Create operation.
|
|
||||||
type CreateResult struct {
|
|
||||||
commonResult
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateResult represents the result of an Update operation.
|
|
||||||
type UpdateResult struct {
|
|
||||||
gophercloud.ErrResult
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReplaceResult represents the result of a Replace operation.
|
|
||||||
type ReplaceResult struct {
|
|
||||||
gophercloud.ErrResult
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteResult represents the result of a Delete operation.
|
|
||||||
type DeleteResult struct {
|
|
||||||
gophercloud.ErrResult
|
|
||||||
}
|
|
||||||
|
|
||||||
// Param represents a configuration parameter API resource.
|
|
||||||
type Param struct {
|
|
||||||
Max int
|
|
||||||
Min int
|
|
||||||
Name string
|
|
||||||
RestartRequired bool `mapstructure:"restart_required" json:"restart_required"`
|
|
||||||
Type string
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParamPage contains a page of Param resources in a paginated collection.
|
|
||||||
type ParamPage struct {
|
|
||||||
pagination.SinglePageBase
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsEmpty indicates whether a ParamPage is empty.
|
|
||||||
func (r ParamPage) IsEmpty() (bool, error) {
|
|
||||||
is, err := ExtractParams(r)
|
|
||||||
if err != nil {
|
|
||||||
return true, err
|
|
||||||
}
|
|
||||||
return len(is) == 0, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExtractParams will retrieve a slice of Param structs from a page.
|
|
||||||
func ExtractParams(page pagination.Page) ([]Param, error) {
|
|
||||||
casted := page.(ParamPage).Body
|
|
||||||
|
|
||||||
var resp struct {
|
|
||||||
Params []Param `mapstructure:"configuration-parameters" json:"configuration-parameters"`
|
|
||||||
}
|
|
||||||
|
|
||||||
err := mapstructure.Decode(casted, &resp)
|
|
||||||
return resp.Params, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParamResult represents the result of an operation which retrieves details
|
|
||||||
// about a particular configuration param.
|
|
||||||
type ParamResult struct {
|
|
||||||
gophercloud.Result
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract will retrieve a param from an operation result.
|
|
||||||
func (r ParamResult) Extract() (*Param, error) {
|
|
||||||
if r.Err != nil {
|
|
||||||
return nil, r.Err
|
|
||||||
}
|
|
||||||
|
|
||||||
var param Param
|
|
||||||
|
|
||||||
err := mapstructure.Decode(r.Body, ¶m)
|
|
||||||
return ¶m, err
|
|
||||||
}
|
|
31
vendor/github.com/rackspace/gophercloud/openstack/db/v1/configurations/urls.go
generated
vendored
31
vendor/github.com/rackspace/gophercloud/openstack/db/v1/configurations/urls.go
generated
vendored
|
@ -1,31 +0,0 @@
|
||||||
package configurations
|
|
||||||
|
|
||||||
import "github.com/rackspace/gophercloud"
|
|
||||||
|
|
||||||
func baseURL(c *gophercloud.ServiceClient) string {
|
|
||||||
return c.ServiceURL("configurations")
|
|
||||||
}
|
|
||||||
|
|
||||||
func resourceURL(c *gophercloud.ServiceClient, configID string) string {
|
|
||||||
return c.ServiceURL("configurations", configID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func instancesURL(c *gophercloud.ServiceClient, configID string) string {
|
|
||||||
return c.ServiceURL("configurations", configID, "instances")
|
|
||||||
}
|
|
||||||
|
|
||||||
func listDSParamsURL(c *gophercloud.ServiceClient, datastoreID, versionID string) string {
|
|
||||||
return c.ServiceURL("datastores", datastoreID, "versions", versionID, "parameters")
|
|
||||||
}
|
|
||||||
|
|
||||||
func getDSParamURL(c *gophercloud.ServiceClient, datastoreID, versionID, paramID string) string {
|
|
||||||
return c.ServiceURL("datastores", datastoreID, "versions", versionID, "parameters", paramID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func listGlobalParamsURL(c *gophercloud.ServiceClient, versionID string) string {
|
|
||||||
return c.ServiceURL("datastores", "versions", versionID, "parameters")
|
|
||||||
}
|
|
||||||
|
|
||||||
func getGlobalParamURL(c *gophercloud.ServiceClient, versionID, paramID string) string {
|
|
||||||
return c.ServiceURL("datastores", "versions", versionID, "parameters", paramID)
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
// Package flavors provides information and interaction with the database API
|
|
||||||
// resource in the OpenStack Database service.
|
|
||||||
//
|
|
||||||
// A database, when referred to here, refers to the database engine running on
|
|
||||||
// an instance.
|
|
||||||
package databases
|
|
|
@ -1,61 +0,0 @@
|
||||||
package databases
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/rackspace/gophercloud/testhelper/fixture"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
instanceID = "{instanceID}"
|
|
||||||
resURL = "/instances/" + instanceID + "/databases"
|
|
||||||
)
|
|
||||||
|
|
||||||
var createDBsReq = `
|
|
||||||
{
|
|
||||||
"databases": [
|
|
||||||
{
|
|
||||||
"character_set": "utf8",
|
|
||||||
"collate": "utf8_general_ci",
|
|
||||||
"name": "testingdb"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "sampledb"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
var listDBsResp = `
|
|
||||||
{
|
|
||||||
"databases": [
|
|
||||||
{
|
|
||||||
"name": "anotherexampledb"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "exampledb"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "nextround"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "sampledb"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "testingdb"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
func HandleCreate(t *testing.T) {
|
|
||||||
fixture.SetupHandler(t, resURL, "POST", createDBsReq, "", 202)
|
|
||||||
}
|
|
||||||
|
|
||||||
func HandleList(t *testing.T) {
|
|
||||||
fixture.SetupHandler(t, resURL, "GET", "", listDBsResp, 200)
|
|
||||||
}
|
|
||||||
|
|
||||||
func HandleDelete(t *testing.T) {
|
|
||||||
fixture.SetupHandler(t, resURL+"/{dbName}", "DELETE", "", "", 202)
|
|
||||||
}
|
|
115
vendor/github.com/rackspace/gophercloud/openstack/db/v1/databases/requests.go
generated
vendored
115
vendor/github.com/rackspace/gophercloud/openstack/db/v1/databases/requests.go
generated
vendored
|
@ -1,115 +0,0 @@
|
||||||
package databases
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/rackspace/gophercloud"
|
|
||||||
"github.com/rackspace/gophercloud/pagination"
|
|
||||||
)
|
|
||||||
|
|
||||||
// CreateOptsBuilder builds create options
|
|
||||||
type CreateOptsBuilder interface {
|
|
||||||
ToDBCreateMap() (map[string]interface{}, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DatabaseOpts is the struct responsible for configuring a database; often in
|
|
||||||
// the context of an instance.
|
|
||||||
type CreateOpts struct {
|
|
||||||
// [REQUIRED] Specifies the name of the database. Valid names can be composed
|
|
||||||
// of the following characters: letters (either case); numbers; these
|
|
||||||
// characters '@', '?', '#', ' ' but NEVER beginning a name string; '_' is
|
|
||||||
// permitted anywhere. Prohibited characters that are forbidden include:
|
|
||||||
// single quotes, double quotes, back quotes, semicolons, commas, backslashes,
|
|
||||||
// and forward slashes.
|
|
||||||
Name string
|
|
||||||
|
|
||||||
// [OPTIONAL] Set of symbols and encodings. The default character set is
|
|
||||||
// "utf8". See http://dev.mysql.com/doc/refman/5.1/en/charset-mysql.html for
|
|
||||||
// supported character sets.
|
|
||||||
CharSet string
|
|
||||||
|
|
||||||
// [OPTIONAL] Set of rules for comparing characters in a character set. The
|
|
||||||
// default value for collate is "utf8_general_ci". See
|
|
||||||
// http://dev.mysql.com/doc/refman/5.1/en/charset-mysql.html for supported
|
|
||||||
// collations.
|
|
||||||
Collate string
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToMap is a helper function to convert individual DB create opt structures
|
|
||||||
// into sub-maps.
|
|
||||||
func (opts CreateOpts) ToMap() (map[string]string, error) {
|
|
||||||
if opts.Name == "" {
|
|
||||||
return nil, fmt.Errorf("Name is a required field")
|
|
||||||
}
|
|
||||||
if len(opts.Name) > 64 {
|
|
||||||
return nil, fmt.Errorf("Name must be less than 64 chars long")
|
|
||||||
}
|
|
||||||
|
|
||||||
db := map[string]string{"name": opts.Name}
|
|
||||||
|
|
||||||
if opts.CharSet != "" {
|
|
||||||
db["character_set"] = opts.CharSet
|
|
||||||
}
|
|
||||||
if opts.Collate != "" {
|
|
||||||
db["collate"] = opts.Collate
|
|
||||||
}
|
|
||||||
return db, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// BatchCreateOpts allows for multiple databases to created and modified.
|
|
||||||
type BatchCreateOpts []CreateOpts
|
|
||||||
|
|
||||||
// ToDBCreateMap renders a JSON map for creating DBs.
|
|
||||||
func (opts BatchCreateOpts) ToDBCreateMap() (map[string]interface{}, error) {
|
|
||||||
dbs := make([]map[string]string, len(opts))
|
|
||||||
for i, db := range opts {
|
|
||||||
dbMap, err := db.ToMap()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
dbs[i] = dbMap
|
|
||||||
}
|
|
||||||
return map[string]interface{}{"databases": dbs}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create will create a new database within the specified instance. If the
|
|
||||||
// specified instance does not exist, a 404 error will be returned.
|
|
||||||
func Create(client *gophercloud.ServiceClient, instanceID string, opts CreateOptsBuilder) CreateResult {
|
|
||||||
var res CreateResult
|
|
||||||
|
|
||||||
reqBody, err := opts.ToDBCreateMap()
|
|
||||||
if err != nil {
|
|
||||||
res.Err = err
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
_, res.Err = client.Request("POST", baseURL(client, instanceID), gophercloud.RequestOpts{
|
|
||||||
JSONBody: &reqBody,
|
|
||||||
OkCodes: []int{202},
|
|
||||||
})
|
|
||||||
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
// List will list all of the databases for a specified instance. Note: this
|
|
||||||
// operation will only return user-defined databases; it will exclude system
|
|
||||||
// databases like "mysql", "information_schema", "lost+found" etc.
|
|
||||||
func List(client *gophercloud.ServiceClient, instanceID string) pagination.Pager {
|
|
||||||
createPageFn := func(r pagination.PageResult) pagination.Page {
|
|
||||||
return DBPage{pagination.LinkedPageBase{PageResult: r}}
|
|
||||||
}
|
|
||||||
|
|
||||||
return pagination.NewPager(client, baseURL(client, instanceID), createPageFn)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete will permanently delete the database within a specified instance.
|
|
||||||
// All contained data inside the database will also be permanently deleted.
|
|
||||||
func Delete(client *gophercloud.ServiceClient, instanceID, dbName string) DeleteResult {
|
|
||||||
var res DeleteResult
|
|
||||||
|
|
||||||
_, res.Err = client.Request("DELETE", dbURL(client, instanceID, dbName), gophercloud.RequestOpts{
|
|
||||||
OkCodes: []int{202},
|
|
||||||
})
|
|
||||||
|
|
||||||
return res
|
|
||||||
}
|
|
|
@ -1,72 +0,0 @@
|
||||||
package databases
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/mitchellh/mapstructure"
|
|
||||||
"github.com/rackspace/gophercloud"
|
|
||||||
"github.com/rackspace/gophercloud/pagination"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Database represents a Database API resource.
|
|
||||||
type Database struct {
|
|
||||||
// Specifies the name of the MySQL database.
|
|
||||||
Name string
|
|
||||||
|
|
||||||
// Set of symbols and encodings. The default character set is utf8.
|
|
||||||
CharSet string
|
|
||||||
|
|
||||||
// Set of rules for comparing characters in a character set. The default
|
|
||||||
// value for collate is utf8_general_ci.
|
|
||||||
Collate string
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateResult represents the result of a Create operation.
|
|
||||||
type CreateResult struct {
|
|
||||||
gophercloud.ErrResult
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteResult represents the result of a Delete operation.
|
|
||||||
type DeleteResult struct {
|
|
||||||
gophercloud.ErrResult
|
|
||||||
}
|
|
||||||
|
|
||||||
// DBPage represents a single page of a paginated DB collection.
|
|
||||||
type DBPage struct {
|
|
||||||
pagination.LinkedPageBase
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsEmpty checks to see whether the collection is empty.
|
|
||||||
func (page DBPage) IsEmpty() (bool, error) {
|
|
||||||
dbs, err := ExtractDBs(page)
|
|
||||||
if err != nil {
|
|
||||||
return true, err
|
|
||||||
}
|
|
||||||
return len(dbs) == 0, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// NextPageURL will retrieve the next page URL.
|
|
||||||
func (page DBPage) NextPageURL() (string, error) {
|
|
||||||
type resp struct {
|
|
||||||
Links []gophercloud.Link `mapstructure:"databases_links"`
|
|
||||||
}
|
|
||||||
|
|
||||||
var r resp
|
|
||||||
err := mapstructure.Decode(page.Body, &r)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return gophercloud.ExtractNextURL(r.Links)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExtractDBs will convert a generic pagination struct into a more
|
|
||||||
// relevant slice of DB structs.
|
|
||||||
func ExtractDBs(page pagination.Page) ([]Database, error) {
|
|
||||||
casted := page.(DBPage).Body
|
|
||||||
|
|
||||||
var response struct {
|
|
||||||
Databases []Database `mapstructure:"databases"`
|
|
||||||
}
|
|
||||||
|
|
||||||
err := mapstructure.Decode(casted, &response)
|
|
||||||
return response.Databases, err
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
package databases
|
|
||||||
|
|
||||||
import "github.com/rackspace/gophercloud"
|
|
||||||
|
|
||||||
func baseURL(c *gophercloud.ServiceClient, instanceID string) string {
|
|
||||||
return c.ServiceURL("instances", instanceID, "databases")
|
|
||||||
}
|
|
||||||
|
|
||||||
func dbURL(c *gophercloud.ServiceClient, instanceID, dbName string) string {
|
|
||||||
return c.ServiceURL("instances", instanceID, "databases", dbName)
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
// Package datastores provides information and interaction with the datastore
|
|
||||||
// API resource in the Rackspace Database service.
|
|
||||||
package datastores
|
|
100
vendor/github.com/rackspace/gophercloud/openstack/db/v1/datastores/fixtures.go
generated
vendored
100
vendor/github.com/rackspace/gophercloud/openstack/db/v1/datastores/fixtures.go
generated
vendored
|
@ -1,100 +0,0 @@
|
||||||
package datastores
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/rackspace/gophercloud"
|
|
||||||
)
|
|
||||||
|
|
||||||
const version1JSON = `
|
|
||||||
{
|
|
||||||
"id": "b00000b0-00b0-0b00-00b0-000b000000bb",
|
|
||||||
"links": [
|
|
||||||
{
|
|
||||||
"href": "https://10.240.28.38:8779/v1.0/1234/datastores/versions/b00000b0-00b0-0b00-00b0-000b000000bb",
|
|
||||||
"rel": "self"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"href": "https://10.240.28.38:8779/datastores/versions/b00000b0-00b0-0b00-00b0-000b000000bb",
|
|
||||||
"rel": "bookmark"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"name": "5.1"
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
const version2JSON = `
|
|
||||||
{
|
|
||||||
"id": "c00000b0-00c0-0c00-00c0-000b000000cc",
|
|
||||||
"links": [
|
|
||||||
{
|
|
||||||
"href": "https://10.240.28.38:8779/v1.0/1234/datastores/versions/c00000b0-00c0-0c00-00c0-000b000000cc",
|
|
||||||
"rel": "self"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"href": "https://10.240.28.38:8779/datastores/versions/c00000b0-00c0-0c00-00c0-000b000000cc",
|
|
||||||
"rel": "bookmark"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"name": "5.2"
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
var versionsJSON = fmt.Sprintf(`"versions": [%s, %s]`, version1JSON, version2JSON)
|
|
||||||
|
|
||||||
var singleDSJSON = fmt.Sprintf(`
|
|
||||||
{
|
|
||||||
"default_version": "c00000b0-00c0-0c00-00c0-000b000000cc",
|
|
||||||
"id": "10000000-0000-0000-0000-000000000001",
|
|
||||||
"links": [
|
|
||||||
{
|
|
||||||
"href": "https://10.240.28.38:8779/v1.0/1234/datastores/10000000-0000-0000-0000-000000000001",
|
|
||||||
"rel": "self"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"href": "https://10.240.28.38:8779/datastores/10000000-0000-0000-0000-000000000001",
|
|
||||||
"rel": "bookmark"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"name": "mysql",
|
|
||||||
%s
|
|
||||||
}
|
|
||||||
`, versionsJSON)
|
|
||||||
|
|
||||||
var (
|
|
||||||
ListDSResp = fmt.Sprintf(`{"datastores":[%s]}`, singleDSJSON)
|
|
||||||
GetDSResp = fmt.Sprintf(`{"datastore":%s}`, singleDSJSON)
|
|
||||||
ListVersionsResp = fmt.Sprintf(`{%s}`, versionsJSON)
|
|
||||||
GetVersionResp = fmt.Sprintf(`{"version":%s}`, version1JSON)
|
|
||||||
)
|
|
||||||
|
|
||||||
var ExampleVersion1 = Version{
|
|
||||||
ID: "b00000b0-00b0-0b00-00b0-000b000000bb",
|
|
||||||
Links: []gophercloud.Link{
|
|
||||||
gophercloud.Link{Rel: "self", Href: "https://10.240.28.38:8779/v1.0/1234/datastores/versions/b00000b0-00b0-0b00-00b0-000b000000bb"},
|
|
||||||
gophercloud.Link{Rel: "bookmark", Href: "https://10.240.28.38:8779/datastores/versions/b00000b0-00b0-0b00-00b0-000b000000bb"},
|
|
||||||
},
|
|
||||||
Name: "5.1",
|
|
||||||
}
|
|
||||||
|
|
||||||
var exampleVersion2 = Version{
|
|
||||||
ID: "c00000b0-00c0-0c00-00c0-000b000000cc",
|
|
||||||
Links: []gophercloud.Link{
|
|
||||||
gophercloud.Link{Rel: "self", Href: "https://10.240.28.38:8779/v1.0/1234/datastores/versions/c00000b0-00c0-0c00-00c0-000b000000cc"},
|
|
||||||
gophercloud.Link{Rel: "bookmark", Href: "https://10.240.28.38:8779/datastores/versions/c00000b0-00c0-0c00-00c0-000b000000cc"},
|
|
||||||
},
|
|
||||||
Name: "5.2",
|
|
||||||
}
|
|
||||||
|
|
||||||
var ExampleVersions = []Version{ExampleVersion1, exampleVersion2}
|
|
||||||
|
|
||||||
var ExampleDatastore = Datastore{
|
|
||||||
DefaultVersion: "c00000b0-00c0-0c00-00c0-000b000000cc",
|
|
||||||
ID: "10000000-0000-0000-0000-000000000001",
|
|
||||||
Links: []gophercloud.Link{
|
|
||||||
gophercloud.Link{Rel: "self", Href: "https://10.240.28.38:8779/v1.0/1234/datastores/10000000-0000-0000-0000-000000000001"},
|
|
||||||
gophercloud.Link{Rel: "bookmark", Href: "https://10.240.28.38:8779/datastores/10000000-0000-0000-0000-000000000001"},
|
|
||||||
},
|
|
||||||
Name: "mysql",
|
|
||||||
Versions: ExampleVersions,
|
|
||||||
}
|
|
47
vendor/github.com/rackspace/gophercloud/openstack/db/v1/datastores/requests.go
generated
vendored
47
vendor/github.com/rackspace/gophercloud/openstack/db/v1/datastores/requests.go
generated
vendored
|
@ -1,47 +0,0 @@
|
||||||
package datastores
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/rackspace/gophercloud"
|
|
||||||
"github.com/rackspace/gophercloud/pagination"
|
|
||||||
)
|
|
||||||
|
|
||||||
// List will list all available datastore types that instances can use.
|
|
||||||
func List(client *gophercloud.ServiceClient) pagination.Pager {
|
|
||||||
pageFn := func(r pagination.PageResult) pagination.Page {
|
|
||||||
return DatastorePage{pagination.SinglePageBase(r)}
|
|
||||||
}
|
|
||||||
return pagination.NewPager(client, baseURL(client), pageFn)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get will retrieve the details of a specified datastore type.
|
|
||||||
func Get(client *gophercloud.ServiceClient, datastoreID string) GetResult {
|
|
||||||
var res GetResult
|
|
||||||
|
|
||||||
_, res.Err = client.Request("GET", resourceURL(client, datastoreID), gophercloud.RequestOpts{
|
|
||||||
OkCodes: []int{200},
|
|
||||||
JSONResponse: &res.Body,
|
|
||||||
})
|
|
||||||
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListVersions will list all of the available versions for a specified
|
|
||||||
// datastore type.
|
|
||||||
func ListVersions(client *gophercloud.ServiceClient, datastoreID string) pagination.Pager {
|
|
||||||
pageFn := func(r pagination.PageResult) pagination.Page {
|
|
||||||
return VersionPage{pagination.SinglePageBase(r)}
|
|
||||||
}
|
|
||||||
return pagination.NewPager(client, versionsURL(client, datastoreID), pageFn)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetVersion will retrieve the details of a specified datastore version.
|
|
||||||
func GetVersion(client *gophercloud.ServiceClient, datastoreID, versionID string) GetVersionResult {
|
|
||||||
var res GetVersionResult
|
|
||||||
|
|
||||||
_, res.Err = client.Request("GET", versionURL(client, datastoreID, versionID), gophercloud.RequestOpts{
|
|
||||||
OkCodes: []int{200},
|
|
||||||
JSONResponse: &res.Body,
|
|
||||||
})
|
|
||||||
|
|
||||||
return res
|
|
||||||
}
|
|
123
vendor/github.com/rackspace/gophercloud/openstack/db/v1/datastores/results.go
generated
vendored
123
vendor/github.com/rackspace/gophercloud/openstack/db/v1/datastores/results.go
generated
vendored
|
@ -1,123 +0,0 @@
|
||||||
package datastores
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/mitchellh/mapstructure"
|
|
||||||
"github.com/rackspace/gophercloud"
|
|
||||||
"github.com/rackspace/gophercloud/pagination"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Version represents a version API resource. Multiple versions belong to a Datastore.
|
|
||||||
type Version struct {
|
|
||||||
ID string
|
|
||||||
Links []gophercloud.Link
|
|
||||||
Name string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Datastore represents a Datastore API resource.
|
|
||||||
type Datastore struct {
|
|
||||||
DefaultVersion string `json:"default_version" mapstructure:"default_version"`
|
|
||||||
ID string
|
|
||||||
Links []gophercloud.Link
|
|
||||||
Name string
|
|
||||||
Versions []Version
|
|
||||||
}
|
|
||||||
|
|
||||||
// DatastorePartial is a meta structure which is used in various API responses.
|
|
||||||
// It is a lightweight and truncated version of a full Datastore resource,
|
|
||||||
// offering details of the Version, Type and VersionID only.
|
|
||||||
type DatastorePartial struct {
|
|
||||||
Version string
|
|
||||||
Type string
|
|
||||||
VersionID string `json:"version_id" mapstructure:"version_id"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetResult represents the result of a Get operation.
|
|
||||||
type GetResult struct {
|
|
||||||
gophercloud.Result
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetVersionResult represents the result of getting a version.
|
|
||||||
type GetVersionResult struct {
|
|
||||||
gophercloud.Result
|
|
||||||
}
|
|
||||||
|
|
||||||
// DatastorePage represents a page of datastore resources.
|
|
||||||
type DatastorePage struct {
|
|
||||||
pagination.SinglePageBase
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsEmpty indicates whether a Datastore collection is empty.
|
|
||||||
func (r DatastorePage) IsEmpty() (bool, error) {
|
|
||||||
is, err := ExtractDatastores(r)
|
|
||||||
if err != nil {
|
|
||||||
return true, err
|
|
||||||
}
|
|
||||||
return len(is) == 0, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExtractDatastores retrieves a slice of datastore structs from a paginated
|
|
||||||
// collection.
|
|
||||||
func ExtractDatastores(page pagination.Page) ([]Datastore, error) {
|
|
||||||
casted := page.(DatastorePage).Body
|
|
||||||
|
|
||||||
var resp struct {
|
|
||||||
Datastores []Datastore `mapstructure:"datastores" json:"datastores"`
|
|
||||||
}
|
|
||||||
|
|
||||||
err := mapstructure.Decode(casted, &resp)
|
|
||||||
return resp.Datastores, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract retrieves a single Datastore struct from an operation result.
|
|
||||||
func (r GetResult) Extract() (*Datastore, error) {
|
|
||||||
if r.Err != nil {
|
|
||||||
return nil, r.Err
|
|
||||||
}
|
|
||||||
|
|
||||||
var response struct {
|
|
||||||
Datastore Datastore `mapstructure:"datastore"`
|
|
||||||
}
|
|
||||||
|
|
||||||
err := mapstructure.Decode(r.Body, &response)
|
|
||||||
return &response.Datastore, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// DatastorePage represents a page of version resources.
|
|
||||||
type VersionPage struct {
|
|
||||||
pagination.SinglePageBase
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsEmpty indicates whether a collection of version resources is empty.
|
|
||||||
func (r VersionPage) IsEmpty() (bool, error) {
|
|
||||||
is, err := ExtractVersions(r)
|
|
||||||
if err != nil {
|
|
||||||
return true, err
|
|
||||||
}
|
|
||||||
return len(is) == 0, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExtractVersions retrieves a slice of versions from a paginated collection.
|
|
||||||
func ExtractVersions(page pagination.Page) ([]Version, error) {
|
|
||||||
casted := page.(VersionPage).Body
|
|
||||||
|
|
||||||
var resp struct {
|
|
||||||
Versions []Version `mapstructure:"versions" json:"versions"`
|
|
||||||
}
|
|
||||||
|
|
||||||
err := mapstructure.Decode(casted, &resp)
|
|
||||||
return resp.Versions, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract retrieves a single Version struct from an operation result.
|
|
||||||
func (r GetVersionResult) Extract() (*Version, error) {
|
|
||||||
if r.Err != nil {
|
|
||||||
return nil, r.Err
|
|
||||||
}
|
|
||||||
|
|
||||||
var response struct {
|
|
||||||
Version Version `mapstructure:"version"`
|
|
||||||
}
|
|
||||||
|
|
||||||
err := mapstructure.Decode(r.Body, &response)
|
|
||||||
return &response.Version, err
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue