mirror of
https://github.com/linuxkit/linuxkit.git
synced 2025-07-21 10:09:07 +00:00
[OpenStack] Support specifying an SSH key name when creating an instance
This commit introduces a new option - `keyname` - to the OpenStack runner, which allows the user to specify the name of a keypair they want to associate with the instance at the time of creation. Signed-off-by: Nick Jones <nick@dischord.org>
This commit is contained in:
parent
0968be802f
commit
0556812b63
@ -1,6 +1,6 @@
|
|||||||
# LinuxKit with OpenStack
|
# LinuxKit with OpenStack
|
||||||
|
|
||||||
LinuxKit interacts with OpenStack through its native APIs and requires access and provides basic support for pushing images and launching virtual instances.
|
LinuxKit interacts with OpenStack through its native APIs, providing basic support for pushing images and launching virtual instances.
|
||||||
|
|
||||||
Supported (tested) versions of the relevant OpenStack APIs are:
|
Supported (tested) versions of the relevant OpenStack APIs are:
|
||||||
|
|
||||||
@ -64,6 +64,7 @@ linuxkit run openstack \
|
|||||||
-username=admin \
|
-username=admin \
|
||||||
-password=xxx \
|
-password=xxx \
|
||||||
-project=linuxkit \
|
-project=linuxkit \
|
||||||
|
-keyname=deadline_ed25519 \
|
||||||
-network c5d02c5f-c625-4539-8aed-1dab3aa85a0a \
|
-network c5d02c5f-c625-4539-8aed-1dab3aa85a0a \
|
||||||
LinuxKitTest
|
LinuxKitTest
|
||||||
```
|
```
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
|
|
||||||
"github.com/gophercloud/gophercloud"
|
"github.com/gophercloud/gophercloud"
|
||||||
"github.com/gophercloud/gophercloud/openstack"
|
"github.com/gophercloud/gophercloud/openstack"
|
||||||
|
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/keypairs"
|
||||||
"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
|
"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
@ -35,6 +36,7 @@ func runOpenStack(args []string) {
|
|||||||
flavorName := flags.String("flavor", defaultOSFlavor, "Instance size (flavor)")
|
flavorName := flags.String("flavor", defaultOSFlavor, "Instance size (flavor)")
|
||||||
instanceName := flags.String("instancename", "", "Name of instance. Defaults to the name of the image if not specified")
|
instanceName := flags.String("instancename", "", "Name of instance. Defaults to the name of the image if not specified")
|
||||||
networkID := flags.String("network", "", "The ID of the network to attach the instance to")
|
networkID := flags.String("network", "", "The ID of the network to attach the instance to")
|
||||||
|
keyName := flags.String("keyname", "", "The name of the SSH keypair to associate with the instance")
|
||||||
passwordFlag := flags.String("password", "", "Password for the specified username")
|
passwordFlag := flags.String("password", "", "Password for the specified username")
|
||||||
projectNameFlag := flags.String("project", "", "Name of the Project (aka Tenant) to be used")
|
projectNameFlag := flags.String("project", "", "Name of the Project (aka Tenant) to be used")
|
||||||
userDomainFlag := flags.String("domain", "Default", "Domain name")
|
userDomainFlag := flags.String("domain", "Default", "Domain name")
|
||||||
@ -83,7 +85,9 @@ func runOpenStack(args []string) {
|
|||||||
UUID: *networkID,
|
UUID: *networkID,
|
||||||
}
|
}
|
||||||
|
|
||||||
serverOpts := &servers.CreateOpts{
|
var serverOpts servers.CreateOptsBuilder
|
||||||
|
|
||||||
|
serverOpts = &servers.CreateOpts{
|
||||||
FlavorName: *flavorName,
|
FlavorName: *flavorName,
|
||||||
ImageName: name,
|
ImageName: name,
|
||||||
Name: *instanceName,
|
Name: *instanceName,
|
||||||
@ -91,6 +95,13 @@ func runOpenStack(args []string) {
|
|||||||
ServiceClient: client,
|
ServiceClient: client,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if *keyName != "" {
|
||||||
|
serverOpts = &keypairs.CreateOptsExt{
|
||||||
|
CreateOptsBuilder: serverOpts,
|
||||||
|
KeyName: *keyName,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
server, err := servers.Create(client, serverOpts).Extract()
|
server, err := servers.Create(client, serverOpts).Extract()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Unable to create server: %s", err)
|
log.Fatalf("Unable to create server: %s", err)
|
||||||
|
3
src/cmd/linuxkit/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/keypairs/doc.go
generated
vendored
Normal file
3
src/cmd/linuxkit/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/keypairs/doc.go
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
// Package keypairs provides information and interaction with the Keypairs
|
||||||
|
// extension for the OpenStack Compute service.
|
||||||
|
package keypairs
|
84
src/cmd/linuxkit/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/keypairs/requests.go
generated
vendored
Normal file
84
src/cmd/linuxkit/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/keypairs/requests.go
generated
vendored
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
package keypairs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gophercloud/gophercloud"
|
||||||
|
"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
|
||||||
|
"github.com/gophercloud/gophercloud/pagination"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CreateOptsExt adds a KeyPair option to the base CreateOpts.
|
||||||
|
type CreateOptsExt struct {
|
||||||
|
servers.CreateOptsBuilder
|
||||||
|
KeyName string `json:"key_name,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToServerCreateMap adds the key_name and, optionally, key_data options 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 opts.KeyName == "" {
|
||||||
|
return base, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
serverMap := base["server"].(map[string]interface{})
|
||||||
|
serverMap["key_name"] = opts.KeyName
|
||||||
|
|
||||||
|
return base, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// List returns a Pager that allows you to iterate over a collection of KeyPairs.
|
||||||
|
func List(client *gophercloud.ServiceClient) pagination.Pager {
|
||||||
|
return pagination.NewPager(client, listURL(client), func(r pagination.PageResult) pagination.Page {
|
||||||
|
return KeyPairPage{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 {
|
||||||
|
ToKeyPairCreateMap() (map[string]interface{}, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateOpts specifies keypair creation or import parameters.
|
||||||
|
type CreateOpts struct {
|
||||||
|
// Name is a friendly name to refer to this KeyPair in other services.
|
||||||
|
Name string `json:"name" required:"true"`
|
||||||
|
// PublicKey [optional] is a pregenerated OpenSSH-formatted public key. If provided, this key
|
||||||
|
// will be imported and no new key will be created.
|
||||||
|
PublicKey string `json:"public_key,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToKeyPairCreateMap constructs a request body from CreateOpts.
|
||||||
|
func (opts CreateOpts) ToKeyPairCreateMap() (map[string]interface{}, error) {
|
||||||
|
return gophercloud.BuildRequestBody(opts, "keypair")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create requests the creation of a new keypair on the server, or to import a pre-existing
|
||||||
|
// keypair.
|
||||||
|
func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) {
|
||||||
|
b, err := opts.ToKeyPairCreateMap()
|
||||||
|
if err != nil {
|
||||||
|
r.Err = err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_, r.Err = client.Post(createURL(client), b, &r.Body, &gophercloud.RequestOpts{
|
||||||
|
OkCodes: []int{200},
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns public data about a previously uploaded KeyPair.
|
||||||
|
func Get(client *gophercloud.ServiceClient, name string) (r GetResult) {
|
||||||
|
_, r.Err = client.Get(getURL(client, name), &r.Body, nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete requests the deletion of a previous stored KeyPair from the server.
|
||||||
|
func Delete(client *gophercloud.ServiceClient, name string) (r DeleteResult) {
|
||||||
|
_, r.Err = client.Delete(deleteURL(client, name), nil)
|
||||||
|
return
|
||||||
|
}
|
86
src/cmd/linuxkit/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/keypairs/results.go
generated
vendored
Normal file
86
src/cmd/linuxkit/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/keypairs/results.go
generated
vendored
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
package keypairs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gophercloud/gophercloud"
|
||||||
|
"github.com/gophercloud/gophercloud/pagination"
|
||||||
|
)
|
||||||
|
|
||||||
|
// KeyPair is an SSH key known to the OpenStack Cloud that is available to be injected into
|
||||||
|
// servers.
|
||||||
|
type KeyPair struct {
|
||||||
|
// Name is used to refer to this keypair from other services within this region.
|
||||||
|
Name string `json:"name"`
|
||||||
|
|
||||||
|
// Fingerprint is a short sequence of bytes that can be used to authenticate or validate a longer
|
||||||
|
// public key.
|
||||||
|
Fingerprint string `json:"fingerprint"`
|
||||||
|
|
||||||
|
// PublicKey is the public key from this pair, in OpenSSH format. "ssh-rsa AAAAB3Nz..."
|
||||||
|
PublicKey string `json:"public_key"`
|
||||||
|
|
||||||
|
// PrivateKey is the private key from this pair, in PEM format.
|
||||||
|
// "-----BEGIN RSA PRIVATE KEY-----\nMIICXA..." It is only present if this keypair was just
|
||||||
|
// returned from a Create call
|
||||||
|
PrivateKey string `json:"private_key"`
|
||||||
|
|
||||||
|
// UserID is the user who owns this keypair.
|
||||||
|
UserID string `json:"user_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// KeyPairPage stores a single, only page of KeyPair results from a List call.
|
||||||
|
type KeyPairPage struct {
|
||||||
|
pagination.SinglePageBase
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsEmpty determines whether or not a KeyPairPage is empty.
|
||||||
|
func (page KeyPairPage) IsEmpty() (bool, error) {
|
||||||
|
ks, err := ExtractKeyPairs(page)
|
||||||
|
return len(ks) == 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExtractKeyPairs interprets a page of results as a slice of KeyPairs.
|
||||||
|
func ExtractKeyPairs(r pagination.Page) ([]KeyPair, error) {
|
||||||
|
type pair struct {
|
||||||
|
KeyPair KeyPair `json:"keypair"`
|
||||||
|
}
|
||||||
|
var s struct {
|
||||||
|
KeyPairs []pair `json:"keypairs"`
|
||||||
|
}
|
||||||
|
err := (r.(KeyPairPage)).ExtractInto(&s)
|
||||||
|
results := make([]KeyPair, len(s.KeyPairs))
|
||||||
|
for i, pair := range s.KeyPairs {
|
||||||
|
results[i] = pair.KeyPair
|
||||||
|
}
|
||||||
|
return results, err
|
||||||
|
}
|
||||||
|
|
||||||
|
type keyPairResult struct {
|
||||||
|
gophercloud.Result
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract is a method that attempts to interpret any KeyPair resource response as a KeyPair struct.
|
||||||
|
func (r keyPairResult) Extract() (*KeyPair, error) {
|
||||||
|
var s struct {
|
||||||
|
KeyPair *KeyPair `json:"keypair"`
|
||||||
|
}
|
||||||
|
err := r.ExtractInto(&s)
|
||||||
|
return s.KeyPair, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateResult is the response from a Create operation. Call its Extract method to interpret it
|
||||||
|
// as a KeyPair.
|
||||||
|
type CreateResult struct {
|
||||||
|
keyPairResult
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetResult is the response from a Get operation. Call its Extract method to interpret it
|
||||||
|
// as a KeyPair.
|
||||||
|
type GetResult struct {
|
||||||
|
keyPairResult
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
25
src/cmd/linuxkit/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/keypairs/urls.go
generated
vendored
Normal file
25
src/cmd/linuxkit/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/keypairs/urls.go
generated
vendored
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
package keypairs
|
||||||
|
|
||||||
|
import "github.com/gophercloud/gophercloud"
|
||||||
|
|
||||||
|
const resourcePath = "os-keypairs"
|
||||||
|
|
||||||
|
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, name string) string {
|
||||||
|
return c.ServiceURL(resourcePath, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func deleteURL(c *gophercloud.ServiceClient, name string) string {
|
||||||
|
return getURL(c, name)
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user