diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index e524aaa4a6..da45a42e9b 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -293,7 +293,7 @@ }, { "ImportPath": "github.com/pyr/egoscale/src/egoscale", - "Rev": "bbaa67324aeeacc90430c1fe0a9c620d3929512e" + "Rev": "347f81398d2ea1f3eebf1cd27ee3183669e34819" }, { "ImportPath": "github.com/rackspace/gophercloud", diff --git a/docs/drivers/exoscale.md b/docs/drivers/exoscale.md index 87d0fd0b17..3aed5be770 100644 --- a/docs/drivers/exoscale.md +++ b/docs/drivers/exoscale.md @@ -25,7 +25,9 @@ Options: - `--exoscale-disk-size`: Disk size for the host in GB (10, 50, 100, 200, 400). - `--exoscale-image`: Image template (eg. ubuntu-14.04, ubuntu-15.10). - `--exoscale-security-group`: Security group. It will be created if it doesn't exist. -- `--exoscale-availability-zone`: exoscale availability zone. +- `--exoscale-availability-zone`: Exoscale availability zone. +- `--exoscale-ssh-user`: SSH username, which must match the default SSH user for the used image. +- `--exoscale-userdata`: Path to file containing user data for cloud-init. If a custom security group is provided, you need to ensure that you allow TCP ports 22 and 2376 in an ingress rule. Moreover, if you want to use Swarm, also add TCP port 3376. @@ -41,3 +43,5 @@ Environment variables and default values: | `--exoscale-image` | `EXOSCALE_IMAGE` | `ubuntu-15.10` | | `--exoscale-security-group` | `EXOSCALE_SECURITY_GROUP` | `docker-machine` | | `--exoscale-availability-zone` | `EXOSCALE_AVAILABILITY_ZONE` | `ch-gva-2` | +| `--exoscale-ssh-user` | `EXOSCALE_SSH_USER` | `ubuntu` | +| `--exoscale-userdata` | `EXOSCALE_USERDATA` | - | diff --git a/drivers/exoscale/exoscale.go b/drivers/exoscale/exoscale.go index dc88172f66..f9540066f7 100644 --- a/drivers/exoscale/exoscale.go +++ b/drivers/exoscale/exoscale.go @@ -1,12 +1,11 @@ package exoscale import ( - "bytes" "fmt" "io/ioutil" "net" + "os" "strings" - "text/template" "time" "github.com/docker/machine/libmachine/drivers" @@ -29,6 +28,7 @@ type Driver struct { AvailabilityZone string KeyPair string PublicKey string + UserDataFile string ID string `json:"Id"` } @@ -37,6 +37,7 @@ const ( defaultDiskSize = 50 defaultImage = "ubuntu-15.10" defaultAvailabilityZone = "ch-gva-2" + defaultSSHUser = "ubuntu" ) // GetCreateFlags registers the flags this driver adds to @@ -88,6 +89,17 @@ func (d *Driver) GetCreateFlags() []mcnflag.Flag { Value: defaultAvailabilityZone, Usage: "exoscale availibility zone", }, + mcnflag.StringFlag{ + EnvVar: "EXOSCALE_SSH_USER", + Name: "exoscale-ssh-user", + Value: defaultSSHUser, + Usage: "Set the name of the ssh user", + }, + mcnflag.StringFlag{ + EnvVar: "EXOSCALE_USERDATA", + Name: "exoscale-userdata", + Usage: "path to file with cloud-init user-data", + }, } } @@ -109,7 +121,11 @@ func (d *Driver) GetSSHHostname() (string, error) { } func (d *Driver) GetSSHUsername() string { - return "ubuntu" + if d.SSHUser == "" { + d.SSHUser = defaultSSHUser + } + + return d.SSHUser } // DriverName returns the name of the driver @@ -130,6 +146,8 @@ func (d *Driver) SetConfigFromFlags(flags drivers.DriverOptions) error { } d.SecurityGroup = strings.Join(securityGroups, ",") d.AvailabilityZone = flags.String("exoscale-availability-zone") + d.SSHUser = flags.String("exoscale-ssh-user") + d.UserDataFile = flags.String("exoscale-userdata") d.SetSwarmConfigFromFlags(flags) if d.URL == "" { @@ -142,6 +160,16 @@ func (d *Driver) SetConfigFromFlags(flags drivers.DriverOptions) error { return nil } +func (d *Driver) PreCreateCheck() error { + if d.UserDataFile != "" { + if _, err := os.Stat(d.UserDataFile); os.IsNotExist(err) { + return fmt.Errorf("user-data file %s could not be found", d.UserDataFile) + } + } + + return nil +} + func (d *Driver) GetURL() (string, error) { if err := drivers.MustBeRunning(d); err != nil { return "", err @@ -226,6 +254,11 @@ func (d *Driver) createDefaultSecurityGroup(client *egoscale.Client, group strin } func (d *Driver) Create() error { + userdata, err := d.getCloudInit() + if err != nil { + return err + } + log.Infof("Querying exoscale for the requested parameters...") client := egoscale.NewClient(d.URL, d.APIKey, d.APISecretKey) topology, err := client.GetTopology() @@ -291,11 +324,6 @@ func (d *Driver) Create() error { d.KeyPair = keypairName log.Infof("Spawn exoscale host...") - - userdata, err := d.getCloudInit() - if err != nil { - return err - } log.Debugf("Using the following cloud-init file:") log.Debugf("%s", userdata) @@ -422,20 +450,15 @@ func (d *Driver) waitForVM(client *egoscale.Client, jobid string) (*egoscale.Dep // Build a cloud-init user data string that will install and run // docker. func (d *Driver) getCloudInit() (string, error) { - const tpl = `#cloud-config -manage_etc_hosts: true -fqdn: {{ .MachineName }} -resize_rootfs: true -` - var buffer bytes.Buffer + if d.UserDataFile != "" { + buf, err := ioutil.ReadFile(d.UserDataFile) + if err != nil { + return "", err + } + return string(buf), nil + } - tmpl, err := template.New("cloud-init").Parse(tpl) - if err != nil { - return "", err - } - err = tmpl.Execute(&buffer, d) - if err != nil { - return "", err - } - return buffer.String(), nil + return `#cloud-config +manage_etc_hosts: true +`, nil } diff --git a/vendor/github.com/pyr/egoscale/src/egoscale/topology.go b/vendor/github.com/pyr/egoscale/src/egoscale/topology.go index 080788d97e..5eb7b4761d 100644 --- a/vendor/github.com/pyr/egoscale/src/egoscale/topology.go +++ b/vendor/github.com/pyr/egoscale/src/egoscale/topology.go @@ -114,12 +114,12 @@ func (exo *Client) GetImages() (map[string]map[int]string, error) { return nil, err } - re := regexp.MustCompile(`^Linux (?PUbuntu|Debian) (?P[0-9.]+).*$`) + re := regexp.MustCompile(`^Linux (?P.+?) (?P[0-9.]+).*$`) for _, template := range r.Templates { size := int(template.Size / (1024 * 1024 * 1024)) submatch := re.FindStringSubmatch(template.Name) if len(submatch) > 0 { - name := strings.ToLower(submatch[1]) + name := strings.Replace(strings.ToLower(submatch[1]), " ", "-", -1) version := submatch[2] image := fmt.Sprintf("%s-%s", name, version)