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 <Vincent.Bernat@exoscale.ch>
This commit is contained in:
Vincent Bernat 2015-06-05 10:23:37 +02:00
parent 471968b039
commit 5ba232227e
2 changed files with 58 additions and 43 deletions

View File

@ -1174,7 +1174,7 @@ Options:
- `--exoscale-instance-profile`: Instance profile. - `--exoscale-instance-profile`: Instance profile.
- `--exoscale-disk-size`: Disk size for the host in GB. - `--exoscale-disk-size`: Disk size for the host in GB.
- `--exoscale-image`: exoscale disk size. (10, 50, 100, 200, 400) - `--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. - `--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. 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.

View File

@ -24,7 +24,7 @@ type Driver struct {
InstanceProfile string InstanceProfile string
DiskSize int DiskSize int
Image string Image string
SecurityGroup string SecurityGroups []string
AvailabilityZone string AvailabilityZone string
MachineName string MachineName string
KeyPair string KeyPair string
@ -142,7 +142,9 @@ func (d *Driver) SetConfigFromFlags(flags drivers.DriverOptions) error {
d.InstanceProfile = flags.String("exoscale-instance-profile") d.InstanceProfile = flags.String("exoscale-instance-profile")
d.DiskSize = flags.Int("exoscale-disk-size") d.DiskSize = flags.Int("exoscale-disk-size")
d.Image = flags.String("exoscale-image") 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.AvailabilityZone = flags.String("exoscale-availability-zone")
d.SwarmMaster = flags.Bool("swarm-master") d.SwarmMaster = flags.Bool("swarm-master")
d.SwarmHost = flags.String("swarm-host") d.SwarmHost = flags.String("swarm-host")
@ -208,6 +210,45 @@ func (d *Driver) PreCreateCheck() error {
return nil 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 { func (d *Driver) Create() error {
log.Infof("Querying exoscale for the requested parameters...") log.Infof("Querying exoscale for the requested parameters...")
client := egoscale.NewClient(d.URL, d.ApiKey, d.ApiSecretKey) 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) log.Debugf("Profile %v = %s", d.InstanceProfile, profile)
// Security group // Security groups
sg, ok := topology.SecurityGroups[d.SecurityGroup] sgs := make([]string, len(d.SecurityGroups))
for idx, group := range d.SecurityGroups {
sg, ok := topology.SecurityGroups[group]
if !ok { if !ok {
log.Infof("Security group %v does not exist, create it", log.Infof("Security group %v does not exist, create it",
d.SecurityGroup) group)
rules := []egoscale.SecurityGroupRule{ sg, err = d.createDefaultSecurityGroup(client, group)
{
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(d.SecurityGroup,
rules,
make([]egoscale.SecurityGroupRule, 0, 0))
if err != nil { if err != nil {
return err return err
} }
sg = sgresp.Id
} }
log.Debugf("Security group %v = %s", d.SecurityGroup, sg) log.Debugf("Security group %v = %s", group, sg)
sgs[idx] = sg
}
log.Infof("Generate an SSH keypair...") log.Infof("Generate an SSH keypair...")
keypairName := fmt.Sprintf("docker-machine-%s", d.MachineName) keypairName := fmt.Sprintf("docker-machine-%s", d.MachineName)
@ -310,7 +325,7 @@ func (d *Driver) Create() error {
machineProfile := egoscale.MachineProfile{ machineProfile := egoscale.MachineProfile{
Template: tpl, Template: tpl,
ServiceOffering: profile, ServiceOffering: profile,
SecurityGroups: []string{sg}, SecurityGroups: sgs,
Userdata: userdata, Userdata: userdata,
Zone: zone, Zone: zone,
Keypair: d.KeyPair, Keypair: d.KeyPair,