From 5ba232227efbbf1854ac958b09bb6038fc254d88 Mon Sep 17 00:00:00 2001 From: Vincent Bernat Date: Fri, 5 Jun 2015 10:23:37 +0200 Subject: [PATCH] exoscale: ability to specify multiple security groups on instance creation Without this feature, when a user needs a specific security group (i.e most of the time if they want to expose a service to Internet), they need to copy the rules needed for Docker itself into each custom group. With this feature, they can spawn new instances with `--exoscale-security-group docker-machine,my-custom-group`. Signed-off-by: Vincent Bernat --- docs/index.md | 2 +- drivers/exoscale/exoscale.go | 99 +++++++++++++++++++++--------------- 2 files changed, 58 insertions(+), 43 deletions(-) diff --git a/docs/index.md b/docs/index.md index c7918ed995..960c94b6d9 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1174,7 +1174,7 @@ Options: - `--exoscale-instance-profile`: Instance profile. - `--exoscale-disk-size`: Disk size for the host in GB. - `--exoscale-image`: exoscale disk size. (10, 50, 100, 200, 400) - - `--exoscale-security-group`: Security group. It will be created if it doesn't exist. + - `--exoscale-security-group`: Comma-separated list of security groups. Non-existent groups will be created. - `--exoscale-availability-zone`: exoscale availability zone. 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. diff --git a/drivers/exoscale/exoscale.go b/drivers/exoscale/exoscale.go index 5a62d3cdda..5002af1bbb 100644 --- a/drivers/exoscale/exoscale.go +++ b/drivers/exoscale/exoscale.go @@ -24,7 +24,7 @@ type Driver struct { InstanceProfile string DiskSize int Image string - SecurityGroup string + SecurityGroups []string AvailabilityZone string MachineName string KeyPair string @@ -142,7 +142,9 @@ func (d *Driver) SetConfigFromFlags(flags drivers.DriverOptions) error { d.InstanceProfile = flags.String("exoscale-instance-profile") d.DiskSize = flags.Int("exoscale-disk-size") d.Image = flags.String("exoscale-image") - d.SecurityGroup = flags.String("exoscale-security-group") + if flags.String("exoscale-security-group") != "" { + d.SecurityGroups = strings.Split(flags.String("exoscale-security-group"), ",") + } d.AvailabilityZone = flags.String("exoscale-availability-zone") d.SwarmMaster = flags.Bool("swarm-master") d.SwarmHost = flags.String("swarm-host") @@ -208,6 +210,45 @@ func (d *Driver) PreCreateCheck() error { return nil } +func (d *Driver) createDefaultSecurityGroup(client *egoscale.Client, group string) (string, error) { + rules := []egoscale.SecurityGroupRule{ + { + SecurityGroupId: "", + Cidr: "0.0.0.0/0", + Protocol: "TCP", + Port: 22, + }, + { + SecurityGroupId: "", + Cidr: "0.0.0.0/0", + Protocol: "TCP", + Port: 2376, + }, + { + SecurityGroupId: "", + Cidr: "0.0.0.0/0", + Protocol: "TCP", + Port: 3376, + }, + { + SecurityGroupId: "", + Cidr: "0.0.0.0/0", + Protocol: "ICMP", + IcmpType: 8, + IcmpCode: 0, + }, + } + sgresp, err := client.CreateSecurityGroupWithRules( + group, + rules, + make([]egoscale.SecurityGroupRule, 0, 0)) + if err != nil { + return "", err + } + sg := sgresp.Id + return sg, nil +} + func (d *Driver) Create() error { log.Infof("Querying exoscale for the requested parameters...") client := egoscale.NewClient(d.URL, d.ApiKey, d.ApiSecretKey) @@ -244,47 +285,21 @@ func (d *Driver) Create() error { } log.Debugf("Profile %v = %s", d.InstanceProfile, profile) - // Security group - sg, ok := topology.SecurityGroups[d.SecurityGroup] - if !ok { - log.Infof("Security group %v does not exist, create it", - d.SecurityGroup) - rules := []egoscale.SecurityGroupRule{ - { - SecurityGroupId: "", - Cidr: "0.0.0.0/0", - Protocol: "TCP", - Port: 22, - }, - { - SecurityGroupId: "", - Cidr: "0.0.0.0/0", - Protocol: "TCP", - Port: 2376, - }, - { - SecurityGroupId: "", - Cidr: "0.0.0.0/0", - Protocol: "TCP", - Port: 3376, - }, - { - SecurityGroupId: "", - Cidr: "0.0.0.0/0", - Protocol: "ICMP", - IcmpType: 8, - IcmpCode: 0, - }, + // Security groups + sgs := make([]string, len(d.SecurityGroups)) + for idx, group := range d.SecurityGroups { + sg, ok := topology.SecurityGroups[group] + if !ok { + log.Infof("Security group %v does not exist, create it", + group) + sg, err = d.createDefaultSecurityGroup(client, group) + if err != nil { + return err + } } - sgresp, err := client.CreateSecurityGroupWithRules(d.SecurityGroup, - rules, - make([]egoscale.SecurityGroupRule, 0, 0)) - if err != nil { - return err - } - sg = sgresp.Id + log.Debugf("Security group %v = %s", group, sg) + sgs[idx] = sg } - log.Debugf("Security group %v = %s", d.SecurityGroup, sg) log.Infof("Generate an SSH keypair...") keypairName := fmt.Sprintf("docker-machine-%s", d.MachineName) @@ -310,7 +325,7 @@ func (d *Driver) Create() error { machineProfile := egoscale.MachineProfile{ Template: tpl, ServiceOffering: profile, - SecurityGroups: []string{sg}, + SecurityGroups: sgs, Userdata: userdata, Zone: zone, Keypair: d.KeyPair,