mirror of https://github.com/docker/docs.git
Initial cut at a Rackspace driver.
* Wrap openstack.Client in an interface. * Alternate openstack Driver creation method. * Register the Rackspace driver in commands.go. Signed-off-by: Ash Wilson <ash.wilson@rackspace.com>
This commit is contained in:
parent
0f02ebe6f2
commit
c12d3f8ecd
|
@ -19,6 +19,7 @@ import (
|
|||
_ "github.com/docker/machine/drivers/google"
|
||||
_ "github.com/docker/machine/drivers/none"
|
||||
_ "github.com/docker/machine/drivers/openstack"
|
||||
_ "github.com/docker/machine/drivers/rackspace"
|
||||
_ "github.com/docker/machine/drivers/virtualbox"
|
||||
_ "github.com/docker/machine/drivers/vmwarefusion"
|
||||
_ "github.com/docker/machine/drivers/vmwarevcloudair"
|
||||
|
|
|
@ -15,13 +15,27 @@ import (
|
|||
"github.com/rackspace/gophercloud/pagination"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
type Client interface {
|
||||
CreateInstance(d *Driver) (string, error)
|
||||
GetInstanceState(d *Driver) (string, error)
|
||||
StartInstance(d *Driver) error
|
||||
StopInstance(d *Driver) error
|
||||
RestartInstance(d *Driver) error
|
||||
DeleteInstance(d *Driver) error
|
||||
WaitForInstanceStatus(d *Driver, status string, timeout int) error
|
||||
GetInstanceIpAddresses(d *Driver) ([]IpAddress, error)
|
||||
CreateKeyPair(d *Driver, name string, publicKey string) error
|
||||
DeleteKeyPair(d *Driver, name string) error
|
||||
Authenticate(d *Driver) error
|
||||
}
|
||||
|
||||
type GenericClient struct {
|
||||
Provider *gophercloud.ProviderClient
|
||||
Compute *gophercloud.ServiceClient
|
||||
Network *gophercloud.ServiceClient
|
||||
}
|
||||
|
||||
func (c *Client) CreateInstance(d *Driver) (string, error) {
|
||||
func (c *GenericClient) CreateInstance(d *Driver) (string, error) {
|
||||
if err := c.initComputeClient(d); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -60,7 +74,7 @@ type IpAddress struct {
|
|||
Mac string
|
||||
}
|
||||
|
||||
func (c *Client) GetInstanceState(d *Driver) (string, error) {
|
||||
func (c *GenericClient) GetInstanceState(d *Driver) (string, error) {
|
||||
server, err := c.getServerDetail(d)
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
@ -73,7 +87,7 @@ func (c *Client) GetInstanceState(d *Driver) (string, error) {
|
|||
return server.Status, nil
|
||||
}
|
||||
|
||||
func (c *Client) StartInstance(d *Driver) error {
|
||||
func (c *GenericClient) StartInstance(d *Driver) error {
|
||||
if err := c.initComputeClient(d); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -83,7 +97,7 @@ func (c *Client) StartInstance(d *Driver) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) StopInstance(d *Driver) error {
|
||||
func (c *GenericClient) StopInstance(d *Driver) error {
|
||||
if err := c.initComputeClient(d); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -93,7 +107,7 @@ func (c *Client) StopInstance(d *Driver) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) RestartInstance(d *Driver) error {
|
||||
func (c *GenericClient) RestartInstance(d *Driver) error {
|
||||
if err := c.initComputeClient(d); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -103,7 +117,7 @@ func (c *Client) RestartInstance(d *Driver) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) DeleteInstance(d *Driver) error {
|
||||
func (c *GenericClient) DeleteInstance(d *Driver) error {
|
||||
if err := c.initComputeClient(d); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -113,14 +127,14 @@ func (c *Client) DeleteInstance(d *Driver) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) WaitForInstanceStatus(d *Driver, status string, timeout int) error {
|
||||
func (c *GenericClient) WaitForInstanceStatus(d *Driver, status string, timeout int) error {
|
||||
if err := servers.WaitForStatus(c.Compute, d.MachineId, status, timeout); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) GetInstanceIpAddresses(d *Driver) ([]IpAddress, error) {
|
||||
func (c *GenericClient) GetInstanceIpAddresses(d *Driver) ([]IpAddress, error) {
|
||||
server, err := c.getServerDetail(d)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -140,7 +154,7 @@ func (c *Client) GetInstanceIpAddresses(d *Driver) ([]IpAddress, error) {
|
|||
return addresses, nil
|
||||
}
|
||||
|
||||
func (c *Client) GetNetworkId(d *Driver, networkName string) (string, error) {
|
||||
func (c *GenericClient) GetNetworkId(d *Driver, networkName string) (string, error) {
|
||||
if err := c.initNetworkClient(d); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -168,7 +182,7 @@ func (c *Client) GetNetworkId(d *Driver, networkName string) (string, error) {
|
|||
return networkId, err
|
||||
}
|
||||
|
||||
func (c *Client) GetFlavorId(d *Driver, flavorName string) (string, error) {
|
||||
func (c *GenericClient) GetFlavorId(d *Driver, flavorName string) (string, error) {
|
||||
if err := c.initComputeClient(d); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -195,7 +209,7 @@ func (c *Client) GetFlavorId(d *Driver, flavorName string) (string, error) {
|
|||
return flavorId, err
|
||||
}
|
||||
|
||||
func (c *Client) GetImageId(d *Driver, imageName string) (string, error) {
|
||||
func (c *GenericClient) GetImageId(d *Driver, imageName string) (string, error) {
|
||||
if err := c.initComputeClient(d); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -223,7 +237,7 @@ func (c *Client) GetImageId(d *Driver, imageName string) (string, error) {
|
|||
return imageId, err
|
||||
}
|
||||
|
||||
func (c *Client) CreateKeyPair(d *Driver, name string, publicKey string) error {
|
||||
func (c *GenericClient) CreateKeyPair(d *Driver, name string, publicKey string) error {
|
||||
if err := c.initComputeClient(d); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -237,7 +251,7 @@ func (c *Client) CreateKeyPair(d *Driver, name string, publicKey string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) DeleteKeyPair(d *Driver, name string) error {
|
||||
func (c *GenericClient) DeleteKeyPair(d *Driver, name string) error {
|
||||
if err := c.initComputeClient(d); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -247,7 +261,7 @@ func (c *Client) DeleteKeyPair(d *Driver, name string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) getServerDetail(d *Driver) (*servers.Server, error) {
|
||||
func (c *GenericClient) getServerDetail(d *Driver) (*servers.Server, error) {
|
||||
if err := c.initComputeClient(d); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -258,7 +272,7 @@ func (c *Client) getServerDetail(d *Driver) (*servers.Server, error) {
|
|||
return server, nil
|
||||
}
|
||||
|
||||
func (c *Client) getFloatingIPs(d *Driver) ([]string, error) {
|
||||
func (c *GenericClient) getFloatingIPs(d *Driver) ([]string, error) {
|
||||
|
||||
if err := c.initNetworkClient(d); err != nil {
|
||||
return nil, err
|
||||
|
@ -283,7 +297,7 @@ func (c *Client) getFloatingIPs(d *Driver) ([]string, error) {
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
func (c *Client) getPorts(d *Driver) ([]string, error) {
|
||||
func (c *GenericClient) getPorts(d *Driver) ([]string, error) {
|
||||
|
||||
if err := c.initNetworkClient(d); err != nil {
|
||||
return nil, err
|
||||
|
@ -310,7 +324,7 @@ func (c *Client) getPorts(d *Driver) ([]string, error) {
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
func (c *Client) initComputeClient(d *Driver) error {
|
||||
func (c *GenericClient) initComputeClient(d *Driver) error {
|
||||
if c.Provider == nil {
|
||||
err := c.Authenticate(d)
|
||||
if err != nil {
|
||||
|
@ -328,7 +342,7 @@ func (c *Client) initComputeClient(d *Driver) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) initNetworkClient(d *Driver) error {
|
||||
func (c *GenericClient) initNetworkClient(d *Driver) error {
|
||||
if c.Provider == nil {
|
||||
err := c.Authenticate(d)
|
||||
if err != nil {
|
||||
|
@ -346,7 +360,7 @@ func (c *Client) initNetworkClient(d *Driver) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) getEndpointType(d *Driver) gophercloud.Availability {
|
||||
func (c *GenericClient) getEndpointType(d *Driver) gophercloud.Availability {
|
||||
switch d.EndpointType {
|
||||
case "internalURL":
|
||||
return gophercloud.AvailabilityInternal
|
||||
|
@ -356,7 +370,7 @@ func (c *Client) getEndpointType(d *Driver) gophercloud.Availability {
|
|||
return gophercloud.AvailabilityPublic
|
||||
}
|
||||
|
||||
func (c *Client) Authenticate(d *Driver) error {
|
||||
func (c *GenericClient) Authenticate(d *Driver) error {
|
||||
log.WithFields(log.Fields{
|
||||
"AuthUrl": d.AuthUrl,
|
||||
"Username": d.Username,
|
||||
|
|
|
@ -38,7 +38,7 @@ type Driver struct {
|
|||
SSHUser string
|
||||
SSHPort int
|
||||
storePath string
|
||||
client *Client
|
||||
client Client
|
||||
}
|
||||
|
||||
type CreateFlags struct {
|
||||
|
@ -159,12 +159,16 @@ func RegisterCreateFlags(cmd *flag.FlagSet) interface{} {
|
|||
}
|
||||
|
||||
func NewDriver(storePath string) (drivers.Driver, error) {
|
||||
return NewDerivedDriver(storePath, &GenericClient{})
|
||||
}
|
||||
|
||||
func NewDerivedDriver(storePath string, client Client) (*Driver, error) {
|
||||
log.WithFields(log.Fields{
|
||||
"storePath": storePath,
|
||||
}).Debug("Instanciate OpenStack driver...")
|
||||
}).Debug("Instantiating OpenStack driver...")
|
||||
return &Driver{
|
||||
storePath: storePath,
|
||||
client: &Client{},
|
||||
client: client,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
package rackspace
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
log "github.com/Sirupsen/logrus"
|
||||
"github.com/docker/machine/drivers/openstack"
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/rackspace"
|
||||
)
|
||||
|
||||
func unsupportedOpErr(operation string) error {
|
||||
return fmt.Errorf("Rackspace does not currently support the %s operation", operation)
|
||||
}
|
||||
|
||||
// Client is a Rackspace specialization of the generic OpenStack driver.
|
||||
type Client struct {
|
||||
openstack.GenericClient
|
||||
|
||||
driver *Driver
|
||||
}
|
||||
|
||||
// Authenticate creates a Rackspace-specific Gophercloud client.
|
||||
func (c *Client) Authenticate(d *openstack.Driver) error {
|
||||
log.WithFields(log.Fields{
|
||||
"Username": d.Username,
|
||||
}).Info("Authenticating...")
|
||||
|
||||
apiKey := c.driver.APIKey
|
||||
opts := gophercloud.AuthOptions{
|
||||
Username: d.Username,
|
||||
APIKey: apiKey,
|
||||
}
|
||||
|
||||
provider, err := rackspace.AuthenticatedClient(opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.Provider = provider
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// StartInstance is unfortunately not supported on Rackspace at this time.
|
||||
func (c *Client) StartInstance(d *openstack.Driver) error {
|
||||
return unsupportedOpErr("start")
|
||||
}
|
||||
|
||||
// StopInstance is unfortunately not support on Rackspace at this time.
|
||||
func (c *Client) StopInstance(d *openstack.Driver) error {
|
||||
return unsupportedOpErr("stop")
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
package rackspace
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
log "github.com/Sirupsen/logrus"
|
||||
flag "github.com/docker/docker/pkg/mflag"
|
||||
"github.com/docker/machine/drivers"
|
||||
"github.com/docker/machine/drivers/openstack"
|
||||
)
|
||||
|
||||
// Driver is a machine driver for Rackspace. It's a specialization of the generic OpenStack one.
|
||||
type Driver struct {
|
||||
drivers.Driver
|
||||
|
||||
APIKey string
|
||||
}
|
||||
|
||||
// CreateFlags stores the command-line arguments given to "machine create".
|
||||
type CreateFlags struct {
|
||||
Username *string
|
||||
APIKey *string
|
||||
Region *string
|
||||
MachineName *string
|
||||
EndpointType *string
|
||||
ImageID *string
|
||||
FlavorID *string
|
||||
SSHUser *string
|
||||
SSHPort *int
|
||||
}
|
||||
|
||||
func init() {
|
||||
drivers.Register("rackspace", &drivers.RegisteredDriver{
|
||||
New: NewDriver,
|
||||
RegisterCreateFlags: RegisterCreateFlags,
|
||||
})
|
||||
}
|
||||
|
||||
// RegisterCreateFlags registers the "machine create" flags recognized by this driver, including
|
||||
// their help text and defaults.
|
||||
func RegisterCreateFlags(cmd *flag.FlagSet) interface{} {
|
||||
createFlags := new(CreateFlags)
|
||||
createFlags.Username = cmd.String(
|
||||
[]string{"-rackspace-username"},
|
||||
os.Getenv("OS_USERNAME"),
|
||||
"Rackspace account username",
|
||||
)
|
||||
createFlags.APIKey = cmd.String(
|
||||
[]string{"-rackspace-api-key"},
|
||||
os.Getenv("OS_API_KEY"),
|
||||
"Rackspace API key",
|
||||
)
|
||||
createFlags.Region = cmd.String(
|
||||
[]string{"-rackspace-region"},
|
||||
os.Getenv("OS_REGION_NAME"),
|
||||
"Rackspace region name",
|
||||
)
|
||||
createFlags.EndpointType = cmd.String(
|
||||
[]string{"-rackspace-endpoint-type"},
|
||||
os.Getenv("OS_ENDPOINT_TYPE"),
|
||||
"Rackspace endpoint type (adminURL, internalURL or the default publicURL)",
|
||||
)
|
||||
createFlags.ImageID = cmd.String(
|
||||
[]string{"-rackspace-image-id"},
|
||||
"",
|
||||
"Rackspace image ID. Default: Ubuntu 14.10 (Utopic Unicorn) (PVHVM)",
|
||||
)
|
||||
createFlags.FlavorID = cmd.String(
|
||||
[]string{"-rackspace-flavor-id"},
|
||||
"general1-1",
|
||||
"Rackspace flavor ID. Default: General Purpose 1GB",
|
||||
)
|
||||
createFlags.SSHUser = cmd.String(
|
||||
[]string{"-rackspace-ssh-user"},
|
||||
"root",
|
||||
"SSH user for the newly booted machine. Set to root by default",
|
||||
)
|
||||
createFlags.SSHPort = cmd.Int(
|
||||
[]string{"-rackspace-ssh-port"},
|
||||
22,
|
||||
"SSH port for the newly booted machine. Set to 22 by default",
|
||||
)
|
||||
return createFlags
|
||||
}
|
||||
|
||||
// NewDriver instantiates a Rackspace driver.
|
||||
func NewDriver(storePath string) (drivers.Driver, error) {
|
||||
log.WithFields(log.Fields{
|
||||
"storePath": storePath,
|
||||
}).Info("Instantiating Rackspace driver.")
|
||||
|
||||
client := &Client{}
|
||||
inner, err := openstack.NewDerivedDriver(storePath, &Client{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
driver := &Driver{Driver: inner}
|
||||
client.driver = driver
|
||||
return driver, nil
|
||||
}
|
Loading…
Reference in New Issue